RSA加密解码:BadPaddingException:数据必须从零开始



我很抱歉向您的技能询问问题很多次。我有一个关于RSA Crypthography的问题。我已经检查了有关此问题的其他主题,但是我没有找到任何有用的答案。我希望你能帮助我。

我想读一个文件,crypt contun contun,然后解密它,然后将这些解密的字节放入新文件中。

我实际上可以: - 获取文件的字节 - crypt it

我有例外:javax.crypto.badpaddingexception:数据必须以零开始。

这是我的代码:

    package com.bodom.ghosty;
    import javax.crypto.BadPaddingException;
    import javax.crypto.Cipher;
    import javax.crypto.IllegalBlockSizeException;
    import javax.crypto.NoSuchPaddingException;
    import java.io.*;
    import java.math.BigInteger;
    import java.nio.ByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.security.*;
    import java.security.spec.InvalidKeySpecException;
    import java.security.spec.RSAPrivateKeySpec;
    import java.security.spec.RSAPublicKeySpec;
    import java.util.Scanner;
    public class EncryptionUtil {
        private final PrivateKey privateKey;
        private final PublicKey publicKey;
        /**
         * Build an EncryptionUtil object
         *
         * @param keyPair The KeyPair used for Ghosty
         */
        public EncryptionUtil (KeyPair keyPair) {
            this.privateKey = keyPair.getPrivate();
            this.publicKey = keyPair.getPublic();
        }

        /**
         * Generate a pair of RSA keys
         *
         * @return A keypair of RSA keys
         * @throws NoSuchAlgorithmException
         */
        private static KeyPair keyGenerate() throws NoSuchAlgorithmException {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            keyGen.initialize(2048);
            return keyGen.genKeyPair();
        }

        /**
         * Crypt data
         *
         * @param data      Data to encrypt
         * @return          The crypted data
         * @throws NoSuchAlgorithmException
         * @throws NoSuchPaddingException
         * @throws InvalidKeyException
         * @throws IllegalBlockSizeException
         * @throws BadPaddingException
         */
        private static byte[] rsaEncryption(byte[] data, EncryptionUtil encryptionUtil) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, encryptionUtil.publicKey);
            return cipher.doFinal(data);
        }

        /**
         * Read the bytes of a file
         *
         * @param file is the file to read
         * @return     the bytes of the file
         * @throws IOException
         */
        private static byte[] readBytesInFile (Path file) throws IOException {
            byte[] result = new byte[(int)Files.size(file)];
            try {
                try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file.getFileName().toString()))) {
                    int bytesRead = 0;
                    while (bytesRead < result.length) {
                        int bytesLeft = result.length - bytesRead;
                        int bytesGet = inputStream.read(result, bytesRead, bytesLeft);
                        if (bytesGet > 0) {
                            bytesRead += bytesGet;
                        }
                    }
                }
            } catch (IOException e) {
                System.out.println(e);
            }
            return result;
        }

        /**
         * Encrypt a file
         *
         * @param file      Path of the file to crypt
         * @return          A byte array which contains the crypted lines of the file
         * @throws java.io.IOException
         * @throws javax.crypto.IllegalBlockSizeException
         * @throws java.security.InvalidKeyException
         * @throws javax.crypto.BadPaddingException
         * @throws java.security.NoSuchAlgorithmException
         * @throws javax.crypto.NoSuchPaddingException
         */
        public static byte[] encryption (Path file, EncryptionUtil encryptionUtil) throws IOException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
            byte[] datatocrypt = readBytesInFile(file);
            int offset = 0;
            byte[] cryptedfile = null;
            while (offset < datatocrypt.length) {
                byte[] outputBytes;
                byte[] tmp;
                if(datatocrypt.length - offset < 200 ) {
                    outputBytes = new byte[datatocrypt.length - offset];
                    System.arraycopy(datatocrypt, offset, outputBytes, 0, datatocrypt.length - offset);
                    byte[] crypt = rsaEncryption(outputBytes, encryptionUtil);
                    tmp = cryptedfile;
                    if (tmp != null) {
                        cryptedfile = new byte[tmp.length + crypt.length];
                    }
                    else cryptedfile = new byte[crypt.length];
                    if (tmp != null) {
                        System.arraycopy(tmp, 0, cryptedfile, 0, tmp.length);
                        System.arraycopy(crypt, 0, cryptedfile, tmp.length, crypt.length);
                    }
                    else {
                        System.arraycopy(crypt, 0, cryptedfile, 0, crypt.length);
                    }
                    break;
                }
                outputBytes = new byte[200];
                System.arraycopy(datatocrypt, offset, outputBytes, 0, 200);
                byte[] crypt = rsaEncryption(outputBytes, encryptionUtil);
                tmp = cryptedfile;
                if (tmp != null) {
                    cryptedfile = new byte[tmp.length + crypt.length];
                }
                else cryptedfile = new byte[crypt.length];
                if (tmp != null) {
                    System.arraycopy(tmp, 0, cryptedfile, 0, tmp.length);
                    System.arraycopy(crypt, 0, cryptedfile, tmp.length, crypt.length);
                }
                else {
                    System.arraycopy(crypt, 0, cryptedfile, 0, crypt.length);
                }
                offset += 200 ;
            }
            return cryptedfile;
        }

        /**
         * Decrypt data
         *
         * @param crypteddata Crypted data to decrypt
         * @return            The decrypted data
         * @throws NoSuchAlgorithmException
         * @throws NoSuchPaddingException
         * @throws InvalidKeyException
         * @throws IllegalBlockSizeException
         * @throws BadPaddingException
         */
        private static byte[] rsaDecryption(byte[] crypteddata, EncryptionUtil encryptionUtil) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, encryptionUtil.privateKey);
            return cipher.doFinal(crypteddata);
        }

        /**
         * Decrypt a file
         *
         * @param file       Path of the file to decrypt
         * @return           A byte array which contains the decrypted lines of the file
         * @throws IOException
         * @throws IllegalBlockSizeException
         * @throws InvalidKeyException
         * @throws BadPaddingException
         * @throws NoSuchAlgorithmException
         * @throws NoSuchPaddingException
         */
        public static byte[] decryption(Path file, EncryptionUtil encryptionUtil) throws IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
            byte[] crypteddata = readBytesInFile(file);
            int offset = 0;
            byte[] decryptedfile = null;
            while (offset < crypteddata.length) {
                byte[] outputBytes;
                byte[] tmp;
                if(crypteddata.length - offset < 200 ) {
                    outputBytes = new byte[crypteddata.length - offset];
                    System.arraycopy(crypteddata, offset, outputBytes, 0, crypteddata.length - offset);
                    byte[] decrypt = rsaDecryption(outputBytes, encryptionUtil);
                    tmp = decryptedfile;
                    if (tmp != null) {
                        decryptedfile = new byte[tmp.length + decrypt.length];
                    }
                    else decryptedfile = new byte[decrypt.length];
                    if (tmp != null) {
                        System.arraycopy(tmp, 0, decryptedfile, 0, tmp.length);
                        System.arraycopy(decrypt, 0, decryptedfile, tmp.length, decrypt.length);
                    }
                    else {
                        System.arraycopy(decrypt, 0, decryptedfile, 0, decrypt.length);
                    }
                    break;
                }
                outputBytes = new byte[200];
                System.arraycopy(crypteddata, offset, outputBytes, 0, 200);
                byte[] decrypt = rsaDecryption(outputBytes, encryptionUtil);
                tmp = decryptedfile;
                if (tmp != null) {
                    decryptedfile = new byte[decrypt.length + tmp.length];
                }
                else decryptedfile = new byte[decrypt.length];
                if (tmp != null) {
                    System.arraycopy(tmp, 0, decryptedfile, 0, tmp.length);
                    System.arraycopy(decrypt, 0, decryptedfile, tmp.length, decrypt.length);
                }
                else {
                    System.arraycopy(decrypt, 0, decryptedfile, 0, decrypt.length);
                }
                offset +=200 ;
            }
            return decryptedfile;
        }
        /**
         * Save a key in a file
         *
         * @param modulus  Modulus of the key to save
         * @param exponent Exponent of the key to save
         * @param filename File used to save the keys
         * @throws IOException
         * @throws NoSuchAlgorithmException
         */
        private static void saveKeyToFile (BigInteger modulus, BigInteger exponent, String filename) throws IOException, NoSuchAlgorithmException {
            Path path = Paths.get(filename);
            if(!Files.exists(path)) {
                Files.createFile(path);
            }
            try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filename))) {
                objectOutputStream.writeObject(modulus);
                objectOutputStream.writeObject(exponent);
            }
        }
        /**
         * Save a KeyPair in two files
         *
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeySpecException
         * @throws FileNotFoundException
         * @throws IOException
         */
        public static void saveKeyPair(EncryptionUtil encryptionUtil, String directorypath) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            RSAPublicKeySpec rsaPublicKeySpec = keyFactory.getKeySpec(encryptionUtil.publicKey, RSAPublicKeySpec.class);
            saveKeyToFile(rsaPublicKeySpec.getModulus(), rsaPublicKeySpec.getPublicExponent(), directorypath + "/public.key");
            RSAPrivateKeySpec rsaPrivateKeySpec = keyFactory.getKeySpec(encryptionUtil.privateKey, RSAPrivateKeySpec.class);
            saveKeyToFile(rsaPrivateKeySpec.getModulus(), rsaPrivateKeySpec.getPrivateExponent(), directorypath + "/private.key");
        }
        /**
         * Get a PublicKey from a file
         *
         * @param filename File where the PublicKey is saved
         * @return         The PublicKey get in the file
         * @throws IOException
         * @throws ClassNotFoundException
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeySpecException
         */
        private static PublicKey getPublicKeyFromFile (String filename) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException {
            try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename))) {
                BigInteger modulus = (BigInteger) objectInputStream.readObject();
                BigInteger exponent = (BigInteger) objectInputStream.readObject();
                RSAPublicKeySpec rsaPublicKeySpec = new RSAPublicKeySpec(modulus, exponent);
                KeyFactory keyFactory = KeyFactory.getInstance("RSA");
                return keyFactory.generatePublic(rsaPublicKeySpec);
            }
        }
        /**
         * Get a PrivateKey from a file
         *
         * @param filename File where the PrivateKey is saved
         * @return         The PrivateKey get in the file
         * @throws IOException
         * @throws ClassNotFoundException
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeySpecException
         */
        private static PrivateKey getPrivateKeyFromFile (String filename) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException {
            try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename))) {
                BigInteger modulus = (BigInteger) objectInputStream.readObject();
                BigInteger exponent = (BigInteger) objectInputStream.readObject();
                RSAPrivateKeySpec rsaPrivateKeySpec = new RSAPrivateKeySpec(modulus, exponent);
                KeyFactory keyFactory = KeyFactory.getInstance("RSA");
                return keyFactory.generatePrivate(rsaPrivateKeySpec);
            }
        }
        /**
         * Get the RSA keypair from the files
         *
         * @return The Keypair which contains the public and the private key
         * @throws IOException
         * @throws ClassNotFoundException
         * @throws NoSuchAlgorithmException
         * @throws InvalidKeySpecException
         */
        public static KeyPair getKeysFromFiles (String directorypath) throws IOException, ClassNotFoundException, NoSuchAlgorithmException, InvalidKeySpecException{
            PublicKey publicKey = getPublicKeyFromFile(directorypath + "/public.key");
            PrivateKey privateKey = getPrivateKeyFromFile(directorypath + "/private.key");
            return new KeyPair(publicKey, privateKey);
        }

        public static void main(String[] args) {
            EncryptionUtil encryptionUtil = null;
            Scanner scanner = new Scanner(System.in);
            System.out.println("Path of the keys :");
            String path = scanner.nextLine();
            try {
                encryptionUtil = new EncryptionUtil(EncryptionUtil.keyGenerate());
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            Path directorypath = Paths.get(path);
            try {
                Files.createDirectories(directorypath);
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                saveKeyPair(encryptionUtil, path);
            } catch (NoSuchAlgorithmException | InvalidKeySpecException| IOException e) {
                System.out.println("Error during the storage of the keys : " + e);
            }
            // Crypt part
            byte[] uncrypt;
            try {
                if (encryptionUtil != null) {
                    if (encryptionUtil.publicKey != null && encryptionUtil.privateKey != null) {
                        //Cryptage
                        byte[] crypt = encryption(Paths.get("filetocrypt"), encryptionUtil);
                        FileOutputStream fileOutputStream = new FileOutputStream("cryptedfile");
                        FileChannel channel = fileOutputStream.getChannel();
                        ByteBuffer byteBuffer = ByteBuffer.allocate(crypt.length * 2);
                        byteBuffer.put(crypt);
                        byteBuffer.flip();
                        channel.write(byteBuffer);
                        channel.close();
                        //Decryptage
                        uncrypt = decryption(Paths.get("cryptedfile"), encryptionUtil);
                        String v = new String(uncrypt);
                        System.out.println("END " + v);
                    }
                }
            } catch (InvalidKeyException | NoSuchAlgorithmException
                    | NoSuchPaddingException | IllegalBlockSizeException
                    | BadPaddingException | IOException e) {
                e.printStackTrace();
            }
        }
    }

我读过这个问题,通常是在使用错误的私人关键来解密或被滥用时出现的。但是我认为这里不是这样,否则我没有看到它...我对我的代码有什么问题不知道。要运行此代码,您需要一个称为" FileTocrypt"的文件。我使用字节[],然后将它们分开以chrypt并解密文件,以躲避字节问题RSA的大小。这种分裂工作正常(我在不使用RSA算法的情况下尝试使用字符串的文件)

感谢您的帮助!

您需要解密代码与加密代码不同。有很多问题,但是导致您错误的一个问题如下。由于RSA填充,您的输入块为200个字节,输出块为256个字节。因此,在解密后,您需要一次阅读256个字节,并希望获得200个字节。相反,您一次仅读取200个字节。

import java.security.*;
import java.security.interfaces.*;
import javax.crypto.Cipher;
public class RsaToy {
    public static void main(String[] args) throws Exception {
        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(1024);
        KeyPair kp = kpg.generateKeyPair();
        RSAPublicKey pub = (RSAPublicKey) kp.getPublic();
        RSAPrivateKey priv = (RSAPrivateKey) kp.getPrivate();

        Cipher c = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
        c.init(Cipher.ENCRYPT_MODE, pub);
        byte [] plain = new byte[100]; // initialize to all zero bytes
        // First encrypt: length of input (plain) is 100
        byte [] cipher = c.doFinal(plain);
        System.out.println("length of cipher is " + cipher.length);
        // Now decrypt: length of input(cipher) is 128;
        c.init(Cipher.DECRYPT_MODE, priv);
        byte [] decrypted_cipher = c.doFinal(cipher);
        System.out.println("length of decrypted cipher is " + decrypted_cipher.length);
    }
}

因此,在您的解密方法中,更改3中出现的200?到256的位置。您真的不应该为这些常数进行硬编码。

最新更新