1

在发布这个问题之前,我已经搜索了很多。早些时候,代码在非 android 4.2/2.1 设备上运行。然后我用谷歌搜索并介绍了以下代码行。这部分解决了它,即它现在可以在 4.2 设备上运行,但不能在 Froyo 上运行。

    if (android.os.Build.VERSION.SDK_INT >= JELLY_BEAN_4_2) {
    sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
    sr = SecureRandom.getInstance("SHA1PRNG");
}

下面给出的是我用于加密的类

    public class Encryption {
private final static String HEX = "0123456789ABCDEF";
private final static int JELLY_BEAN_4_2 = 17;
private final static byte[] key = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0 };

public static String encrypt(String seed, String cleartext)
        throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes());
    byte[] result = encrypt(rawKey, cleartext.getBytes());
    String fromHex = toHex(result);
    return fromHex;
}

public static String decrypt(String seed, String encrypted)
        throws Exception {
    byte[] seedByte = seed.getBytes();
    System.arraycopy(seedByte, 0, Constants.SEED, 0,
            ((seedByte.length < 16) ? seedByte.length : 16));
    String base64 = new String(Base64.decode(encrypted, 0));
    byte[] rawKey = getRawKey(seedByte);
    byte[] enc = toByte(base64);
    byte[] result = decrypt(rawKey, enc);
    return new String(result);
}

public static byte[] encryptBytes(String seed, byte[] cleartext)
        throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes());
    byte[] result = encrypt(rawKey, cleartext);
    return result;
}

public static byte[] decryptBytes(String seed, byte[] encrypted)
        throws Exception {
    byte[] rawKey = getRawKey(seed.getBytes());
    byte[] result = decrypt(rawKey, encrypted);
    return result;
}

private static byte[] getRawKey(byte[] seed) throws Exception {
    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    SecureRandom sr = null;
    if (android.os.Build.VERSION.SDK_INT >= JELLY_BEAN_4_2) {
        sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
    } else {
        sr = SecureRandom.getInstance("SHA1PRNG");
    }
    sr.setSeed(seed);
    try {
        kgen.init(256, sr);
    } catch (Exception e) {
        // "This device doesn't suppor 256bits, trying 192bits.");
        try {
            kgen.init(192, sr);
        } catch (Exception e1) {
             Log.w(LOG,
             "This device doesn't suppor 192bits, trying 128bits.");
            kgen.init(128, sr);
        }
    }
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    return raw;
}

private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(clear);
    return encrypted;
}

private static byte[] decrypt(byte[] raw, byte[] encrypted)
        throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    Cipher cipher = Cipher.getInstance("AES");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] decrypted = cipher.doFinal(encrypted);
    return decrypted;
}

public static String toHex(String txt) {
    return toHex(txt.getBytes());
}

public static String fromHex(String hex) {
    return new String(toByte(hex));
}

public static byte[] toByte(String hexString) {
    int len = hexString.length() / 2;
    byte[] result = new byte[len];
    for (int i = 0; i < len; i++)
        result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                16).byteValue();
    return result;
}

public static String toHex(byte[] buf) {
    if (buf == null)
        return "";
    StringBuffer result = new StringBuffer(2 * buf.length);
    for (int i = 0; i < buf.length; i++) {
        appendHex(result, buf[i]);
    }
    return result.toString();
}

private static void appendHex(StringBuffer sb, byte b) {
    sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}

}

该代码在非 froyo 设备上正常工作。但是在 froyo 上,加密的结果与非 froyo 设备上的不同。

4

1 回答 1

3

您正在滥用伪随机数生成器,并将其作为密钥推导函数的种子 - 这真的是非常糟糕的风格。伪随机数生成器“SHA1PRNG”不是像 AES 这样的标准——因此你永远不知道你得到了什么实现。另请参阅是否有 SHA1PRNG 标准

难怪你会得到不同的结果。基于给定种子获得确定性结果不是您可以从伪随机数函数中获得的属性。

如果您想从密码中派生加密密钥,请使用密钥派生函数,如 PKCS #5 / PBKDF2。PBKDF2 的一个实现是包含在 Bouncy Castle 中的 AFAIR。

于 2013-05-03T15:25:46.070 回答