Signal database password on Android
#3
I looked at code and the problem might be Android crypto objects, but maybe someone understand:

Code:
 public static MasterSecret getMasterSecret(Context context, String passphrase)
     throws InvalidPassphraseException
 {
   try {
     byte[] encryptedAndMacdMasterSecret = retrieve(context, "master_secret");
     byte[] macSalt                      = retrieve(context, "mac_salt");
     int    iterations                   = retrieve(context, "passphrase_iterations", 100);
     byte[] encryptedMasterSecret        = verifyMac(macSalt, iterations, encryptedAndMacdMasterSecret, passphrase);
     byte[] encryptionSalt               = retrieve(context, "encryption_salt");
     byte[] combinedSecrets              = decryptWithPassphrase(encryptionSalt, iterations, encryptedMasterSecret, passphrase);
     byte[] encryptionSecret             = Util.split(combinedSecrets, 16, 20)[0];
     byte[] macSecret                    = Util.split(combinedSecrets, 16, 20)[1];

     return new MasterSecret(new SecretKeySpec(encryptionSecret, "AES"),
                             new SecretKeySpec(macSecret, "HmacSHA1"));
   } catch (GeneralSecurityException e) {
     Log.w("keyutil", e);
     return null; //XXX
   } catch (IOException e) {
     Log.w("keyutil", e);
     return null; //XXX
   }
}

I have all the above data and I see SHA1 so I think great, will be easy and can just compare the MAC:
Code:
 private static byte[] verifyMac(byte[] macSalt, int iterations, byte[] encryptedAndMacdData, String passphrase) throws InvalidPassphraseException, GeneralSecurityException, IOException {
   Mac hmac        = getMacForPassphrase(passphrase, macSalt, iterations);

   byte[] encryptedData = new byte[encryptedAndMacdData.length - hmac.getMacLength()];
   System.arraycopy(encryptedAndMacdData, 0, encryptedData, 0, encryptedData.length);

   byte[] givenMac      = new byte[hmac.getMacLength()];
   System.arraycopy(encryptedAndMacdData, encryptedAndMacdData.length-hmac.getMacLength(), givenMac, 0, givenMac.length);

   byte[] localMac      = hmac.doFinal(encryptedData);

   if (Arrays.equals(givenMac, localMac)) return encryptedData;
   else                                   throw new InvalidPassphraseException("MAC Error");
}

Code:
 private static Mac getMacForPassphrase(String passphrase, byte[] salt, int iterations)
     throws GeneralSecurityException
 {
   SecretKey     key     = getKeyFromPassphrase(passphrase, salt, iterations);
   byte[]        pbkdf2  = key.getEncoded();
   SecretKeySpec hmacKey = new SecretKeySpec(pbkdf2, "HmacSHA1");
   Mac           hmac    = Mac.getInstance("HmacSHA1");
   hmac.init(hmacKey);

   return hmac;
}

But then I do further and getKeyFromPassphrase() does something different:
Code:
 private static SecretKey getKeyFromPassphrase(String passphrase, byte[] salt, int iterations)
     throws GeneralSecurityException
 {
   PBEKeySpec keyspec    = new PBEKeySpec(passphrase.toCharArray(), salt, iterations);
   SecretKeyFactory skf  = SecretKeyFactory.getInstance("PBEWITHSHA1AND128BITAES-CBC-BC");
   return skf.generateSecret(keyspec);
}

There is AES step?  I try to run code backward in jshell but get NoSuchAlgorithmException on second line. 

What hashcat mode correspond to this operation?  It look like it should be PBKDF2-HMAC-SHA1 but hashcat exhausted a list with known password.  Can two hashcat mode be run consecutive?

I test the bytes 17-37 in the Signal master_secret as the hash, then use the mac_salt and passphrase_iterations in mode 12000.

Signal is popular - if hashcat cannot crack it should add support!


Messages In This Thread
RE: Signal database password on Android - by deeppurple - 06-11-2018, 11:53 PM