|
|
|
|
@ -24,9 +24,12 @@ import java.net.URL;
@@ -24,9 +24,12 @@ import java.net.URL;
|
|
|
|
|
import java.security.GeneralSecurityException; |
|
|
|
|
import java.security.KeyFactory; |
|
|
|
|
import java.security.PrivateKey; |
|
|
|
|
import java.security.spec.InvalidKeySpecException; |
|
|
|
|
import java.security.spec.PKCS8EncodedKeySpec; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.Base64; |
|
|
|
|
import java.util.Arrays; |
|
|
|
|
import java.util.Collection; |
|
|
|
|
import java.util.Collections; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.function.Function; |
|
|
|
|
@ -41,6 +44,7 @@ import org.springframework.util.ResourceUtils;
@@ -41,6 +44,7 @@ import org.springframework.util.ResourceUtils;
|
|
|
|
|
* |
|
|
|
|
* @author Scott Frederick |
|
|
|
|
* @author Phillip Webb |
|
|
|
|
* @author Moritz Halbritter |
|
|
|
|
*/ |
|
|
|
|
final class PrivateKeyParser { |
|
|
|
|
|
|
|
|
|
@ -59,11 +63,15 @@ final class PrivateKeyParser {
@@ -59,11 +63,15 @@ final class PrivateKeyParser {
|
|
|
|
|
private static final String BASE64_TEXT = "([a-z0-9+/=\\r\\n]+)"; |
|
|
|
|
|
|
|
|
|
private static final List<PemParser> PEM_PARSERS; |
|
|
|
|
|
|
|
|
|
static { |
|
|
|
|
List<PemParser> parsers = new ArrayList<>(); |
|
|
|
|
parsers.add(new PemParser(PKCS1_HEADER, PKCS1_FOOTER, "RSA", PrivateKeyParser::createKeySpecForPkcs1)); |
|
|
|
|
parsers.add(new PemParser(EC_HEADER, EC_FOOTER, "EC", PrivateKeyParser::createKeySpecForEc)); |
|
|
|
|
parsers.add(new PemParser(PKCS8_HEADER, PKCS8_FOOTER, "RSA", PKCS8EncodedKeySpec::new)); |
|
|
|
|
parsers.add(new PemParser(PKCS1_HEADER, PKCS1_FOOTER, Collections.singleton("RSA"), |
|
|
|
|
PrivateKeyParser::createKeySpecForPkcs1)); |
|
|
|
|
parsers.add( |
|
|
|
|
new PemParser(EC_HEADER, EC_FOOTER, Collections.singleton("EC"), PrivateKeyParser::createKeySpecForEc)); |
|
|
|
|
parsers.add( |
|
|
|
|
new PemParser(PKCS8_HEADER, PKCS8_FOOTER, Arrays.asList("RSA", "EC", "DSA"), PKCS8EncodedKeySpec::new)); |
|
|
|
|
PEM_PARSERS = Collections.unmodifiableList(parsers); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -145,14 +153,14 @@ final class PrivateKeyParser {
@@ -145,14 +153,14 @@ final class PrivateKeyParser {
|
|
|
|
|
|
|
|
|
|
private final Pattern pattern; |
|
|
|
|
|
|
|
|
|
private final String algorithm; |
|
|
|
|
private final Collection<String> algorithms; |
|
|
|
|
|
|
|
|
|
private final Function<byte[], PKCS8EncodedKeySpec> keySpecFactory; |
|
|
|
|
|
|
|
|
|
PemParser(String header, String footer, String algorithm, |
|
|
|
|
PemParser(String header, String footer, Collection<String> algorithms, |
|
|
|
|
Function<byte[], PKCS8EncodedKeySpec> keySpecFactory) { |
|
|
|
|
this.pattern = Pattern.compile(header + BASE64_TEXT + footer, Pattern.CASE_INSENSITIVE); |
|
|
|
|
this.algorithm = algorithm; |
|
|
|
|
this.algorithms = algorithms; |
|
|
|
|
this.keySpecFactory = keySpecFactory; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -169,8 +177,15 @@ final class PrivateKeyParser {
@@ -169,8 +177,15 @@ final class PrivateKeyParser {
|
|
|
|
|
private PrivateKey parse(byte[] bytes) { |
|
|
|
|
try { |
|
|
|
|
PKCS8EncodedKeySpec keySpec = this.keySpecFactory.apply(bytes); |
|
|
|
|
KeyFactory keyFactory = KeyFactory.getInstance(this.algorithm); |
|
|
|
|
return keyFactory.generatePrivate(keySpec); |
|
|
|
|
for (String algorithm : this.algorithms) { |
|
|
|
|
KeyFactory keyFactory = KeyFactory.getInstance(algorithm); |
|
|
|
|
try { |
|
|
|
|
return keyFactory.generatePrivate(keySpec); |
|
|
|
|
} |
|
|
|
|
catch (InvalidKeySpecException ignored) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
catch (GeneralSecurityException ex) { |
|
|
|
|
throw new IllegalArgumentException("Unexpected key format", ex); |
|
|
|
|
|