无法在Android中解密加密的短信(在2.2操作系统中加密)...(试图在2.3操作系统中解密)

时间:2011-12-09 12:52:42

标签: java android encryption aes

我能够加密短信并将其从一个模拟器(Android 2.2)发送到另一个模拟器。 在接收端,我能够成功解密。但问题是如果在一个操作系统版本(即Android 2.2)中进行加密并尝试在另一个操作系统版本(Android 2.3)中进行解密,我会收到'糟糕的填充异常'。我检查过我在两端使用了相同的密钥。 代码如下所示

public class ED {


    private  String Key;

        public ED() {
            Key = "abc12";   // Assigning default key.
        }

        public ED(String key) {
            // TODO Auto-generated constructor stub
            Key = key;

        }



        public String encrypt(String toEncrypt) throws Exception {
            byte[] rawKey = getRawKey(Key.getBytes("UTF-8"));
            byte[] result = encrypt(rawKey, toEncrypt.getBytes("UTF-8"));
            return toHex(result);
        }



        public  byte[] encrypt(byte[] key, byte[] toEncodeString) throws Exception {

            SecretKeySpec sKeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, sKeySpec);

            byte[] encrypted = cipher.doFinal(toEncodeString);

            return encrypted;
        }

        private  byte[] getRawKey(byte[] key) throws Exception {

            KeyGenerator kGen = KeyGenerator.getInstance("AES");
            SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
            sr.setSeed(key);
            kGen.init(128, sr);
            SecretKey sKey = kGen.generateKey();
            byte[] raw = sKey.getEncoded();
            return raw;

        } 

    /************************************* Decription *********************************************/

            public String decrypt(String encryptedString) throws Exception {

                byte[] rawKey = getRawKey(Key.getBytes("UTF-8"));
                System.out.println("Decrypted Key in bytes : "+rawKey);


                System.out.println("Key in decryption :"+rawKey);


                SecretKeySpec sKeySpec = new SecretKeySpec(rawKey, "AES");
                Cipher cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.DECRYPT_MODE, sKeySpec);
                byte[] decrypted = cipher.doFinal(toByte(encryptedString));
                System.out.println("Decrypted mess in bytes---------->" +decrypted);
                return new String(decrypted);
            }






            public 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 String HEX = "0123456789ABCDEF";
            private void appendHex(StringBuffer sb, byte b) {
                sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
            }

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

    }

我正在使用sendTextMessage()函数发送短信。我读到加密/解密不依赖于操作系统,但在这种情况下并非如此。在配置密码时(在AES中),我是否遗漏了任何重要的内容?请告诉我。

4 个答案:

答案 0 :(得分:1)

这是setSeed()。它没有做你认为它做的事情:它只是将给定种子的熵添加到底层算法。您可能会发现它在两个平台上都返回了不同的东西。 SHA1PRNG 伪随机函数,但如果它已经播种,则可能会返回不同的结果。

答案 1 :(得分:0)

如果问题出在密钥长度上,您可以从密码中派生一个密钥,而不是直接使用密码。您可以使用哈希(如SHA-1,MD5等)并将其裁剪为正确的大小(128,192或256位),或使用PBEKeySpec代替SecretKeySpec

用于消除密钥长度的问题。如果填充问题出在明文中,我建议您使用CipherInputStreamCipherOutputStream,它们比Cipher.doFinal使用的程序员更友好。

答案 2 :(得分:0)

问题在于SecureRandom的生成。它在不同的平台上提供不同的结果。这是因为engineNextBytes()方法中的SHA1PRNG_SecureRandomImpl.java第320行(在Gingerbread源代码中)修复了错误

bits = seedLength << 3 + 64; 

已更改为

bits = (seedLength << 3) + 64; 

使用SecretKeyFactory()生成安全密钥而不是安全随机。

public class Crypto {

Cipher ecipher;
Cipher dcipher;

byte[] salt = { 1, 2, 4, 5, 7, 8, 3, 6 };
int iterationCount = 1979;

Crypto(String passPhase) {
    try {
        // Create the key
        KeySpec keySpec = new PBEKeySpec(passPhase.toCharArray(), salt, iterationCount);
        SecretKey key = SecretKeyFactory.getInstance("PBEWITHSHA256AND128BITAES-CBC-BC").generateSecret(keySpec);
        ecipher = Cipher.getInstance(key.getAlgorithm()); 
        dcipher = Cipher.getInstance(key.getAlgorithm());

        AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);

        ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
        dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);

    } catch (Exception e) {
        // TODO: handle exception
        //Toast.makeText(this, "I cought ", Toast.LENGTH_LONG).show();
    }


}

public String encrypt(String str) {
    String rVal;
    try {
        byte[] utf8 = str.getBytes("UTF8");

        byte[] enc = ecipher.doFinal(utf8);

        rVal = toHex(enc);

    } catch (Exception e) {
        // TODO: handle exception
        rVal = "Exception Caught "+e.getMessage();
    }
    return rVal;
}


public String decrypt(String str) {
    String rVal;
    try {
        byte[] dec = toByte(str);
        byte[] utf8 = dcipher.doFinal(dec);

        rVal = new String(utf8, "UTF8");

    } catch(Exception e) {
        rVal = "Error in decrypting :"+e.getMessage();
    }
    return rVal;
}

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


}

答案 3 :(得分:0)

请勿依赖KeyGenerator生成相同的密钥,因为您以相同的方式播种RNG。如果您预先共享密钥,请共享密钥,而不是种子。

您还应该完全指定加密转换:“AES / ECB / PKCS5Padding”

最后,ECB模式对于一般用途并不安全。

有关使用JCE正确执行加密的示例,请参阅another answer of mine