IK.AM

@making's tech note


OpenSSLで作成したRSAの鍵を使ってJavaで暗号化・復号するサンプル

🗃 {Programming/Java/java/security}
🏷 Java 🏷 OpenSSL 
🗓 Updated at 2015-03-19T07:55:40Z  🗓 Created at 2015-03-19T07:55:40Z   🌎 English Page

メモ

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

public class RSADemo {
    public static void main(String[] args) {
        // まずはJava APIで作成したRSAの秘密鍵と公開鍵を使って、Javaで暗復号する例
        new RSADemo().generateKeysByJava();
        // OpenSSLで作成したRSAの秘密鍵と公開鍵を使って、Javaで暗号化、OpenSSLで復号する例
        new RSADemo().useOpenSSLDecryption();
        // OpenSSLで作成したRSAの秘密鍵と公開鍵を使って、OpenSSLで暗号化、Javaで復号する例
        new RSADemo().useOpenSSLEncryption();
    }

    public void generateKeysByJava() {
        try {

            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
            generator.initialize(2048);// 鍵の長さ(bit)
            KeyPair keyPair = generator.generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();

            byte[] encrypted = encryptByPublicKey("Hello World!", publicKey);
            System.out.println(Base64.getEncoder().encodeToString(encrypted));
            String decrypted = decryptByPrivateKey(encrypted, privateKey);
            System.out.println(decrypted);
        } catch (NoSuchAlgorithmException ignored) {
            throw new IllegalStateException("Should not be happend!", ignored);
        }

    }

    public void useOpenSSLDecryption() {
        // [プログラム実行前]
        // DER形式で秘密鍵を生成
        // openssl genrsa -out hoge.pem 2048
        // 秘密鍵をJavaで読めるように PKCS #8 形式かつ DER 形式に変換
        // openssl pkcs8 -topk8 -nocrypt -in hoge.pem -out private.pk8 -outform DER
        // 秘密鍵からDER形式公開鍵生成
        // openssl rsa -pubout -in hoge.pem -out public.der -outform DER

        // [プログラム実行後]
        // 秘密鍵で復号
        // openssl rsautl -decrypt -inkey hoge.pem -in encryptedByJava.txt
        try {
            KeySpec publicKeySpec = new X509EncodedKeySpec(Files
                    .readAllBytes(Paths.get("public.der")));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);

            byte[] encrypted = encryptByPublicKey("Hello World!", publicKey);

            Files.write(Paths.get("encryptedByJava.txt"), encrypted);
            System.out.println("Please execute the following command:");
            System.out
                    .println("openssl rsautl -decrypt -inkey hoge.pem -in encryptedByJava.txt");
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        } catch (NoSuchAlgorithmException ignored) {
            throw new IllegalStateException("Should not be happend!", ignored);
        } catch (InvalidKeySpecException e) {
            throw new IllegalArgumentException(e);
        }
    }

    public void useOpenSSLEncryption() {
        // [プログラム実行前]
        // DER形式で秘密鍵を生成
        // openssl genrsa -out hoge.pem 2048
        // 秘密鍵をJavaで読めるように PKCS #8 形式かつ DER 形式に変換
        // openssl pkcs8 -topk8 -nocrypt -in hoge.pem -out private.pk8 -outform DER
        // 秘密鍵からDER形式公開鍵生成
        // openssl rsa -pubout -in hoge.pem -out public.der -outform DER
        // 公開鍵で暗号
        // echo Hello!! | openssl rsautl -encrypt -keyform DER -pubin -inkey public.der -out ecryptedByOpenSSL.txt
        try {
            KeySpec privateKeySpec = new PKCS8EncodedKeySpec(Files
                    .readAllBytes(Paths.get("private.pk8")));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

            String decrypted = decryptByPrivateKey(Files.readAllBytes(Paths
                    .get("ecryptedByOpenSSL.txt")), privateKey);
            System.out.println(decrypted);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        } catch (NoSuchAlgorithmException ignored) {
            throw new IllegalStateException("Should not be happend!", ignored);
        } catch (InvalidKeySpecException e) {
            throw new IllegalArgumentException(e);
        }
    }

    // 暗号化・復号用のメソッド

    /**
     * 平文を公開鍵で暗号化し、バイト配列返却
     */
    public byte[] encryptByPublicKey(String clearText, PublicKey publicKey) {
        try {
            // 暗復号のためのCipher生成
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            // 暗号化
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(clearText.getBytes());
        } catch (NoSuchAlgorithmException | NoSuchPaddingException ignored) {
            throw new IllegalStateException("Should not be happened!", ignored);
        } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * バイト配列を秘密鍵で暗号化し、平文を返却
     */
    public String decryptByPrivateKey(byte[] encrypted, PrivateKey privateKey) {
        try {
            // 暗復号のためのCipher生成
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            // 暗号化
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] decrypted = cipher.doFinal(encrypted);
            return new String(decrypted);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException ignored) {
            throw new IllegalStateException("Should not be happened!", ignored);
        } catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            throw new IllegalArgumentException(e);
        }
    }
}

✒️️ Edit  ⏰ History  🗑 Delete