メモ
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);
}
}
}