“javax.crypto.BadPaddingException:数据必须从零开始”异常

时间:2011-06-26 09:34:55

标签: java rsa

我在解密字符串时遇到了上述异常。

以下是我的代码:

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;

public class EncryptAndDecrypt {

    public static Cipher createCipher () throws Exception{

            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");

            return cipher;
    }
    public static KeyPair generateKey () throws  NoSuchAlgorithmException{

            KeyPairGenerator keyGen = KeyPairGenerator.getInstance ("RSA");
            keyGen.initialize(1024);
            KeyPair key = keyGen.generateKeyPair();

            return key;
    }
    public static byte [] encrypt (String  str, Cipher cip, KeyPair key) {

        byte [] cipherText = null;
        try {

            byte [] plainText = str.getBytes("UTF8");
            cip.init(Cipher.ENCRYPT_MODE, key.getPublic());
            cipherText = cip.doFinal(plainText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherText;
    }
    public static String decrypt (byte [] c, Cipher cip, KeyPair key) throws Exception {

        cip.init(Cipher.DECRYPT_MODE, key.getPrivate());

        byte [] decryptedPlainText = cip.doFinal (c);// exception occurred here
        String decryptedPlainStr = new String (decryptedPlainText);

        return decryptedPlainStr;
    }
}


//separate class below to use the encrypt method

public class EncryptionApp {

    public static void main (String [] args) {

        getEncrypted();
    }
    public static byte [] getEncrypted () {

        byte [] encyptedByte = null;
        try {
            String plainText = "der";
            Cipher cip = Safety.createCipher();
            KeyPair key = Safety.generateKey();
            encyptedByte = Safety.useRSA(plainText, cip, key);
        }
        catch (Exception e) {
            e.printStackTrace();
        }

         return encyptedByte;
    }
}

// Another class to use the decrypt method 

public class DecryptionApp {

    public static void main(String[] args) {
        System.out.println (useDecrypted () );
    }
    public static byte[] useDecrypted () {

        byte [] decryptedText = null;
        try {
            Cipher cip = EncryptAndDecrypt.createCipher();
            KeyPair key = EncryptAndDecrypt.generateKey();
            decryptedText = EncryptAndDecrypt.decrypt(EncryptionApp.getEncrypted(),cip,key);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    return decryptedText;
    }
}

4 个答案:

答案 0 :(得分:8)

您已经在"javax.crypto.BadPaddingException: Data must start with zero" exception中提出了相同的问题,我给了您一个答案:您使用了两个不同的密钥对:一个用于加密,另一个用于解密。那不行。我甚至给了你一个代码示例,表明如果使用相同的密钥对,一切运行正常。

KeyPairGenerator.generateKeyPair()生成密钥对。两次调用此方法将获得两个不同的密钥对:它在内部使用随机数生成器来生成始终不同的密钥对。

您必须生成一次密钥对,将其存储在变量中,并使用此变量进行加密和解密。

您应该阅读您正在使用的类和方法的文档。 documentation of generateKeyPair说:

  

这将生成一个新密钥对   每次被召唤。

答案 1 :(得分:3)

将此主要方法添加到EncryptAndDecrypt,然后执行它。你会发现evrything工作得很好。

public static void main(String[] args) throws Exception {
    String s = "hello";
    Cipher cipher = createCipher();
    KeyPair keyPair = generateKey();
    byte[] b = encrypt(s, cipher, keyPair);
    String s2 = decrypt(b, cipher, keyPair);
    System.out.println(s2);
}

问题在于你使用这门课的方式。 useDecrypted方法执行以下操作:

Cipher cip = EncryptAndDecrypt.createCipher(); // create a Cipher object using EncryptAndDecrypt
KeyPair key = EncryptAndDecrypt.generateKey(); // generate a KeyPair using EncryptAndDecrypt

// call EncryptionApp.getEncrypted() to get an encrypted text, then decrypt this encrypted text
// using the keypair created above.
decryptedVote = EncryptAndDecrypt.decrypt(EncryptionApp.getEncrypted(), cip, key);

getEncrypted方法执行以下操作:

String plainText = "der"; // create some plain text
// create a Cipher instance. Is it the same algorithm as the one in useDecrypted?
// we don't know, because it uses another, unknown, Safety class
Cipher cip = Safety.createCipher(); 
// create a new KeyPair instance. Is it the same KeyPair as the one in useDecrypted?
// No : another keypair is generated. There is no way something encrypted using a keypair
// will decrypt correctly with another keypair.
KeyPair key = Safety.generateKey();
encyptedByte = Safety.useRSA(plainText, cip, key);

因此,简而言之,您使用两个不同的密钥对:一个用于加密,另一个用于解密。那不行。

另请注意,在encrypt中,您使用UTF8编码将字符串转换为字节数组,而在decrypt中,使用默认平台编码将字节数组转换为字符串。您应该为两者使用UTF8,因此在decrypt中使用以下代码:

String decryptedPlainStr = new String (decryptedPlainText, "UTF8");

答案 2 :(得分:3)

你用Google搜索了吗?当加密密钥与解密密钥不同时,很多人都会遇到这个问题。您似乎始终生成新密钥,而不是使用相同的密钥来解密您用于加密的密钥。

答案 3 :(得分:0)

我收到了这个错误,在我的情况下结果是我作为参数发送的基本64字符串包含由于在URL中而被更改的一些字符。解决方案结果是对参数进行URL编码。