我正在创建一个Android应用程序,我希望在将其发送到DataBase之前对其进行加密,并且加密是正确的。解密String时会出现问题,因为我收到了BadPaddingException并且我不知道问题出在哪里。这是代码:
public final static String HEX = "36A52C8FB7DF9A3F";
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);
}
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 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;
}
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
我用这段代码加密和解密:
String encrypted = encrypt(HEX, "some text");
String decrypted = decrypt(HEX, encrypted);
有人可以帮我吗?
非常感谢!!
编辑:问题尚未解决,但我有更多信息。首先,我在Java项目中加密,然后在Android项目中解密。我试图在同一个Java项目中解密,没有问题,但如果我尝试在Android中解密,它就不起作用。问题出在方法“getRawKey”(查看kgen.generateKey()注释):
JAVA:
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed); //Seed: [51, 54, 65, 53, 50, 67, 56, 70, 66, 55, 68, 70, 57, 65, 51, 70]
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey(); //skey.key = [-97, -52, 45, -95, -64, -58, 16, -20, 124, -50, -104, 58, 23, -75, 88, 94]
byte[] raw = skey.getEncoded();
return raw;
}
机器人
private static byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed); //Seed: [51, 54, 65, 53, 50, 67, 56, 70, 66, 55, 68, 70, 57, 65, 51, 70]
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey(); //skey.key = [-114, 32, 16, -52, -81, 125, -88, 88, -76, 20, -117, -11, 33, -61, 32, -91]
byte[] raw = skey.getEncoded();
return raw;
}
我不是地穴专家,但是怎么可能用相同的种子,我得到一个不同的关键?
答案 0 :(得分:3)
我遇到了一些问题。解决方案:
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
public class StringEncrypter {
Cipher ecipher;
Cipher dcipher;
StringEncrypter(String password) {
// 8-bytes Salt
byte[] salt = {
(byte)0xA9, (byte)0x9B, (byte)0xC8, (byte)0x32,
(byte)0x56, (byte)0x34, (byte)0xE3, (byte)0x03
};
// Iteration count
int iterationCount = 19;
try {
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, iterationCount);
SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
ecipher = Cipher.getInstance(key.getAlgorithm());
dcipher = Cipher.getInstance(key.getAlgorithm());
// Prepare the parameters to the cipthers
AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);
ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
} catch (InvalidAlgorithmParameterException e) {
System.out.println("EXCEPTION: InvalidAlgorithmParameterException");
} catch (InvalidKeySpecException e) {
System.out.println("EXCEPTION: InvalidKeySpecException");
} catch (NoSuchPaddingException e) {
System.out.println("EXCEPTION: NoSuchPaddingException");
} catch (NoSuchAlgorithmException e) {
System.out.println("EXCEPTION: NoSuchAlgorithmException");
} catch (InvalidKeyException e) {
System.out.println("EXCEPTION: InvalidKeyException");
}
}
/**
* Takes a single String as an argument and returns an Encrypted version
* of that String.
* @param str String to be encrypted
* @return <code>String</code> Encrypted version of the provided String
*/
public byte[] encrypt(String str) {
try {
// Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");
// Encrypt
byte[] enc = ecipher.doFinal(utf8);
// Encode bytes to base64 to get a string
//return new sun.misc.BASE64Encoder().encode(enc);
return enc;
} catch (BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
}
return null;
}
/**
* Takes a encrypted String as an argument, decrypts and returns the
* decrypted String.
* @param str Encrypted String to be decrypted
* @return <code>String</code> Decrypted version of the provided String
*/
public String decrypt(byte[] dec) {
try {
// Decode base64 to get bytes
//byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(str);
//byte[] dec = Base64Coder.decode(str);
// Decrypt
byte[] utf8 = dcipher.doFinal(dec);
// Decode using utf-8
return new String(utf8, "UTF8");
} catch (BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
}
return null;
}
}
我找到了这个解决方案here。 这很完美。但我真的很想知道,AES的问题是什么。
答案 1 :(得分:2)
对于那些希望使用String和Base64编码用于数据库的人,可以使用Mike Keskinov(和Andalv.org上的xalien)的这些(略微重写的)函数。
public String encrypt(String str)
{
try {
// Encode the string into bytes using utf-8
byte[] utf8 = str.getBytes("UTF8");
// Encrypt
byte[] enc = ecipher.doFinal(utf8);
// Encode bytes to base64 to get a string
return new String(Base64.encode(enc,0));
} catch (BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
}
return null;
}
public String decrypt(String str)
{
try {
// Decode base64 to get bytes
byte[] dec = Base64.decode(str, 0);
// Decrypt
byte[] utf8 = dcipher.doFinal(dec);
// Decode using utf-8
return new String(utf8, "UTF8");
} catch (BadPaddingException e) {
} catch (IllegalBlockSizeException e) {
} catch (UnsupportedEncodingException e) {
}
return null;
}
此代码还使用内置的Android Base64库,因此无需导入任何其他外部库。
我最初没有意识到的是如何从另一个班级(我的无知)实际使用这个班级。这是一个简单的例子:
StringEncrypter se = new StringEncrypter("mypass");
String decryptedString = se.decrypt(encryptedString);
Base64还有一件事。我发现Base64编码只要字符串长度超过76个字符就会添加'/ n'换行符(0x0a)。这严重扰乱了解密结果。要删除这些换行符,您可以添加以下内容:
b64_enc_str = se.encrypt(plaintext_str);
str = b64_enc_str.replace("/n","");
希望它有助于某人。
答案 2 :(得分:1)
从一般的角度来看,我认为BadPaddingException可能是由于以下原因:
I&GT;加密算法的数据大小不正确。
II&GT;正在使用不同的密钥加密&amp;解密数据。