加密算法在Android 2.1和2.1以上版本上提供了不同的结果 [英] Encryption algorithm giving different results on Android 2.1 and versions above 2.1

查看:203
本文介绍了加密算法在Android 2.1和2.1以上版本上提供了不同的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

发布此问题之前,我已经进行了很多搜索.之前的代码在非android 4.2/2.1设备上运行.然后我用谷歌搜索并介绍了以下代码行.那部分解决了它,即它现在可以在4.2设备上使用,但不能在Froyo上使用.

I have searched lot before posting this question. Earlier the code was working in non android 4.2/2.1 devices. Then i googled and introduced the below lines of code. That solved it partially,ie it's now working on 4.2 devices but not on Froyo.

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

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

The below given is the class I use for encryption

    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设备上产生的结果不同.

The code is working properly on non-froyo devices. But on froyo the encryption is giving different result than on non-froyo devices.

推荐答案

您正在误用伪随机数生成器,并且它的种子是作为密钥派生函数的-这确实是很糟糕的样式.伪随机数生成器"SHA1PRNG"不是像AES这样的标准-因此,您永远不知道所获得的实现.另请参见是否有SHA1PRNG标准?

You are misusing a pseudo random number generator and it's seed as a key derivation function - this is really really bad style. The pseudo random number generator "SHA1PRNG" is not a standard like AES - therefore you never know what implementation you get. See also Is there a SHA1PRNG standard?

这使我难怪您会得到不同的结果.基于给定种子获得确定性结果不是您可以从伪随机数函数中获得的特性.

It makes me no wonder that you get different results. Getting a deterministic result based on a given seed is not a property you can expect from a pseudo random number function.

如果您想从密码派生加密密钥,请使用密钥派生函数,例如PKCS#5/PBKDF2.Bouncy Castle中包含了AFAIR的PBKDF2实现.

If you want to derive a cryptographic key from a password please use a Key Derivation Function like PKCS #5 / PBKDF2. An implementation of PBKDF2 is AFAIR included in Bouncy Castle.

这篇关于加密算法在Android 2.1和2.1以上版本上提供了不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆