Java 无法在Android中解密加密短信(在2.2操作系统中加密)…(正在尝试在2.3操作系统中解密)
我能够加密短信并将其从一个模拟器(Android 2.2)发送到另一个模拟器。 在接收端,我能够成功地进行解密。但问题是,如果在一个操作系统版本(即安卓2.2)中进行加密,并在另一个操作系统版本(安卓2.3)中尝试解密,我会遇到“错误填充异常”。我检查了一下两端是否使用了相同的钥匙。 代码如下所示Java 无法在Android中解密加密短信(在2.2操作系统中加密)…(正在尝试在2.3操作系统中解密),java,android,encryption,aes,Java,Android,Encryption,Aes,我能够加密短信并将其从一个模拟器(Android 2.2)发送到另一个模拟器。 在接收端,我能够成功地进行解密。但问题是,如果在一个操作系统版本(即安卓2.2)中进行加密,并在另一个操作系统版本(安卓2.3)中尝试解密,我会遇到“错误填充异常”。我检查了一下两端是否使用了相同的钥匙。 代码如下所示 public class ED { private String Key; public ED() { Key = "abc12"; //
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;
}
}
公共类ED{
私钥;
公共教育署(){
Key=“abc12”;//分配默认键。
}
公共ED(字符串键){
//TODO自动生成的构造函数存根
钥匙=钥匙;
}
公共字符串加密(字符串到加密)引发异常{
byte[]rawKey=getRawKey(Key.getBytes(“UTF-8”);
byte[]result=encrypt(rawKey,toEncrypt.getBytes(“UTF-8”);
返回到hex(结果);
}
公共字节[]加密(字节[]密钥,字节[]toEncodeString)引发异常{
SecretKeySpec sKeySpec=新SecretKeySpec(键,“AES”);
Cipher Cipher=Cipher.getInstance(“AES”);
cipher.init(cipher.ENCRYPT_模式,sKeySpec);
字节[]加密=cipher.doFinal(toEncodeString);
返回加密;
}
私有字节[]getRawKey(字节[]键)引发异常{
KeyGenerator kGen=KeyGenerator.getInstance(“AES”);
SecureRandom sr=SecureRandom.getInstance(“SHA1PRNG”);
高级固定种子(键);
kGen.init(128,sr);
SecretKey sKey=kGen.generateKey();
字节[]原始=sKey.getEncoded();
返回原材料;
}
/*************************************描述*********************************************/
公共字符串解密(String encryptedString)引发异常{
byte[]rawKey=getRawKey(Key.getBytes(“UTF-8”);
System.out.println(“以字节为单位的解密密钥:“+rawKey”);
System.out.println(“解密中的密钥:+rawKey”);
SecretKeySpec sKeySpec=新的SecretKeySpec(rawKey,“AES”);
Cipher Cipher=Cipher.getInstance(“AES”);
cipher.init(cipher.DECRYPT_模式,sKeySpec);
byte[]decrypted=cipher.doFinal(toByte(encryptedString));
System.out.println(“以字节为单位的解密混乱------->”+解密);
返回新字符串(已解密);
}
公共字符串toHex(字节[]buf){
如果(buf==null)
返回“”;
StringBuffer结果=新的StringBuffer(2*buf.长度);
对于(int i=0;i>4)和0x0f)).append(十六进制字符(b和0x0f));
}
公共字节[]到字节(字符串hexString){
int len=hexString.length()/2;
字节[]结果=新字节[len];
对于(int i=0;i
我正在使用sendTextMessage()函数发送短信。我读到加密/解密不依赖于操作系统,但在这种情况下,这是不正确的。配置密码(在AES中)时是否遗漏了任何重要内容?请让我知道。是设置种子()。它不做你认为它做的事情:它只是将给定种子的熵添加到底层算法中。您可能会发现,它在两种平台上都返回不同的结果。SHA1PRNG是一个伪随机函数,但是如果它已经被植入种子,它可能会返回不同的结果。如果问题出在密钥长度上,您可以从密码派生密钥,而不是直接使用它。您可以使用散列(如SHA-1、MD5等)并将其裁剪为正确的大小(128、192或256位),或者使用
PBEKeySpec
而不是SecretKeySpec
这样可以消除密钥长度的问题。如果填充问题出现在明文中,我建议您使用
CipherInputStream
和CipherOutputStream
,这比Cipher更便于程序员使用。doFinal
问题在于安全随机生成。它在不同的平台上给出了不同的结果。这是因为engineNextBytes()方法中SHA1PRNG_SecureRandomImpl.java的第320行(姜饼源代码)上有一个bug修复,其中
bits = seedLength << 3 + 64;
bits=seedLength不要仅仅因为您以相同的方式为RNG设定种子,就依赖KeyGenerator
来生成相同的密钥。如果要预共享密钥,请共享密钥,而不是种子
您还应该完全指定加密转换:“AES/ECB/pkcs5pdadding”
最后,ECB模式不适合一般使用
请参阅,以获取一个使用JCE正确执行加密的示例。不是答案,只是一个想法:比较了输出/输入(您发送的内容和接收的内容)-比如,对其进行哈希运算并比较结果?如果您不介意性能和Java 1.5及更高版本的兼容性,我总是使用sb.append(String.format(“%02X”,b&0xFF))。我甚至不确定最后一个0xFF(使其成为可能)是否有必要。类似的问题:非常感谢Robert。这个链接解决了我的问题。安全随机密钥生成的问题。您是对的,Owlstead先生。问题在于SecureRandom()生成,setSeed()。你说“你可能会发现它在两个平台上返回的结果不同”,这是正确的。所以解决这个问题的最好方法是使用另一种方法生成密钥。对于
bits = (seedLength << 3) + 64;
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));
}
}