How can I call AES / ECB 64k times efficiently?

I am working on a library for MEGA (this strange man's cloud site). If I understand correctly, they get the AES key from the user's password:

  • Use UTF-8 encoding as initial s sequence
  • Expand s by adding 0 so that its length is a multiple of 16
  • Set 128-bit key-key-key to fix the initialization vector
  • In each of the 64k rounds:
    • For each 128-bit block, s [i] for AES / ECB encryption k using s [i] as the key.

In general, for a 28 character password, I need to make 128k AES calls. My implementation turns out to be pretty slow. Like: "Damn, this is too long."

DDMS shows me that the GC is running hot. How can I get an AES implementation to do all these rounds internally, or at least more efficiently? Each call creates a new byte array, which is then discarded. Is there a way to do this locally?

public static byte[] calculatePasswordKey(String password) {
    Log.v(TAG, ">calculatePasswordKey");

    byte[] pw = password.getBytes();
    byte[] pkey = {(byte)0x93, (byte)0xC4, 0x67, (byte)0xE3, 0x7D, (byte)0xB0, (byte)0xC7, (byte)0xA4, (byte)0xD1, (byte)0xBE, 0x3F, (byte)0x81, 0x01, 0x52, (byte)0xCB, 0x56};

    //expand by appending 0s
    Log.v(TAG, Arrays.toString(pw));
    if ((pw.length & 0xf0) != 0) {
        int l = (pw.length & 0xf0) + 0x10;
        byte[] paddedpw = new byte[l];
        System.arraycopy(pw, 0, paddedpw, 0, pw.length);
        pw = paddedpw;
        Log.v(TAG, Arrays.toString(pw));
    }

    try {
        //create ciphers only once
        Cipher[] ciphers = new Cipher[pw.length / 16];
        Log.v(TAG, "Creating " + ciphers.length + " AES ciphers");
        for (int cIndex = 0; cIndex < ciphers.length; cIndex++) {
            ciphers[cIndex] = getAesEcbCipher();
            ciphers[cIndex].init(Cipher.ENCRYPT_MODE, new SecretKeySpec(pw, cIndex * 16, 16, "AES"));
        }

        Log.v(TAG, "Beginning 65536 rounds of AES encryption");
        for (int round = 0; round < 65536; round--) {
            for (Cipher c: ciphers) {
                pkey = c.update(pkey);
                if (pkey.length != 16) {
                    throw new Error("update does not work, revert to doFinal()");
                }
            }
        }
        return pkey;
    } catch (Exception e) {
        Log.e(TAG, "Cannot calculate password key: " + e.getMessage());
        e.printStackTrace();
    }
    return null;
}

      

Thanks a lot, Volker

+3


source to share


1 answer


For archiving purposes, I am writing my comment as an answer, as some of the comments might be helpful to someone in the future.



The problem lies in count--

the second loop. It should be count++

. Be that as it may, the code does 2 ^ 31 rounds, which is 2147483648 instead of the desired 65536.

+1


source







All Articles