In this tutorial, we will see how to load public and private RSA keys in java spring boot.
Encryption of data is one of the important steps in ensuring the security of data while transferring it over the network.
While doing Asymmetric encryption using RSA (public & private) keys or certificates. We need to load the keys or the certificate from the files or if stored in the application properties in java spring boot.
Load the .pem
file from file path
To read the file content we can use load the file from the path and then extract its content. The following method should help in reading the file from its path.
private static String getFileContent(String filePath) throws IOException { final StringBuilder sb = new StringBuilder(); File file = new File(filePath); if (file.exists()) { Scanner scanner = new Scanner(file); while (scanner.hasNextLine()) { sb.append(scanner.nextLine()).append(LINE_SEPARATOR); } scanner.close(); return sb.toString(); } else { throw new IllegalArgumentException("File does not exist"); } }
Extract the keys from the file
Once the file is read, we will get its content in the string format. The public and private keys or certificates are wrapped inside a special annotation.
For example, a public RSA key looks something like this,
-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCHJKZRIwlEU0Es5ywUWrOsjSyJ chneAVkWsgKZ/3pOR1QCmEl0AAg60B/X0hmxjQwR0YvQ/XSCfx7W2NTes4HV1rK0 TCtFaxLclmfOWJgofbcmL0OzYRGe/XSBO1hmtmPjIwDnVJnk7e/A/8COY9cigVFz pY+29jUTYSZL5/PIIQIDAQAB -----END PUBLIC KEY-----
and its corresponding private key would look like this,
-----BEGIN RSA PRIVATE KEY----- MIICXAIBAAKBgQCHJKZRIwlEU0Es5ywUWrOsjSyJchneAVkWsgKZ/3pOR1QCmEl0 AAg60B/X0hmxjQwR0YvQ/XSCfx7W2NTes4HV1rK0TCtFaxLclmfOWJgofbcmL0Oz YRGe/XSBO1hmtmPjIwDnVJnk7e/A/8COY9cigVFzpY+29jUTYSZL5/PIIQIDAQAB AoGAUH1SlXaRmWEgq1bQGRtgcf/vK7mKkIArCGpjREc2GBNBhP4gmXc/b4/vt0IK TYZdTuuII6QhVWvS+VFRj4ZIaChXZKEd0Yw10Z6qsjCw7m66lW2NpcOhZGo1cMnU taMYoxOcGQT31r/LHC7nQEbo8bRgv/vEFasgirXZym2lAHUCQQDwAQzJRNwKXmQ1 73gMPhQzz7FyqT85vQ8SSKQcTXLlMpSn9JkvvS1ImUoXm4idsPrqeVGp35iaav7y lt3MAVAjAkEAkCZ2XWApBmk0k/CEV+M3wMVvjfi2DwekpyCW8WYHKNvmY2PlrCBv sBTiurXuvvJAtoM10cPnJAVHQ7/S55to6wJAeqiutjaBFrODF6WZfvhDLu+YyvcA nyumhjul0+kpLUYaf3Qczi8q842UNliBC8alliwGtoDV5yWDwsuj811AbQJAdINi MN9EybXHlbxWfGNf8SSkonBhV4yp/ZxN5Ri+uLvlYHiib5pYLE71ZE0hiJ1uyRcN LVvXPDo3+/7UjfgDuQJBAKKZ6tes09DvRXLG8hoTInQr3JYoUY4yXCx3Q1bQQXOc A5z6sW2AouITTlr/pqZM6T5LTIinLGvBWTM91GKmGAg= -----END RSA PRIVATE KEY-----
Thus to read their content, we will have to get the substring inside these specific annotations.
public class LoadRSAKeys { private static final String LINE_SEPARATOR = "\r\n"; private static final String BEGIN_CERTIFICATE = "-----BEGIN CERTIFICATE-----"; private static final String END_CERTIFICATE = "-----END CERTIFICATE-----"; private static final String BEGIN_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----"; private static final String END_PUBLIC_KEY = "-----END PUBLIC KEY-----"; private static final String BEGIN_PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----"; private static final String END_PRIVATE_KEY = "-----END PRIVATE KEY-----"; public RSAPublicKey loadPublicKeyFromFile(String publicKeyFilePath) throws IOException, GeneralSecurityException { String publicKeyPem = getFileContent(publicKeyFilePath); return loadPublicKeyFromPem(publicKeyPem); } public static RSAPublicKey loadPublicKeyFromPem(String publicKeyPem) throws GeneralSecurityException { String publicKeyPEMStr = publicKeyPem; if (publicKeyPem.startsWith(BEGIN_CERTIFICATE)) { publicKeyPEMStr = publicKeyPEMStr.replace(BEGIN_CERTIFICATE, "") .replaceAll(LINE_SEPARATOR, "") .replace(END_CERTIFICATE, ""); return (RSAPublicKey) getX509Certificate(publicKeyPEMStr.trim()).getPublicKey(); } else if (publicKeyPEMStr.startsWith(BEGIN_PUBLIC_KEY)) { publicKeyPEMStr = publicKeyPEMStr.replace(BEGIN_PUBLIC_KEY, "") .replaceAll(LINE_SEPARATOR, "") .replace(END_PUBLIC_KEY, ""); byte[] encoded = DatatypeConverter.parseBase64Binary(publicKeyPEMStr.trim()); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encoded); return (RSAPublicKey) keyFactory.generatePublic(keySpec); } throw new IllegalArgumentException("Content is not a certificate or public key in PEM format"); } private static X509Certificate getX509Certificate(String certificateString) throws CertificateException { CertificateFactory cfb = CertificateFactory.getInstance("X509"); InputStream inputStream = new ByteArrayInputStream(DatatypeConverter.parseBase64Binary(certificateString)); return (X509Certificate) cfb.generateCertificate(inputStream); } public RSAPrivateKey loadPrivateKeyFromFile(String privateKeyPath) throws IOException, GeneralSecurityException { String privateKeyPem = getFileContent(privateKeyPath); return loadPrivateKeyFromPem(privateKeyPem); } public static RSAPrivateKey loadPrivateKeyFromPem(String privateKeyPem) throws GeneralSecurityException { String privateKey = privateKeyPem.replace(BEGIN_PRIVATE_KEY, "") .replaceAll(LINE_SEPARATOR, "") .replace(END_PRIVATE_KEY, ""); byte[] encodedPrivateKey = DatatypeConverter.parseBase64Binary(privateKey); return (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(encodedPrivateKey)); } private static String getFileContent(String filePath) throws IOException { final StringBuilder sb = new StringBuilder(); File file = new File(filePath); if (file.exists()) { Scanner scanner = new Scanner(file); while (scanner.hasNextLine()) { sb.append(scanner.nextLine()).append(LINE_SEPARATOR); } scanner.close(); return sb.toString(); } else { throw new IllegalArgumentException("File does not exist"); } } }
Using the methods in the above class you get the public and private keys from the given file path and load the keys and use them internally for encryption.