【问题标题】:How do I call AES/ECB 64k times efficiently?如何有效地调用 AES/ECB 64k 次?
【发布时间】:2013-02-08 02:37:36
【问题描述】:

我正在为 MEGA(这个陌生人的云站点)开发一个库。如果我猜对了,他们会通过以下方式从用户密码中获取 AES 主密钥:

  • 使用 UTF-8 编码的密码作为起始序列 s
  • 通过附加 0 扩展 s,使其长度为 16 的倍数
  • 设置 128 位主密钥 pkey 以修复初始化向量
  • 在每轮 64k 轮中:
    • 对于 s 的每个 128 位块 s[i],AES/ECB 使用 s[i] 作为密钥加密 k。

总而言之,对于 28 个字符的密码,我必须对 AES 进行 128k 次调用。我的实现结果相当缓慢。如:“见鬼,这需要的时间太长了。”

DDMS 显示 GC 正在热运行。我怎样才能让 AES 实现在内部或至少更有效地完成所有这些轮次?每次调用都会创建一个新的字节数组,之后会被丢弃。有没有办法就地做到这一点?

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;
}

非常感谢, 沃尔克

【问题讨论】:

  • 嗯。我想知道“PKDBF-2”是否相关? ^^
  • 一点建议:至少暂时避免使用 MEGA。目前,它使用任何措施都认为不安全的加密机制。 google.com/…
  • 我希望。不幸的是,看起来他们必须创建自己的密钥派生而不是使用已建立的东西。对我来说,这看起来不像 PKDBF。
  • @Eric 谢谢。尽管我真的不喜欢 Kim,但多年来我一直渴望基于客户端的加密云。在我看来,所有问题都源于 MEGA 使用从其服务器加载的 javascript。使用强大的加密库的 Android 应用程序应该可以解决这些问题,至少如果您从不使用 javascript 网站(包括注册)。
  • 你确定for (int round = 0; round &lt; 65536; round--)中的round--吗?

标签: android performance encryption cryptography aes


【解决方案1】:

出于存档目的,我写下我的评论作为答案,因为某些 cmets 将来可能对某人有用。

问题在于第二个 for 循环中的 count--。它应该是count++。实际上,代码执行了 2^31 轮,即 2147483648 而不是所需的 65536。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多