我正在编写一个应用程序,它根据用户设置的密码加密和解密用户注释。我使用以下算法进行加密/解密 1. PBEWithSHA256And256BitAES-CBC-BC 2. PBEWithMD5And128BitAES-CBC-OpenSSL
e_Cipher = Cipher.getInstance(PBEWithSHA256And256BitAES-CBC-BC);
d_Cipher = Cipher.getInstance(PBEWithSHA256And256BitAES-CBC-BC);
e_Cipher.init()
d_Cipher.init()
加密效果很好,但在尝试解密时会给出
异常 - 非法块大小
加密后我将cipherText转换为HEX并将其存储在sqlite数据库中。我在decyption期间从sqlite数据库中检索正确的值但是当调用d_Cipher.dofinal()
时它会抛出异常。
我以为我错过了指定填充并尝试检查其他可用的密码算法是什么,但我无法找到。
请求您提供一些关于 Android支持的密码算法和填充的知识吗?如果我使用的算法可以用于填充,我应该如何指定填充机制? 我是加密的新手,所以尝试了BouncyCastle.java中提供的几种算法,但不成功。
这里要求的是代码
public class CryptoHelper {
private static final String TAG = "CryptoHelper";
//private static final String PBEWithSHA256And256BitAES = "PBEWithSHA256And256BitAES-CBC-BC";
//private static final String PBEWithSHA256And256BitAES = "PBEWithMD5And128BitAES-CBC-OpenSSL";
private static final String PBEWithSHA256And256BitAES = "PBEWithMD5And128BitAES-CBC-OpenSSLPBEWITHSHA1AND3-KEYTRIPLEDES-CB";
private static final String randomAlgorithm = "SHA1PRNG";
public static final int SALT_LENGTH = 8;
public static final int SALT_GEN_ITER_COUNT = 20;
private final static String HEX = "0123456789ABCDEF";
private Cipher e_Cipher;
private Cipher d_Cipher;
private SecretKey secretKey;
private byte salt[];
public CryptoHelper(String password) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, InvalidKeySpecException {
char[] cPassword = password.toCharArray();
PBEKeySpec pbeKeySpec = new PBEKeySpec(cPassword);
PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, SALT_GEN_ITER_COUNT);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(PBEWithSHA256And256BitAES);
secretKey = keyFac.generateSecret(pbeKeySpec);
SecureRandom saltGen = SecureRandom.getInstance(randomAlgorithm);
this.salt = new byte[SALT_LENGTH];
saltGen.nextBytes(this.salt);
e_Cipher = Cipher.getInstance(PBEWithSHA256And256BitAES);
d_Cipher = Cipher.getInstance(PBEWithSHA256And256BitAES);
e_Cipher.init(Cipher.ENCRYPT_MODE, secretKey, pbeParamSpec);
d_Cipher.init(Cipher.DECRYPT_MODE, secretKey, pbeParamSpec);
}
public String encrypt(String cleartext) throws IllegalBlockSizeException, BadPaddingException {
byte[] encrypted = e_Cipher.doFinal(cleartext.getBytes());
return convertByteArrayToHex(encrypted);
}
public String decrypt(String cipherString) throws IllegalBlockSizeException {
byte[] plainText = decrypt(convertStringtobyte(cipherString));
return(new String(plainText));
}
public byte[] decrypt(byte[] ciphertext) throws IllegalBlockSizeException {
byte[] retVal = {(byte)0x00};
try {
retVal = d_Cipher.doFinal(ciphertext);
} catch (BadPaddingException e) {
Log.e(TAG, e.toString());
}
return retVal;
}
public String convertByteArrayToHex(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 void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));
}
private static byte[] convertStringtobyte(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 byte[] getSalt() {
return salt;
}
public SecretKey getSecretKey() {
return secretKey;
}
public static SecretKey createSecretKey(char[] password) throws NoSuchAlgorithmException, InvalidKeySpecException {
PBEKeySpec pbeKeySpec = new PBEKeySpec(password);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance(PBEWithSHA256And256BitAES);
return keyFac.generateSecret(pbeKeySpec);
}
}
我将调用mCryptoHelper.decrypt(String str)
然后导致非法块大小异常
我的环境:Eclipse上的Android 1.6
答案 0 :(得分:1)
在代码中,每次我生成“salt”时,
SecureRandom saltGen = SecureRandom.getInstance(randomAlgorithm);
this.salt = new byte[SALT_LENGTH];
saltGen.nextBytes(this.salt);
因此加密和解密密码之间存在差异。所以它给错误Bad Pad块或Padding块损坏了。 如果我将Salt声明为某个已知值,它就可以正常工作。
答案 1 :(得分:1)
@Vamsi是正确的,它看起来像是正在生成一个新的Salt。这应该生成一次,并存储为程序已知的。如果salt发生变化,那么加密/解密数据检查就不会匹配。