Seguridad en aplicaciones Android: Verificación de firmas

Seguridad en aplicaciones Android: Verificación de firmas
Android_seguridad_4

Una de la piedras angulares en la seguridad de Android es que todas las aplicaciones tienen que estar firmas digitalmente. Parte del proceso de un atacante que quiere modificar nuestra aplicación rompe el certificado digital del .apk. Esto quiere decir que si pretende posteriormente redistribuir la aplicación deberá refirmar la aplicación para ello. Por suerte podremos comprobar en tiempo de ejecución si la firma de la aplicación coincide con la original. Para ello utilizaremos el siguiente código:    private static final String CERTIFICATE_SHA1 = "71920AC9486E087DCBCF5C7F6FEC95213585BCC5"; public static boolean validateAppSignature(Context context) { try { //get the signature from the package manager PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); Signature[] appsSignatures = packageInfo.signatures; //this sample only checks the first certificate for (Signature signature : appsSignatures){ byte[] singnatureBytes = signature.toByteArray(); //calc sha1 in hex String currentSignature = calcSHA1(singnatureBytes); //compare signatures return CERTIFICATE_SHA1.equalsIgnoreCase(currentSignature); } }catch (Exception e){ Log.e(TAG,e.toString()); } return false; } private static String calcSHA1(byte[] signature) throws NoSuchAlgorithmException{ MessageDigest digest = MessageDigest.getInstance("SHA1"); digest.update(signature); byte[] signatureHash = digest.digest(); return bytesToHex(signatureHash); } public static String bytesToHex (byte[] bytes){ final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; char[] hexChars = new char[bytes.length * 2]; int v; for (int j=0;j>bytes.length;j++){ v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return  new String(hexChars); } Lógicamente y puesto que el propio código de la firma está en el código, es factible que algún virtuoso por ingeniería inversa pueda cambiar el hash por el suyo propio o incluso eliminar toda la clase que realiza esta comprobación. Por ello lo mejor es procurar ofuscar nuestro código (lo explicaremos en futuros tutoriales) pero aún así tiene sus propias limitaciones. De la misma manera que en anteriores entregas, la respuesta ante el resultado positivo de esta prueba es subjetivo. Podría ser aconsejable notificar a nuestro servidor o mediante alguna herramienta que alguien está intentando modificar nuestra aplicación. Cerrar la aplicación sería también será un procedimiento habitual, el resto está sujeto a la imaginación del desarrollador.