AES+ RSA加密提供垃圾字符

发布于 2025-02-08 17:23:35 字数 7741 浏览 2 评论 0原文

我正在尝试使用AES和RSA对XML文件进行加密,但解密后获得一些垃圾字符。

package com.example.demo.junk;


import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.Duration;
import java.time.Instant;

public class EncryptionPOC {

    private static IvParameterSpec getIv() {
        SecureRandom srandom = new SecureRandom();
        byte[] iv = new byte[128 / 8];
        srandom.nextBytes(iv);
        IvParameterSpec ivspec = new IvParameterSpec(iv);
        //Save it.
        try (FileOutputStream fos = new FileOutputStream("iv.file")) {
            fos.write(iv);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return ivspec;
    }

    private static SecretKey getSecretKey(String algorithm) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance(algorithm);
            kgen.init(128);
            return kgen.generateKey();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static PrivateKey loadPrivateKey() {
        try {
            byte[] bytes = Files.readAllBytes(Paths.get("private.key"));
            PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey pvt = kf.generatePrivate(ks);
            return pvt;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static KeyPair getKeyPair(String algorithm) {
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
            kpg.initialize(2048);
            KeyPair keyPair = kpg.generateKeyPair();
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static void writeContent(IvParameterSpec ivspec, PrivateKey privateKey, SecretKey secretKey) {

        try {
            FileOutputStream out = new FileOutputStream("Manifest-Encrypted.enc");
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] b = cipher.doFinal(secretKey.getEncoded());
            out.write(b);

            Cipher ci = Cipher.getInstance("AES/CBC/ISO10126Padding");
            ci.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
            try (FileInputStream in = new FileInputStream("Manifest1.xml")) {
                processFileForAes(ci, in, out);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void readContent() {

        try {
            byte[] bytes = Files.readAllBytes(Paths.get("public.pub"));
            X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PublicKey pub = kf.generatePublic(ks);

            FileInputStream in = new FileInputStream("Manifest-Encrypted.enc");
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, pub);
            byte[] b = new byte[256];
            in.read(b);
            byte[] keyb = cipher.doFinal(b);
            SecretKeySpec skey = new SecretKeySpec(keyb, "AES");

            byte[] iv = new byte[128 / 8];
            FileInputStream fis = new FileInputStream("iv.file");
            fis.read(iv);
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Cipher ci = Cipher.getInstance("AES/CBC/ISO10126Padding");
            ci.init(Cipher.DECRYPT_MODE, skey, ivspec);
            try (FileOutputStream out = new FileOutputStream("Manifest2.xml")) {
                processFile(ci, in, out);
                readFile("Manifest2.xml");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void readFile(String fileName) throws IOException {
        try(FileInputStream out = new FileInputStream(fileName)) {
            int i;

            while ((i = out.read()) != -1) {
                System.out.print((char) i);
            }
            System.out.println();
        }
    }


    //  ////////////////////////////////////////////////////////////////////////////////////////
    private static void saveKeypair(KeyPair keyPair) {
        try (FileOutputStream out = new FileOutputStream("private.key")) {
            out.write(keyPair.getPrivate().getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        try (FileOutputStream out = new FileOutputStream("public.pub")) {
            out.write(keyPair.getPublic().getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    public static void RSAEncryption(PrivateKey privateKey) {

        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);

            try (FileOutputStream out = new FileOutputStream("Doc-enc.des");
                 FileInputStream in = new FileInputStream("File1.deb")) {
                processFile(cipher, in, out);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private static void processFile(Cipher ci, InputStream in, OutputStream out)
            throws javax.crypto.IllegalBlockSizeException,
            javax.crypto.BadPaddingException,
            java.io.IOException {
        byte[] ibuf = new byte[1024];
        int len;
        while ((len = in.read(ibuf)) != -1) {
            byte[] obuf = ci.update(ibuf, 0, len);
            if (obuf != null)
            {
                out.write(obuf);
            }
        }
        byte[] obuf = ci.doFinal();
        if (obuf != null) out.write(obuf);
    }


    static private void processFileForAes(Cipher ci, InputStream in, OutputStream out)
            throws javax.crypto.IllegalBlockSizeException,
            javax.crypto.BadPaddingException,
            java.io.IOException {
        byte[] ibuf = new byte[1024];
        int len;
        while ((len = in.read(ibuf)) != -1) {
            byte[] obuf = ci.update(ibuf, 0, len);
            if (obuf != null) out.write(obuf);
        }
        byte[] obuf = ci.doFinal();
        if (obuf != null) out.write(obuf);
    }

    public static void main(String[] args) {
//      Instant in1 = Instant.now();
//      KeyPair keyPair = getKeyPair("RSA");
//      saveKeypair(keyPair);
//      RSAEncryption(keyPair.getPrivate());
//      Instant in2 = Instant.now();
//
//      Duration duration = Duration.between(in1, in2);
//      System.out.println(duration.toMillis());

        //KeyPair keyPair = getKeyPair("RSA");
        //saveKeypair(keyPair);
//        Instant in1 = Instant.now();
//        SecretKey secretKey = getSecretKey("AES");
//        IvParameterSpec ivs = getIv();
//        PrivateKey privateKey = loadPrivateKey();
//        writeContent(ivs, privateKey, secretKey);
//        Instant in2 = Instant.now();
        readContent();
        //Duration duration = Duration.between(in1, in2);
        //System.out.println(duration.toMillis());

    }

}

输出:

#y```

** 这个问题的根本原因?

I am trying to encrypt and decrypt the XML file using AES and RSA but getting some junk characters after decryption.

package com.example.demo.junk;


import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.Duration;
import java.time.Instant;

public class EncryptionPOC {

    private static IvParameterSpec getIv() {
        SecureRandom srandom = new SecureRandom();
        byte[] iv = new byte[128 / 8];
        srandom.nextBytes(iv);
        IvParameterSpec ivspec = new IvParameterSpec(iv);
        //Save it.
        try (FileOutputStream fos = new FileOutputStream("iv.file")) {
            fos.write(iv);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return ivspec;
    }

    private static SecretKey getSecretKey(String algorithm) {
        try {
            KeyGenerator kgen = KeyGenerator.getInstance(algorithm);
            kgen.init(128);
            return kgen.generateKey();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static PrivateKey loadPrivateKey() {
        try {
            byte[] bytes = Files.readAllBytes(Paths.get("private.key"));
            PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PrivateKey pvt = kf.generatePrivate(ks);
            return pvt;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static KeyPair getKeyPair(String algorithm) {
        try {
            KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm);
            kpg.initialize(2048);
            KeyPair keyPair = kpg.generateKeyPair();
            return keyPair;
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    private static void writeContent(IvParameterSpec ivspec, PrivateKey privateKey, SecretKey secretKey) {

        try {
            FileOutputStream out = new FileOutputStream("Manifest-Encrypted.enc");
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] b = cipher.doFinal(secretKey.getEncoded());
            out.write(b);

            Cipher ci = Cipher.getInstance("AES/CBC/ISO10126Padding");
            ci.init(Cipher.ENCRYPT_MODE, secretKey, ivspec);
            try (FileInputStream in = new FileInputStream("Manifest1.xml")) {
                processFileForAes(ci, in, out);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void readContent() {

        try {
            byte[] bytes = Files.readAllBytes(Paths.get("public.pub"));
            X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            PublicKey pub = kf.generatePublic(ks);

            FileInputStream in = new FileInputStream("Manifest-Encrypted.enc");
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, pub);
            byte[] b = new byte[256];
            in.read(b);
            byte[] keyb = cipher.doFinal(b);
            SecretKeySpec skey = new SecretKeySpec(keyb, "AES");

            byte[] iv = new byte[128 / 8];
            FileInputStream fis = new FileInputStream("iv.file");
            fis.read(iv);
            IvParameterSpec ivspec = new IvParameterSpec(iv);

            Cipher ci = Cipher.getInstance("AES/CBC/ISO10126Padding");
            ci.init(Cipher.DECRYPT_MODE, skey, ivspec);
            try (FileOutputStream out = new FileOutputStream("Manifest2.xml")) {
                processFile(ci, in, out);
                readFile("Manifest2.xml");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void readFile(String fileName) throws IOException {
        try(FileInputStream out = new FileInputStream(fileName)) {
            int i;

            while ((i = out.read()) != -1) {
                System.out.print((char) i);
            }
            System.out.println();
        }
    }


    //  ////////////////////////////////////////////////////////////////////////////////////////
    private static void saveKeypair(KeyPair keyPair) {
        try (FileOutputStream out = new FileOutputStream("private.key")) {
            out.write(keyPair.getPrivate().getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        try (FileOutputStream out = new FileOutputStream("public.pub")) {
            out.write(keyPair.getPublic().getEncoded());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }


    public static void RSAEncryption(PrivateKey privateKey) {

        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);

            try (FileOutputStream out = new FileOutputStream("Doc-enc.des");
                 FileInputStream in = new FileInputStream("File1.deb")) {
                processFile(cipher, in, out);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private static void processFile(Cipher ci, InputStream in, OutputStream out)
            throws javax.crypto.IllegalBlockSizeException,
            javax.crypto.BadPaddingException,
            java.io.IOException {
        byte[] ibuf = new byte[1024];
        int len;
        while ((len = in.read(ibuf)) != -1) {
            byte[] obuf = ci.update(ibuf, 0, len);
            if (obuf != null)
            {
                out.write(obuf);
            }
        }
        byte[] obuf = ci.doFinal();
        if (obuf != null) out.write(obuf);
    }


    static private void processFileForAes(Cipher ci, InputStream in, OutputStream out)
            throws javax.crypto.IllegalBlockSizeException,
            javax.crypto.BadPaddingException,
            java.io.IOException {
        byte[] ibuf = new byte[1024];
        int len;
        while ((len = in.read(ibuf)) != -1) {
            byte[] obuf = ci.update(ibuf, 0, len);
            if (obuf != null) out.write(obuf);
        }
        byte[] obuf = ci.doFinal();
        if (obuf != null) out.write(obuf);
    }

    public static void main(String[] args) {
//      Instant in1 = Instant.now();
//      KeyPair keyPair = getKeyPair("RSA");
//      saveKeypair(keyPair);
//      RSAEncryption(keyPair.getPrivate());
//      Instant in2 = Instant.now();
//
//      Duration duration = Duration.between(in1, in2);
//      System.out.println(duration.toMillis());

        //KeyPair keyPair = getKeyPair("RSA");
        //saveKeypair(keyPair);
//        Instant in1 = Instant.now();
//        SecretKey secretKey = getSecretKey("AES");
//        IvParameterSpec ivs = getIv();
//        PrivateKey privateKey = loadPrivateKey();
//        writeContent(ivs, privateKey, secretKey);
//        Instant in2 = Instant.now();
        readContent();
        //Duration duration = Duration.between(in1, in2);
        //System.out.println(duration.toMillis());

    }

}

Output:

** �#y`�X�&f(�{��declaration">1176**

For some files, I am getting correct output but for some, it is giving junk characters in beginning. What could be the possible root cause of this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

弄潮 2025-02-15 17:23:35

主要问题是,当您创建密文时,您似乎将IV写入单独的文件,并假设将其写入文件时将其写入文件的前面。

此外,即使您使用流API从正确的位置获取内容字节,也应该知道Java inputStream.Read()可能不会读取字节的缓冲区值。相反,您应该使用 inputStream#readnbytes(int) 也获得了更多简洁的代码。

我还强烈建议您适当处理您的例外情况,并使用尝试 -with-resources。

The main issue is that you seem to write the IV to a separate file when you create your ciphertext, and assume that is written to the front of the file when deciphering it.

Furthermore, even if you use the streaming API to get to the content bytes from the right location, you should be aware that Java InputStream.read() may not read a buffer-worth of bytes. Instead you should use InputStream#readNBytes(int) to get more concise code as well.

I'd also strongly advice you to handle your exceptions appropriately and use try-with-resources.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文