JAVA使用加密期间使用的这3种组合分离AES密钥,初始化向量和加密文件中的数据

问题描述 投票:0回答:1

我创建了加密文件,结合了AES加密,intilizatio矢量和原始数据。所以我的加密文件包含加密形式的3个以上元素。现在在解密期间,我再次将所有这3个元素分开,而且我必须在加密期间生成的解密期间使用硬编码的AES密钥长度。

public static void encrypt() throws Exception {

        // RSA with ECB mode
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, generatePublicKey(readKeysFromFile("My_public.pub")));

        // AES key generator
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(128, srandom);
        SecretKey skey = kgen.generateKey();

        // Initialization vector 16 byte
        byte[] iv = new byte[128/8];
        srandom.nextBytes(iv);
        IvParameterSpec ivspec = new IvParameterSpec(iv);

        try (FileOutputStream out = new FileOutputStream("dataFile" + ".enc")) {
            {
                byte[] b = cipher.doFinal(skey.getEncoded());
                out.write(b);
                System.err.println("AES Key Length: " + b.length);
            }

            out.write(iv);
            System.err.println("IV Length: " + iv.length);

            Cipher ci = Cipher.getInstance("AES/CBC/PKCS5Padding");
            ci.init(Cipher.ENCRYPT_MODE, skey, ivspec);

            File inputDataFile = new File("dataFile.xml");
            try (DataInputStream in = new DataInputStream(new FileInputStream(inputDataFile))) {
                byte[] buffer = new byte[(int)inputDataFile.length()];
                in.readFully(buffer);
                in.close();
                byte[] encryptedData = ci.doFinal(buffer);
                out.write(encryptedData);
                out.close();
            }
        }

    }


public static void decryptRSAAES() throws Exception {

        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, generatePrivateKey(readKeysFromFile("My_private.key")));

        File file2 = new File("dataFile.enc");
        RandomAccessFile raf = new RandomAccessFile(file2, "r");

        // length of AES key 
        byte[] c = new byte[384];

        // read the AES key from file
        raf.read(c, 0 , 384);
        byte[] fileContent = Files.readAllBytes(file2.toPath());
        byte[] keyb = cipher.doFinal(c);
        SecretKeySpec skey = new SecretKeySpec(keyb, "AES");

        // read the initializatoin vector
        byte[] iv = new byte[128/8];
        raf.seek(384);
        raf.read(iv);
        IvParameterSpec ivspec = new IvParameterSpec(iv);

        raf.seek(400);

        Cipher ci = Cipher.getInstance("AES/CBC/PKCS5Padding");
        ci.init(Cipher.DECRYPT_MODE, skey, ivspec);
        try (FileOutputStream out = new FileOutputStream("decryptedFileTest"+".xml")){

            byte[] decryptedData = ci.doFinal(fileContent);
            out.write(decryptedData);
            out.close();
            //processDecryptFile(ci, in, out);
        }
    }

实际结果:使用AES密钥和原始纯文本数据创建解密文件

预期结果:在输出中仅写入原始明文数据,删除AES和初始化向量。

java security encryption cryptography rsa
1个回答
1
投票

让我们简化一下,使用Java qazxsw poi类中新增的函数:

InputStream

正如您所看到的,代码现在更像是镜像。我只是复制了加密代码,然后对其进行了更改。正如您所看到的,现在依靠public static void encrypt(RSAPublicKey publicKey) throws Exception { try (FileOutputStream out = new FileOutputStream("dataFile" + ".enc")) { // --- RSA using PKCS#1 v1.5 padding Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); // --- AES key generator KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); SecretKey skey = kgen.generateKey(); // --- write encrypted AES key byte[] encryptedSKey = cipher.doFinal(skey.getEncoded()); out.write(encryptedSKey); // --- Initialization vector 16 byte SecureRandom srandom = new SecureRandom(); byte[] iv = new byte[128/8]; srandom.nextBytes(iv); IvParameterSpec ivspec = new IvParameterSpec(iv); // --- write IV out.write(iv); // --- initialize AES cipher Cipher ci = Cipher.getInstance("AES/CBC/PKCS5Padding"); ci.init(Cipher.ENCRYPT_MODE, skey, ivspec); // --- convert file by copying to memory try (FileInputStream in = new FileInputStream("dataFile.xml")) { byte[] buffer = in.readAllBytes(); byte[] encryptedData = ci.doFinal(buffer); out.write(encryptedData); } } } public static void decrypt(RSAPrivateKey privateKey) throws Exception { try (FileInputStream in = new FileInputStream("dataFile" + ".enc")) { // --- RSA using PKCS#1 v1.5 padding Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.DECRYPT_MODE, privateKey); // --- read encrypted AES key byte[] encryptedSKey = in.readNBytes(determineEncryptionSizeInBytes(privateKey)); byte[] decryptedSKey = cipher.doFinal(encryptedSKey); SecretKey skey = new SecretKeySpec(decryptedSKey, "AES"); // --- Initialization vector 16 byte byte[] iv = in.readNBytes(128 / Byte.SIZE); IvParameterSpec ivspec = new IvParameterSpec(iv); // --- initialize AES cipher Cipher ci = Cipher.getInstance("AES/CBC/PKCS5Padding"); ci.init(Cipher.DECRYPT_MODE, skey, ivspec); // --- convert file by copying to memory File outputDataFile = new File("dataFile.xml2"); try (FileOutputStream out = new FileOutputStream(outputDataFile)) { byte[] buffer = in.readAllBytes(); byte[] decryptedData = ci.doFinal(buffer); out.write(decryptedData); } } } private static int determineEncryptionSizeInBytes(RSAPrivateKey privateKey) { return (privateKey.getModulus().bitLength() + Byte.SIZE - 1) / Byte.SIZE; } public static void main(String[] args) throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(384 * Byte.SIZE); KeyPair pair = kpg.generateKeyPair(); encrypt((RSAPublicKey) pair.getPublic()); decrypt((RSAPrivateKey) pair.getPrivate()); } (自Java 9起)和InputStream#readAllBytes()(自Java 11起)使用更少的类。

请注意,您通常希望使用较小的缓冲区来流式传输文件。由于整个明文和密文当前都是缓冲的,因此您的应用程序使用的内存比所需的多得多。要使用流加密数据,您可以依赖InputStream#readNBytes()CipherInputStream

不用说异常处理需要改进,我只是简单地看一下解决当前问题的最佳方法。当你的工作正常工作(让事情正常,做好事情,优化事情)时,请再看看它。

© www.soinside.com 2019 - 2024. All rights reserved.