Bad pad block exception when using simple crypto c

2020-02-10 11:34发布

问题:

WHen im trying to decrypt using this class, i get "Bad pad block exception". Any idea why?

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

}

回答1:

I think your Simple Crypto class is too simple. Any time you don't code decryption well enough to even work it's going to end up with bad pad block exception (unless you are using authenticated encryption).

And in the above code I don't even see any usage of initialization vectors, which means your code is either not going to work or be really insecure.

My suggestion don't code this yourself or even cut and paste code from the internet. There's a lot of bad cut and paste encryption code out there. Use a high level library instead.

Keyczar works on android:

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



回答2:

That piece of code does not know how to generate keys. It should certainly not use the proprietary, unspecified "SHA1PRNG" from Sun (which has different implementations under Android) to derive keys from a password.

The getRawKey function may generate different keys on different platforms. It may even generate completely random keys each time it is used, depending on the implementation of "SHA1PRNG". This means you may never be able to retrieve your plaintext ever again, especially on Android.

If you want to encrypt something with a password, please lookup articles on how to use Password Based Encryption (PBE) where the key derivation is performed using PBKDF2 - present the Oracle Java platform..


Furthermore, the seed seems to use the default character encoding, which might be UTF-16 LE, UTF-16 BE, UTF-8 or some latin based character encoding. It's also using ECB as the "AES" instance of Cipher uses ECB by default, so it is not safe for keeping your data confidential.