LoginSignup
2
3

More than 3 years have passed since last update.

JavaでRSA公開鍵による暗号化と復号化の方法

Posted at

RSAを使った暗号化と復号化のやり方を今日も忘れたので備忘録として残しておく。

マイクロサービスアーキテクチャにおいて、ユーザーの認証情報を引き渡していくための方法として、いろいろなやり方があるが、オーバーヘッドが小さく確実にサービス側、呼び出し元の相互に認証と認可が可能なので公開鍵を使った認証済みのユーザー情報の暗号化がいいと思う。

なお、RSAの場合、鍵長に1024ビットを指定すると128バイトとなり、パディングが11バイトなので暗号化可能な文字列の長さは117バイトまでとなる。

認証済みのユーザーのIDなどを送信するには十分であるが、このあたりは注意が必要だ。

RSA鍵ペアの作成

KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024); // RSA鍵の長さを指定する
KeyPair keyPair = keyGen.generateKeyPair();

KeyPair には、秘密鍵と公開鍵の両方が含まれている。

秘密鍵のPEM形式での書き出し

"-----BEGIN RSA PRIVATE KEY-----\r\n" + 
encodeBase64(keyPair.getPrivate().getEncoded()) + "\r\n" +
"-----END RSA PRIVATE KEY-----\r\n";

encodeBase64(byte[]) は64文字ずつ改行を入れたBase64エンコードを行う関数。

公開鍵のPEM形式での書き出し

"-----BEGIN PUBLIC KEY-----\r\n" +
encodeBase64(keyPair.getPublic().getEncoded()) + "\r\n" +
"-----END PUBLIC KEY-----\r\n";

公開鍵での暗号化

RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);

String encrypted = Base64.getEncoder()
    .encodeToString(cipher.doFinal(plainText.getBytes("ISO-8859-1")));

暗号化モードとして ECB を利用しているので、平文が同じ場合は常に同じ暗号文になる。これが許容できない場合はデータの頭にでも乱数でIVの代わりとなるダミーデータを入れておくとよいだろう。

秘密鍵での複合化

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPublic());

String plainText = new String(
    cipher.doFinal(Base64.getDecoder().decode(encrypted)), "ISO-8859-1");

まとめ

JWTほど面倒ではなく、あらゆる言語環境で共通して利用可能なRSAによる暗号化はマイクロサービス間の認証と認可の現実解だ。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3