今回は OpenSSL で作成する RSA鍵です。
RSA鍵作成
PEM形式の秘密鍵を生成する → private_key.pem
openssl genrsa -out private_key.pem 1024
パスワード付きの秘密鍵にするなら、
openssl genrsa -aes256 2048 > private_key.pem
で、入力求められるのでパスフレーズを入れます
PKC8/DER形式に変換する → private_key.pk8
Java で複合する場合の秘密鍵です
openssl pkcs8 -in private_key.pem -topk8 -nocrypt -outform DER -out private_key.pk8
DER形式の公開鍵を生成する → public_key.der
openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der
Java で暗号化
String str = "サンプル1234_ABCD"; try{ KeyFactory keyfactory = KeyFactory.getInstance("RSA"); // 秘密鍵 KeySpec keyspec = new PKCS8EncodedKeySpec(readFile("private_key.pk8")); Key secret_key = keyfactory.generatePrivate(keyspec); // 公開鍵 keyspec = new X509EncodedKeySpec(readFile("public_key.der")); Key public_key = keyfactory.generatePublic(keyspec); String encryptString = Base64.getEncoder() .encodeToString(encrypt(str, public_key)); System.out.println(encryptString); String str = new String( decrypt(Base64.getDecoder() .decode(encryptString), secret_key) ); System.out.println(str); // 暗号化文字列 Base64 ファイル出力 try(FileWriter fw=new FileWriter("encrypt.txt", StandardCharsets.UTF_8)){ fw.write(encryptString); } }catch(NoSuchAlgorithmException e){ e.printStackTrace(); }catch(IOException e){ e.printStackTrace(); }catch(InvalidKeySpecException e){ e.printStackTrace(); }catch(InvalidKeyException e){ e.printStackTrace(); }catch(NoSuchPaddingException e){ e.printStackTrace(); }catch(IllegalBlockSizeException e){ e.printStackTrace(); }catch(BadPaddingException e){ e.printStackTrace(); }
static byte[] readFile(String path) throws IOException{ try(InputStream in = new FileInputStream(path)){ byte[] data = new byte[in.available()]; in.read(data); in.close(); return data; } } /* 暗号化 */ static byte[] encrypt(String target, Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException , IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); cipher.init(Cipher.ENCRYPT_MODE, key); return cipher.doFinal(target.getBytes()); } /* 複合化 */ static byte[] decrypt(byte[] data, Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException , IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); cipher.init(Cipher.DECRYPT_MODE, key); return cipher.doFinal(data); }
Python で複合
準備として、pycrypto は古いので
pycryptodome をインストールしておきます。
pip install pycryptodome
https://www.pycryptodome.org/en/latest/
秘密鍵 PEM ファイル使用して複合する場合
-----BEGIN RSA PRIVATE KEY-----
と
-----END RSA PRIVATE KEY-----
の間を鍵として読込みます。
def rsa_decrypt(s): with open("private_key.pem") as f: from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 from base64 import b64decode pemkey = b64decode(f.read().replace("-----BEGIN RSA PRIVATE KEY-----", "").replace("-----END RSA PRIVATE KEY-----", "").replace("\n", "")) rsakey = RSA.importKey(pemkey) cipher = PKCS1_v1_5.new(rsakey) text = cipher.decrypt(b64decode(s), "Error while decrypt") return text.decode('utf-8')
Javaで複合時と同じ秘密鍵 pk8 ファイルから複合する場合
def rsa_decrypt(s): with open("private_key.pk8", "rb") as f: from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 from base64 import b64decode rsakey = RSA.importKey(f.read()) cipher = PKCS1_v1_5.new(rsakey) text = cipher.decrypt(b64decode(s), "Error while decrypt") return text.decode('utf-8')
暗号化されたテキストを読んで上の複合メソッドを呼び出します
with open("encrypt.txt", "r") as f: enctext = f.read() planetext = rsa_decrypt(enctext)
次に、、、
Pythonで暗号化
公開鍵で暗合化します。
def rsa_encrypt(s): with open("public_key.der", "rb") as f: from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_v1_5 from base64 import b64encode key = RSA.importKey(f.read()) cipher = PKCS1_v1_5.new(key) return b64encode(cipher.encrypt(bytes(s, 'utf-8'))).decode('utf-8')
Java で複合化
秘密鍵で複合します、秘密鍵でメソッド呼び出し前に抱えるように作って
以下のようなメソッドにすれば簡単になります
public String decrpt(String encstring) throws Exception{ Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); cipher.init(Cipher.DECRYPT_MODE, secret_key); return new String(cipher.doFinal(Base64.getDecoder().decode(encstring))); }