简体   繁体   中英

How to save and re-use keypairs in Java asymmetric encryption?

I've written code that generates the key pairs, but was wondering if there's any way to save and re-use them?

Here is the code that generaes the pair:

public static void main(String[] args) throws Exception {

    String plainText = "Hello world";

    Map<String, Object> keys = getRSAKeys();

    PrivateKey privateKey = (PrivateKey) keys.get("private");
    PublicKey publicKey = (PublicKey) keys.get("public");

    System.out.println(privateKey.getEncoded());

    System.out.println(publicKey.getEncoded());



    String encrypted = encryptMessage(plainText, privateKey);


    System.out.println(encrypted);

    String decrypted = decryptMessage(plainText, publicKey, encrypted);

    System.out.println(decrypted);

}

private static Map<String, Object> getRSAKeys() throws Exception {

    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048);
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    PrivateKey privateKey = keyPair.getPrivate();
    PublicKey publicKey = keyPair.getPublic();
    Map<String, Object> keys = new HashMap<String, Object>();
    keys.put("private", privateKey);
    keys.put("public", publicKey);

    return keys;

}

https://docs.oracle.com/javase/tutorial/security/apisign/step2.html -- good entry point.

Also here is some example code to do exactly what you want:

package mx.playground.security;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.Cipher;

public class AppForStackOverflow {

    public static final int KEY_SIZE = 2048;

    public static final String PUBLIC_KEY_X509 = "C:\\workspace\\rsa-pair\\public-key";
    public static final String PUBLIC_KEY_PKCS1 = "C:\\workspace\\rsa-pair\\public-key-pkcs1";
    public static final String PUBLIC_KEY_PEM = "C:\\workspace\\rsa-pair\\public-key-pem";

    public static final String PRIVATE_KEY_PKCS8 = "C:\\workspace\\rsa-pair\\private-key";
    public static final String PRIVATE_KEY_PKCS1 = "C:\\workspace\\rsa-pair\\private-key-pkcs1";
    public static final String PRIVATE_KEY_PEM = "C:\\workspace\\rsa-pair\\private-key-pem";

    public static final String SIGNATURE_PATH = "C:\\workspace\\rsa-pair\\signature";

    public static final String PRIVATE_KEY_PATH = PRIVATE_KEY_PKCS8;
    public static final String PUBLIC_KEY_PATH = PUBLIC_KEY_X509;

    public static void main(String[] args) {
        generateRsaKeysPair();
        encryptDecryptTest();

        // symmetric encryption example, use it to store your Private Key in safe manner
        String message = "test message";
        String rightPass = "0123456789ABCDEF"; // for AES password should be at least 16 chars 
        String wrongPass = "zzz";

        byte[] encryptedMessage = symmetricEncrypt(message.getBytes(), rightPass);
        System.out.print(new String(encryptedMessage));

        byte[] decryptedMessage = symmetricDecrypt(encryptedMessage, rightPass);
        System.out.println(new String(decryptedMessage));

    }       

    public static void generateRsaKeysPair() {
        try {
            KeyPairGeneratorJdk kpg = new KeyPairGeneratorJdk(KEY_SIZE, "RSA");

            PublicKey  publicKey  = kpg.getPublicKey();
            PrivateKey privateKey = kpg.getPrivateKey();

            save(PUBLIC_KEY_PATH,  publicKey.getEncoded());
            save(PRIVATE_KEY_PATH, privateKey.getEncoded());
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute generateRsaKeysPair()", e);           
        }
    }

    public static void encryptDecryptTest() {
        try {
            byte[] privateKeyBytes = read(PRIVATE_KEY_PATH);
            byte[] publicKeyBytes = read(PUBLIC_KEY_PATH);

            KeyFactory kf = KeyFactory.getInstance("RSA");
            PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            PrivateKey privateKey = kf.generatePrivate(privateKeySpec);

            X509EncodedKeySpec spec = new X509EncodedKeySpec(publicKeyBytes);
            PublicKey publicKey = kf.generatePublic(spec);

            Cipher cipher = Cipher.getInstance("RSA");

            // doing encryption
            String message = "test message";
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] encodedMessage = cipher.doFinal(message.getBytes("UTF-8"));
            System.out.println("ENCRYPTED: " + new String(encodedMessage));

            // doing decryption
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] decodedMessage = cipher.doFinal(encodedMessage);
            System.out.println("DECRYPTED: " + new String(decodedMessage));
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute encryptDecryptTest()", e);
        }
    }

    private static void save(String path, byte[] data) {
        try {
            File file = new File(path);
            file.getParentFile().mkdirs();

            try (FileOutputStream fos = new FileOutputStream(file)){
                fos.write(Base64.getEncoder().encode(data));
                fos.flush();
            };
        } catch (IOException e) {
            throw new RuntimeException("Failed to save data to file: " + path, e);
        }
    }

    private static byte[] read(String path) {
        try {
            return Base64.getDecoder().decode(Files.readAllBytes(new File(path).toPath()));
        } catch (IOException e) {
            throw new RuntimeException("Failed to read data from file: " + path, e);
        }
    }   

    /*
     * Use this to encrypt your private key before saving it to disk  
     */
    public static byte[] symmetricEncrypt(byte[] data, String password) {
        try {
            SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            byte[] result = cipher.doFinal(data);
            return result;
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute symmetricEncrypt()", e);
        }
    }

    public static byte[] symmetricDecrypt(byte[] data, String password) {
        try {
            SecretKeySpec secretKey = new SecretKeySpec(password.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            byte[] result = cipher.doFinal(data);
            return result;
        } catch (Exception e) {
            throw new RuntimeException("Failed to execute symmetricEncrypt()", e);
        }
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM