2

当我尝试使用此类解密时,我得到“坏垫块异常”。知道为什么吗?

public class SimpleCrypto {

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

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

    private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        sr.setSeed(seed);
        kgen.init(128, sr); // 192 and 256 bits may not be available
        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 final static String HEX = "0123456789ABCDEF";

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

}
4

2 回答 2

4

那段代码不知道如何生成密钥。它当然不应该使用"SHA1PRNG"来自 Sun 的专有的、未指定的(在 Android 下有不同的实现)从密码中派生密钥。

getRawKey函数可能会在不同的平台上生成不同的密钥。它甚至可以在每次使用时生成完全随机的密钥,具体取决于"SHA1PRNG". 这意味着您可能永远无法再次检索明文,尤其是在 Android 上。

如果您想使用密码加密某些内容,请查找有关如何使用基于密码的加密 (PBE) 的文章,其中使用 PBKDF2 执行密钥派生 - 提供 Oracle Java 平台。


此外,种子似乎使用默认字符编码,可能是 UTF-16 LE、UTF-16 BE、UTF-8 或一些基于拉丁文的字符编码。它还使用 ECB 作为默认使用 ECB 的"AES"实例Cipher,因此对您的数据保密并不安全。

于 2013-01-18T14:50:57.710 回答
1

我认为您的 Simple Crypto 课程太简单了。任何时候,只要您对解密的编码不够好,甚至无法正常工作,最终都会出现坏垫块异常(除非您使用的是经过身份验证的加密)。

在上面的代码中,我什至没有看到初始化向量的任何用法,这意味着您的代码要么无法工作,要么真的不安全。

我的建议不要自己编写代码,甚至不要从互联网上剪切和粘贴代码。那里有很多糟糕的剪切和粘贴加密代码。请改用高级库。

Keyczar适用于安卓:

https://github.com/kruton/android-keyczar-demo

于 2013-01-17T21:36:24.987 回答