From e77a3fd498888272b6b93fe918197b18926ea330 Mon Sep 17 00:00:00 2001 From: Biju Kunjummen Date: Thu, 15 Feb 2018 10:50:03 -0800 Subject: [PATCH] Allows more standard rsa private key for config values encryption (#323) --- .../context/encrypt/EncryptorFactory.java | 37 +++++++++++++++++-- .../encrypt/EncryptorFactoryTests.java | 15 +++++--- .../resources/example-test-rsa-private-key | 20 +++++----- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/context/encrypt/EncryptorFactory.java b/spring-cloud-context/src/main/java/org/springframework/cloud/context/encrypt/EncryptorFactory.java index 948c749c..edb9cabd 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/context/encrypt/EncryptorFactory.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/context/encrypt/EncryptorFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2014 the original author or authors. + * Copyright 2013-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,13 +15,23 @@ */ package org.springframework.cloud.context.encrypt; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.openssl.MiscPEMGenerator; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.util.io.pem.PemObjectGenerator; +import org.bouncycastle.util.io.pem.PemWriter; import org.springframework.security.crypto.encrypt.Encryptors; import org.springframework.security.crypto.encrypt.TextEncryptor; import org.springframework.security.rsa.crypto.RsaSecretEncryptor; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + /** * @author Dave Syer - * + * @author Biju Kunjummen */ public class EncryptorFactory { @@ -34,7 +44,8 @@ public class EncryptorFactory { if (data.contains("RSA PRIVATE KEY")) { try { - encryptor = new RsaSecretEncryptor(data); + String normalizedPemData = normalizePem(data); + encryptor = new RsaSecretEncryptor(normalizedPemData.replaceAll("\\n", "").replaceAll("\\r", "")); } catch (IllegalArgumentException e) { throw new KeyFormatException(e); @@ -51,6 +62,26 @@ public class EncryptorFactory { return encryptor; } + private String normalizePem(String data) { + PEMParser pemParser = new PEMParser(new StringReader(data)); + PEMKeyPair pemKeyPair = null; + try { + pemKeyPair = (PEMKeyPair) pemParser.readObject(); + PrivateKeyInfo privateKeyInfo = pemKeyPair.getPrivateKeyInfo(); + + StringWriter textWriter = new StringWriter(); + PemWriter pemWriter = new PemWriter(textWriter); + PemObjectGenerator pemObjectGenerator = new MiscPEMGenerator(privateKeyInfo); + + pemWriter.writeObject(pemObjectGenerator); + pemWriter.flush(); + return textWriter.toString(); + } + catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } diff --git a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EncryptorFactoryTests.java b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EncryptorFactoryTests.java index 545e8d01..9376b9e0 100644 --- a/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EncryptorFactoryTests.java +++ b/spring-cloud-context/src/test/java/org/springframework/cloud/bootstrap/encrypt/EncryptorFactoryTests.java @@ -35,13 +35,18 @@ public class EncryptorFactoryTests { String key = StreamUtils.copyToString( new ClassPathResource("/example-test-rsa-private-key").getInputStream(), Charset.forName("ASCII")); - //RSA private key needs to be with no new lines - //-----BEGIN RSA PRIVATE KEY-----MIIEowI....iX8htsO-----END RSA PRIVATE KEY----- - String keyNoNewLines = key.replaceAll("\\n", ""); - TextEncryptor encryptor = new EncryptorFactory().create(keyNoNewLines); + + TextEncryptor encryptor = new EncryptorFactory().create(key); String toEncrypt = "sample text to encrypt"; String encrypted = encryptor.encrypt(toEncrypt); assertEquals(toEncrypt, encryptor.decrypt(encrypted)); } -} + + @Test(expected = RuntimeException.class) + public void testWithInvalidRsaPrivateKey() { + String key = "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEowIBAAKCAQEAwClFgrRa/PUHPIJr9gvIPL6g6Rjp/TVZmVNOf2fL96DYbkj5\n"; + new EncryptorFactory().create(key); + } +} \ No newline at end of file diff --git a/spring-cloud-context/src/test/resources/example-test-rsa-private-key b/spring-cloud-context/src/test/resources/example-test-rsa-private-key index 53ee7a10..1050b1dc 100644 --- a/spring-cloud-context/src/test/resources/example-test-rsa-private-key +++ b/spring-cloud-context/src/test/resources/example-test-rsa-private-key @@ -1,27 +1,25 @@ -----BEGIN RSA PRIVATE KEY----- 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 -----END RSA PRIVATE KEY-----