com.amazonaws.auth.PEM Maven / Gradle / Ivy
Show all versions of aws-java-sdk-cloudfront Show documentation
/*
* Copyright 2013-2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.auth;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.List;
import com.amazonaws.util.Base64;
/**
* A PEM utility that can be used to read keys from PEM. With this PEM utility,
* private keys in either PKCS#1 or PKCS#8 PEM encoded format can be read
* without the need to depend on the Bouncy Castle library.
*
* Some background information:
*
* - Interestingly, the creation of a CloudFront Key Pair via the AWS console
* would result in a private key in PKCS#1 PEM format.
* - Unfortunately, the JDK doesn't provide a means to load PEM key encoded in
* PKCS#1 without adding the Bouncy Castle to the classpath. The JDK can only
* load PEM key encoded in PKCS#8 encoding.
* - One the other hand, one can use openssl to convert a PEM file from PKCS#1
* to PKCS#8. Example:
*
*
* openssl pkcs8 -topk8 -in pk-APKAJM22QV32R3I2XVIQ.pem -inform pem -out pk-APKAJM22QV32R3I2XVIQ_pk8.pem -outform pem -nocrypt
*
*
*
*
*/
public enum PEM {
;
private static final String BEGIN_MARKER = "-----BEGIN ";
/**
* Returns the first private key that is found from the input stream of a
* PEM file.
*
* @throws InvalidKeySpecException
* if failed to convert the DER bytes into a private key.
* @throws IllegalArgumentException
* if no private key is found.
*/
public static PrivateKey readPrivateKey(InputStream is)
throws InvalidKeySpecException, IOException {
List objects = readPEMObjects(is);
for (PEMObject object : objects) {
switch (object.getPEMObjectType()) {
case PRIVATE_KEY_PKCS1:
return RSA.privateKeyFromPKCS1(object.getDerBytes());
case PRIVATE_KEY_PKCS8:
return RSA.privateKeyFromPKCS8(object.getDerBytes());
default:
break;
}
}
throw new IllegalArgumentException("Found no private key");
}
/**
* Returns the first public key that is found from the input stream of a PEM
* file.
*
* @throws InvalidKeySpecException
* if failed to convert the DER bytes into a public key.
* @throws IllegalArgumentException
* if no public key is found.
*/
public static PublicKey readPublicKey(InputStream is)
throws InvalidKeySpecException, IOException {
List objects = readPEMObjects(is);
for (PEMObject object : objects) {
switch (object.getPEMObjectType()) {
case PUBLIC_KEY_X509:
return RSA.publicKeyFrom(object.getDerBytes());
default:
break;
}
}
throw new IllegalArgumentException("Found no public key");
}
/**
* A lower level API used to returns all PEM objects that can be read off
* from the input stream of a PEM file.
*
* This method can be useful if more than one PEM object of different types
* are embedded in the same PEM file.
*/
public static List readPEMObjects(InputStream is)
throws IOException {
List pemContents = new ArrayList();
/*
* State of reading: set to true if reading content between a
* begin-marker and end-marker; false otherwise.
*/
boolean readingContent = false;
String beginMarker = null;
String endMarker = null;
StringBuffer sb = null;
String line;
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
try {
while ((line = reader.readLine()) != null) {
if (readingContent) {
if (line.indexOf(endMarker) != -1) {
pemContents.add( // completed reading one PEM object
new PEMObject(beginMarker, Base64.decode(sb
.toString())));
readingContent = false;
} else {
sb.append(line.trim());
}
} else {
if (line.indexOf(BEGIN_MARKER) != -1) {
readingContent = true;
beginMarker = line.trim();
endMarker = beginMarker.replace("BEGIN", "END");
sb = new StringBuffer();
}
}
}
return pemContents;
} finally {
try {
reader.close();
} catch (IOException ignore) {
}
}
}
}