日期:2014-05-20  浏览次数:20782 次

RSA解密时BadPaddingException
public class RSATest2 {

public static void main(String[] args) {
try {
RSATest2 encrypt = new RSATest2();

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
// 私钥,其实私钥是指定好的,与公钥是一对,我这里随便取一个暂时用用。
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 公钥不用,只用上面的私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

// 假设这是加密后的字符串,我要把它解密
String encryptedStr = "sdfds23fd23";
/*
* 为什么会出现javax.crypto.BadPaddingException: Data must start with zero
* 看了Cipher的文档也不懂是什么意思,“如果此 cipher
* 为解密模式,并且未请求填充或不填充,但解密的数据没有用适当的填充字节所限制” 需要怎么做?
*/
byte[] de = encrypt.decrypt(privateKey, encryptedStr.getBytes());
System.out.println(de.toString());
} catch (Exception e) {
e.printStackTrace();
}
}

protected byte[] decrypt(RSAPrivateKey privateKey, byte[] obj) {
if (privateKey != null) {
try {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(obj);
} catch (Exception e) {
e.printStackTrace();
}
}

return null;
}
}

先说说正确的情况,先用Cipher.getInstance("RSA");初始化为加密模式,把一个指定的串加密后返回一个byte数组;如果把这个byte数组传给解密的doFinal方法,解密成功。
但是传给解密doFinal方法的参数是普通的一个字符串产生的byte数组,那么就会抛出
javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.a(DashoA6275)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA6275)
at javax.crypto.Cipher.doFinal(DashoA12275)
at RSATest2.decrypt(RSATest2.java:41)
at RSATest2.main(RSATest2.java:29)
java.lang.NullPointerException
at RSATest2.main(RSATest2.java:30)
为什么呢?
在文档中找到了如下描述,可是可以帮我理解一下么,谢谢。
BadPaddingException - 如果此 cipher 为解密模式,并且未请求填充或不填充,但解密的数据没有用适当的填充字节所限制

------解决方案--------------------
没用过,友情帮你顶
------解决方案--------------------
那个当然,你的给普通字符串的byte数组都不符合加密后的排列要求,当然会出错。

------解决方案--------------------
帮顶
------解决方案--------------------
终于搞定了,基本功太差,得好好补补了。
加密后产生的byte数组转成string时要在各byte之间加个标识符,我加了个空格,
然后再根据空格分隔转换回byte数组。如果不加标识符,由于byte值可能是一位到三位,无法知道某一个byte是在哪里结束。当然也可以在转成string时补0。或者转成16进制固定为两位长。


code:
public class RSATest {

public static void main(String[] args) {
try {
RSATest encrypt = new RSATest();

KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

String str = "Hello World!";
System.out.println("String will be encrypted: " + str);
byte[] e = encrypt.encrypt(publicKey, str.getBytes());
String tmp1 = encrypt.bytesToString(e);
System.out
.println("encrypted String's bytes, use
bytesToString() method convert bytes to string: " + tmp1);
String[] strArr = tmp1.split(" ");
int len = strArr.length;
byte[] clone = new byte[len];
for (int i = 0; i < len; i++) {
clone[i] = Byte.parseByte(strArr[i]);
}
System.out.println("convert to String, then back to bytes