如何读取public/private个base64加密密钥文件?

How to read public/private key files for encryption when they are Base64?

我正在尝试在 Java 中学习 RSA public/private 密钥对加密。

我可以使用下面的代码。它生成一个私钥和public密钥对,将密钥写入磁盘,使用磁盘中的public密钥加密字符串,使用磁盘中的私钥解密,然后输出解密后的字符串。

一切都很好。

接下来是,我希望密钥文件是可读的“-----BEGIN RSA PRIVATE KEY-----”类型的密钥文件...所以我写了方法saveKeysToDiskBase64.

问题是,当我使用 saveKeysToDiskBase64 写入文件时,读取关键文件的方法失败了。即loadPrivateKeyloadPublicKey无法读取Base64文件。

我错过了什么?

public class EncryptionTest1 {


    public void execute() throws Exception {
        
        String filename = "test1";
        
        KeyPair keyPair = EncryptionUtil.generateKeyPair();
        EncryptionUtil.saveKeysToDisk(filename, keyPair);
        // EncryptionUtil.saveKeysToDiskBase64(filename, keyPair);

        String pvtKeyFilename = filename+".key";
        String pubKeyFilename = filename+".pub";
        
        PrivateKey privateKey = EncryptionUtil.loadPrivateKey(pvtKeyFilename);
        byte[] bPrivateKey = privateKey.getEncoded();

        PublicKey publicKey = EncryptionUtil.loadPublicKey(pubKeyFilename);
        byte[] bPublicKey = publicKey.getEncoded();

        String sOriginal = "hi this is plain text";

        byte[] encryptedData = EncryptionUtil.encrypt(bPublicKey, sOriginal.getBytes());
        byte[] decryptedData = EncryptionUtil.decrypt(bPrivateKey, encryptedData);
        
        String sEncrypted = new String(encryptedData);
        String sDecrypted = new String(decryptedData);
        
        System.out.println("sOriginal = "+sOriginal);
        System.out.println("sEncrypted = "+sEncrypted);
        System.out.println("sDecryptedData = "+sDecrypted);

    }
    
    
    public static void main(String[] args) {
        try {
            new EncryptionTest1().execute();
        } catch (Exception x) {
            x.printStackTrace();
        }
    }
    
}

...

public class EncryptionUtil {

    
    private static final String ALGORITHM = "RSA";

    
    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {

        KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);

        SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");

        // 2048 is keysize
        keyGen.initialize(2048, random);

        KeyPair generateKeyPair = keyGen.generateKeyPair();
        
        return generateKeyPair;
    }
    
    public static void saveKeysToDisk(String name, KeyPair keyPair) {
        try {
            String privateFileName = name+".key";
            FileOutputStream out1 = new FileOutputStream(privateFileName);
            out1.write(keyPair.getPrivate().getEncoded());
            out1.close();
             
            String publicFileName = name+".pub";
            FileOutputStream out2 = new FileOutputStream(publicFileName);
            out2.write(keyPair.getPublic().getEncoded());
            out2.close();
        } catch (Exception x) {
            x.printStackTrace();
        }
    }


    public static void saveKeysToDiskBase64(String name, KeyPair keyPair) {
        try {

            Base64.Encoder encoder = Base64.getEncoder();
             
            String privateFileName = name+".key";
            Writer out = new FileWriter(privateFileName);
            out.write("-----BEGIN RSA PRIVATE KEY-----\n");
            out.write(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
            out.write("\n-----END RSA PRIVATE KEY-----\n");
            out.close();            

            String publicFileName = name+".pub";
            Writer out2 = new FileWriter(publicFileName);
            out2.write("-----BEGIN RSA PUBLIC KEY-----\n");
            out2.write(encoder.encodeToString(keyPair.getPublic().getEncoded()));
            out2.write("\n-----END RSA PUBLIC KEY-----\n");
            out2.close();           

        } catch (Exception x) {
            x.printStackTrace();
        }
    }

    
    public static PrivateKey loadPrivateKey(String keyFile) {
        PrivateKey pvt = null;
        try {
            /* Read all bytes from the private key file */
            Path path = Paths.get(keyFile);
            byte[] bytes = Files.readAllBytes(path);

            /* Generate private key. */
            PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            pvt = kf.generatePrivate(ks);
        } catch (Exception x) {
            x.printStackTrace();
        }
        
        return pvt;
    }
    
    public static PublicKey loadPublicKey(String keyFile) {
        PublicKey pub = null;
        try {
            /* Read all the public key bytes */
            Path path = Paths.get(keyFile);
            byte[] bytes = Files.readAllBytes(path);
            
            /* Generate public key. */
            X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            pub = kf.generatePublic(ks);
        } catch (Exception x) {
            x.printStackTrace();
        }
        return pub;
    }
    
    
    
    


    public static byte[] encrypt(byte[] publicKey, byte[] inputData) throws Exception {

        PublicKey key = KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(publicKey));

        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);

        byte[] encryptedBytes = cipher.doFinal(inputData);

        return encryptedBytes;
    }

    public static byte[] decrypt(byte[] privateKey, byte[] inputData) throws Exception {

        PrivateKey key = KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(privateKey));

        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);

        byte[] decryptedBytes = cipher.doFinal(inputData);

        return decryptedBytes;
    }
    
}

非常感谢@President James K. Polk 在评论中给了我正确的答案。

这是对我有用的 Base64 相关代码...

private static String PRIVATE_HEADER = "-----BEGIN PRIVATE KEY-----\n";
private static String PRIVATE_FOOTER = "\n-----END PRIVATE KEY-----\n";
private static String PUBLIC_HEADER = "-----BEGIN PUBLIC KEY-----\n";
private static String PUBLIC_FOOTER = "\n-----END PUBLIC KEY-----\n";


public static void saveKeysToDiskBase64(String name, KeyPair keyPair) {
    try {

        Base64.Encoder encoder = Base64.getEncoder();
         
        String privateFileName = name+".key";
        Writer out = new FileWriter(privateFileName);
        out.write(PRIVATE_HEADER);
        out.write(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
        out.write(PRIVATE_FOOTER);
        out.close();            

        String publicFileName = name+".pub";
        Writer out2 = new FileWriter(publicFileName);
        out2.write(PUBLIC_HEADER);
        out2.write(encoder.encodeToString(keyPair.getPublic().getEncoded()));
        out2.write(PUBLIC_FOOTER);
        out2.close();           

    } catch (Exception x) {
        x.printStackTrace();
    }
}

public static PrivateKey loadPrivateKeyBase64(String keyFile) {
    PrivateKey pvt = null;
    try {
        /* Read all bytes from the private key file */
        Path path = Paths.get(keyFile);
        byte[] bytes = Files.readAllBytes(path);

        String s = new String(bytes);
        s = s.replace(PRIVATE_HEADER, "");
        s = s.replace(PRIVATE_FOOTER, "");
        
        bytes = Base64.getDecoder().decode(s.getBytes());

        /* Generate private key. */
        PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        pvt = kf.generatePrivate(ks);
    } catch (Exception x) {
        x.printStackTrace();
    }
    
    return pvt;
}

public static PublicKey loadPublicKeyBase64(String keyFile) {
    PublicKey pub = null;
    try {
        /* Read all the public key bytes */
        Path path = Paths.get(keyFile);
        byte[] bytes = Files.readAllBytes(path);
        
        String s = new String(bytes);
        s = s.replace(PUBLIC_HEADER, "");
        s = s.replace(PUBLIC_FOOTER, "");
        
        bytes = Base64.getDecoder().decode(s.getBytes());
        
        /* Generate public key. */
        X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        pub = kf.generatePublic(ks);
    } catch (Exception x) {
        x.printStackTrace();
    }
    return pub;
}