Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RSA解密期间的javax.crypto.BadPaddingException_Java_Encryption_Cryptography_Rsa_Padding - Fatal编程技术网

RSA解密期间的javax.crypto.BadPaddingException

RSA解密期间的javax.crypto.BadPaddingException,java,encryption,cryptography,rsa,padding,Java,Encryption,Cryptography,Rsa,Padding,在我的Java代码中,我尝试使用RSA加密字符串,并使用公钥。该字符串是表示图像的Base64编码字符串(图像已转换为字符串)。它将使用私钥解密 在加密过程中,我首先得到一个异常“javax.crypto.IllegalBlockSizeException:数据不能超过190字节”。因此,我处理了189块的字符串(纯文本),然后解析它 在解密过程中,我得到了另一个异常“javax.crypto.IllegalBlockSizeException:数据不能超过256字节”。因此,我首先将字节[](

在我的Java代码中,我尝试使用RSA加密字符串,并使用公钥。该字符串是表示图像的Base64编码字符串(图像已转换为字符串)。它将使用私钥解密

在加密过程中,我首先得到一个异常“javax.crypto.IllegalBlockSizeException:数据不能超过190字节”。因此,我处理了189块的字符串(纯文本),然后解析它

在解密过程中,我得到了另一个异常“javax.crypto.IllegalBlockSizeException:数据不能超过256字节”。因此,我首先将字节[](密文)转换为字符串,以256块为单位进行处理,然后再对其进行解析

同样,在解密过程中,我最终得到了一个“javax.crypto.BadPaddingException:decryption error”异常,我一直无法解决该异常

根据该网站专家的推荐,我使用了“OAEPTHA-256和MGF1”。我甚至尝试在其他填充方法之后使用No-Padding,以查看异常是否会消失,但它不起作用。我做错了什么

我能够确定异常是在-decryptedImagePartial=t.rsaDecrypt(cipherTextTrimmed.getBytes(),privateKey)行抛出的; -它位于主方法的解密部分

如果我的编码实践不好,请容忍我。我现在更愿意找出异常背后的错误

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;

public class Tester
{

    public KeyPair buildKeyPair() throws NoSuchAlgorithmException 
    {
        final int keySize = 2048;
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(keySize);
        return keyPairGenerator.genKeyPair();   
    }

    public byte[] encrypt(PublicKey publicKey, String message) throws Exception
    {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");  
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);  
        return cipher.doFinal(message.getBytes());  
    }

    public String decrypt(PrivateKey privateKey, byte [] encrypted) throws Exception
    { 
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");  
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return new String(cipher.doFinal(encrypted));
    }

    public byte[] rsaEncrypt(String watermarkMsg, PublicKey publicKey) throws Exception
    {
        byte[] cipherText = encrypt(publicKey, watermarkMsg);
        return cipherText;
    }

    public String rsaDecrypt(byte[] cipherText, PrivateKey privateKey) throws Exception
    {
        String plainText = decrypt(privateKey, cipherText);
        return plainText;
    }

    public static void main(String args[]) throws NoSuchAlgorithmException
    {
        Tester t = new Tester();

        String inputImageFilePath = "<file_path_here";
        String stringOfImage = null;
        byte[] encryptedImage = null;
        byte[] encryptedImagePartial = null;
        KeyPair keyPair = t.buildKeyPair();
        PublicKey pubKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate()

        //-----------IMAGE TO STRING CONVERSION----------------
        //The imagetostring() function retrieves the image at the file path and converts it into a Base64 encoded String  
        try
        {
            stringOfImage = t.imagetostring(inputImageFilePath);
        }
        catch(Exception e)
        {
            System.out.println(e.toString());
        }

        //-----------ENCRYPTION OF STRING----------------
        //The encryption is done in blocks of 189, because earlier I got an exception - "javax.crypto.IllegalBlockSizeException: Data must not be longer than 190 bytes"
        try
        {
            String plaintext = stringOfImage;
            String plaintextTrimmed = "";
            System.out.println(stringOfImage);
            encryptedImage = new byte[15512];    //The size is given as 15512 because the length of the particular string was found to be 15512
            while(plaintext!="")
            {
                if(plaintext.length()>189)
                {
                    plaintextTrimmed = plaintext.substring(0, 189);
                    plaintext = plaintext.substring(189);
                }
                else
                {
                    plaintextTrimmed = plaintext;
                    plaintext = "";
                }
                encryptedImagePartial = t.rsaEncrypt(plaintextTrimmed, pubKey);
                encryptedImage = t.concatenate(encryptedImage, encryptedImagePartial);
                System.out.println(encryptedImage.length);
            }

        }
        catch(Exception e)
        {
            System.out.println(e.toString());
        }
        t.byteDigest(encryptedImage);

        //-----------DECRYPTION OF STRING--------------
        //The decryption is done in blocks of 189, because earlier I got an exception - "javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes"
        try
        {
            // The ciphertext is located in the variable encryptedImage which is a byte[]
            String stringRepOfCipherText = new String(encryptedImage);              String cipherTextTrimmed = "";
            String decryptedImagePartial;
            String decryptedImage = "";
            while(stringRepOfCipherText!="")
            {
                if(stringRepOfCipherText.length()>189)
                {
                    cipherTextTrimmed = stringRepOfCipherText.substring(0, 189);
                    stringRepOfCipherText = stringRepOfCipherText.substring(189);
                }
                else
                {
                    cipherTextTrimmed = stringRepOfCipherText;
                    stringRepOfCipherText = "";
                }
                decryptedImagePartial = t.rsaDecrypt(cipherTextTrimmed.getBytes(), privateKey);
                decryptedImage = decryptedImage + decryptedImagePartial;
            }
        }
        catch(BadPaddingException e)
        {
            System.out.println(e.toString());
        }
        catch(Exception e)
        {
            System.out.println(e.toString());
        }
    }
}
导入java.security.KeyPair;
导入java.security.KeyPairGenerator;
导入java.security.NoSuchAlgorithmException;
导入java.security.PrivateKey;
导入java.security.PublicKey;
导入javax.crypto.BadPaddingException;
导入javax.crypto.Cipher;
公共类测试员
{
公钥对buildKeyPair()抛出NoSuchAlgorithmException
{
最终int键大小=2048;
KeyPairGenerator KeyPairGenerator=KeyPairGenerator.getInstance(“RSA”);
keyPairGenerator.initialize(密钥大小);
返回keyPairGenerator.genKeyPair();
}
公共字节[]加密(公钥公钥、字符串消息)引发异常
{
Cipher Cipher=Cipher.getInstance(“RSA/ECB/OAEPWithSHA-256和MGF1padding”);
cipher.init(cipher.ENCRYPT_模式,公钥);
返回cipher.doFinal(message.getBytes());
}
公共字符串解密(PrivateKey PrivateKey,字节[]加密)引发异常
{ 
Cipher Cipher=Cipher.getInstance(“RSA/ECB/OAEPWithSHA-256和MGF1padding”);
cipher.init(cipher.DECRYPT_模式,privateKey);
返回新字符串(cipher.doFinal(加密));
}
公共字节[]RSANCRYPT(字符串watermarkMsg,PublicKey PublicKey)引发异常
{
字节[]密文=加密(公钥、水印消息);
返回密文;
}
公共字符串rsaDecrypt(字节[]密文,PrivateKey PrivateKey)引发异常
{
字符串明文=解密(私钥、密文);
返回纯文本;
}
公共静态void main(字符串args[])抛出NoSuchAlgorithmException
{
测试仪t=新测试仪();

String inputImageFilePath=“您无法将密文切割成任意块

由于您特别要求使用不涉及对称算法的普通RSA(我强烈建议您不要这样做!),因此您需要这样做:

  • 了解您的RSA配置的详细信息
  • 将纯文本拆分为此大小的块
  • 单独加密每个块,不要简单地连接它们并放弃块边界!
  • 解密期间:

  • 使用加密后的原始大小将每个密文块传递给解密函数。不要附加任何数据,也不要创建“子字符串”
  • 连接生成的明文

  • 理想情况下,您应该使用混合加密方案:

  • 生成加密密钥(
    encKey
  • 使用
    encKey
  • 使用RSA加密
    encKey

  • 对称密码可以在不同的操作模式下使用,从而避免这种长度限制。

    首先,将图像编码为base 64是完全没有意义的。现代密码的输入由字节组成,而图像已经是字节。如果要存储该字符串,可能需要base 64对密文进行编码。

    输入块大小实际上是190字节。您可以看到RSA/OAEP的一个表(别忘了向上投票!)。我不确定您为什么要在这种情况下使用189;但是我的代码是通用的。输出块大小只是RSA的密钥大小,因为它显式转换为密钥大小(以字节为单位)(即使它可能更小)

    在解密过程中,您将密文转换为字符串。但是,Java中的字符串解码是有损的;如果解码器发现一个不代表字符的字节,那么它将被无声地删除。因此,这不会(始终有效),例如会导致
    BadPaddingException
    。不过,这没关系,我们可以保留二进制密文

    因此,无需进一步讨论,您可以查看一些代码。请注意,密文的扩展为每个块66字节,解密性能较差(主要是解密)。强烈建议在混合密码系统中使用AES和RSA(对于这个问题,这不是第一次)

    import java.io.ByteArrayOutputStream;
    导入java.nio.charset.StandardCharset;
    导入java.security.KeyPair;
    导入java.security.KeyPairGenerator;
    导入java.security.NoSuchAlgorithmException;
    导入java.security.interfaces.RSAPrivateKey;
    导入java.security.interfaces.RSAPublicKey;
    导入java.util.array;
    导入javax.crypto.Cipher;
    公共类测试员{
    私有静态最终整数密钥大小=2048;
    专用静态最终int OAEP_MGF1_SHA256_开销=66;
    公共静态密钥
    
    import java.io.ByteArrayOutputStream;
    import java.nio.charset.StandardCharsets;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.util.Arrays;
    
    import javax.crypto.Cipher;
    
    public class Tester {
    
        private static final int KEY_SIZE = 2048;
        private static final int OAEP_MGF1_SHA256_OVERHEAD = 66;
    
        public static KeyPair buildKeyPair() throws NoSuchAlgorithmException {
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
            keyPairGenerator.initialize(KEY_SIZE);
            return keyPairGenerator.generateKeyPair();
        }
    
        public static void main(String args[]) throws Exception {
    
            KeyPair keyPair = Tester.buildKeyPair();
            RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    
            // assumes the bitLength is a multiple of 8 (check first!)
            int keySizeBytes = pubKey.getModulus().bitLength() / Byte.SIZE;
    
            byte[] image = new byte[1000];
            Arrays.fill(image, (byte) 'm'); 
    
            // --- encryption
    
            final Cipher enc;
            try {
                enc = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException("OAEP with MGF-1 using SHA-256 not available in this runtime", e);
            }
            enc.init(Cipher.ENCRYPT_MODE, pubKey);
    
            int fragmentsize = keySizeBytes - OAEP_MGF1_SHA256_OVERHEAD;
    
            ByteArrayOutputStream ctStream = new ByteArrayOutputStream();
            int off = 0;
            while (off < image.length) {
                int toCrypt = Math.min(fragmentsize, image.length - off);
                byte[] partialCT = enc.doFinal(image, off, toCrypt);
                ctStream.write(partialCT);
                off += toCrypt;
            }
    
            byte[] ct = ctStream.toByteArray();
    
            // --- decryption
    
            Cipher dec = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
            dec.init(Cipher.DECRYPT_MODE, privateKey);
    
            ByteArrayOutputStream ptStream = new ByteArrayOutputStream();
            off = 0;
            while (off < ct.length) {
                int toCrypt = Math.min(keySizeBytes, ct.length - off);
                byte[] partialPT = dec.doFinal(ct, off, toCrypt);
                ptStream.write(partialPT);
                off += toCrypt;
            }
    
            byte[] pt = ptStream.toByteArray();
    
            // mmmm...
            System.out.println(new String(pt, StandardCharsets.US_ASCII));
        }
    }