公開鍵暗号方式(RSA)による暗号化、復号化を試してみる

前回PEM形式のファイルをBouncy Castleを利用して読み込めることが確認できたので、公開鍵暗号方式で暗号化、復号化を試してみようと思います。
ichiwork.hatenablog.com

公開鍵暗号方式では暗号化には公開鍵を利用し、復号化には秘密鍵を利用します。

サンプルソース

メイン

プログラムの流れとしては以下の流れです。

  1. PEMファイルから公開鍵、秘密鍵を読み込む
  2. 公開鍵を利用して暗号化する
  3. 秘密鍵を利用して復号化する
public class CriptoSample {

	private static final String ALGORITHM = "RSA";

	public static void main(String[] args) {
		String org = "パパの頭にちょんまげがあったら、朝の挨拶おはようでござる";

		KeyPair keypair = PEMUtil.pemToKeyPair("rs256.key.pkcs8", "rs256.pub.key");

		try {
			System.out.println("元の文字列:" + org);
			String encrypted = CriptoUtil.cripto(org, keypair.getPublic(), ALGORITHM);
			System.out.println("暗号化後の文字列:" + encrypted);
			String decrypted = CriptoUtil.decrypt(encrypted, keypair.getPrivate(), ALGORITHM);
			System.out.println("複合化後の文字列:" + decrypted);
		} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException
				| BadPaddingException e) {
			e.printStackTrace();
		}
	}
}
PEMファイルから公開鍵、秘密鍵を生成するユーティリティークラス

Bouncy Castleを利用してPEMファイルから公開鍵と秘密鍵を生成しています。

public class PEMUtil {
	private PEMUtil() {
	};

	private static final JcaPEMKeyConverter conv = new JcaPEMKeyConverter().setProvider(new BouncyCastleProvider());

	public static PrivateKey pemToPrivateKey(String privateKeyFilePath) {
		PrivateKey privateKey = null;

		// PEM形式の秘密鍵ファイルからPrivateKeyを生成する
		try (PEMParser parser = new PEMParser(
				new InputStreamReader(ClassLoader.getSystemResourceAsStream(privateKeyFilePath)))) {
			Object obj = parser.readObject();
			if (obj instanceof PrivateKeyInfo) {
				PrivateKeyInfo keyInfo = (PrivateKeyInfo) obj;
				privateKey = conv.getPrivateKey(keyInfo);
			}
			if (obj instanceof PEMKeyPair) {
				PEMKeyPair keyInfo = (PEMKeyPair) obj;
				privateKey = conv.getKeyPair(keyInfo).getPrivate();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return privateKey;
	}

	public static PublicKey pemToPublicKey(String publicKeyFilePath) {
		PublicKey publicKey = null;

		// PEM形式の公開鍵ファイルからPublicKeyを生成する
		try (PEMParser parser = new PEMParser(
				new InputStreamReader(ClassLoader.getSystemResourceAsStream(publicKeyFilePath)))) {
			Object obj = parser.readObject();
			if (obj instanceof SubjectPublicKeyInfo) {
				SubjectPublicKeyInfo keyInfo = (SubjectPublicKeyInfo) obj;
				publicKey = conv.getPublicKey(keyInfo);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return publicKey;
	}

	public static KeyPair pemToKeyPair(String privateKeyFilePath, String publicKeyFilePath) {
		PrivateKey privateKey = pemToPrivateKey(privateKeyFilePath);
		PublicKey publicKey = pemToPublicKey(publicKeyFilePath);
		KeyPair keyPair = null;

		// PrivateKey、PublicKeyからKeyPairを生成する
		if (publicKey != null && privateKey != null) {
			keyPair = new KeyPair(publicKey, privateKey);
		}

		return keyPair;
	}
}
暗号化ユーティリティークラス
public class CriptoUtil {
	private CriptoUtil() {
	};

	public static String cripto(String org, Key key, String algorithm) throws NoSuchAlgorithmException,
			NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		Cipher cipher;
		String dest = null;

		cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.ENCRYPT_MODE, key);
		dest = new String(Base64.encode(cipher.doFinal(org.getBytes())));
		return dest;
	}

	public static String decrypt(String encrypted, Key key, String algorithm) throws NoSuchAlgorithmException,
			NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
		Cipher cipher;
		String org = null;

		cipher = Cipher.getInstance(algorithm);
		cipher.init(Cipher.DECRYPT_MODE, key);
		org = new String(cipher.doFinal(Base64.decode(encrypted.getBytes())));
		return org;
	}
}