mirror of https://github.com/apache/jclouds.git
addded shortcuts for Stringified certificates and keys
This commit is contained in:
parent
0f60364ba7
commit
c2c15ce633
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License 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 net.oauth.signature.pem;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
|
||||
/**
|
||||
* PKCS#1 encoded public key spec. In oauth package as they made all classes
|
||||
* package visible.
|
||||
*
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class PKCS1EncodedPublicKeySpec {
|
||||
|
||||
private RSAPublicKeySpec keySpec;
|
||||
|
||||
/**
|
||||
* Create a PKCS#1 keyspec from DER encoded buffer
|
||||
*
|
||||
* @param keyBytes
|
||||
* DER encoded octet stream
|
||||
* @throws IOException
|
||||
*/
|
||||
public PKCS1EncodedPublicKeySpec(byte[] keyBytes) throws IOException {
|
||||
decode(keyBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the key spec that JCE understands.
|
||||
*
|
||||
* @return CRT keyspec defined by JCE
|
||||
*/
|
||||
public RSAPublicKeySpec getKeySpec() {
|
||||
return keySpec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode PKCS#1 encoded private key into RSAPublicKeySpec.
|
||||
*
|
||||
* <p/>
|
||||
* The ASN.1 syntax for the private key with CRT is
|
||||
*
|
||||
* <pre>
|
||||
* --
|
||||
* -- Representation of RSA private key with information for the CRT algorithm.
|
||||
* --
|
||||
* RSAPrivateKey ::= SEQUENCE {
|
||||
* version Version,
|
||||
* modulus INTEGER, -- n
|
||||
* publicExponent INTEGER, -- e
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param keyBytes
|
||||
* PKCS#1 encoded key
|
||||
* @throws IOException
|
||||
*/
|
||||
|
||||
private void decode(byte[] keyBytes) throws IOException {
|
||||
|
||||
DerParser parser = new DerParser(keyBytes);
|
||||
|
||||
Asn1Object sequence = parser.read();
|
||||
if (sequence.getType() != DerParser.SEQUENCE)
|
||||
throw new IOException("Invalid DER: not a sequence"); //$NON-NLS-1$
|
||||
|
||||
// Parse inside the sequence
|
||||
parser = sequence.getParser();
|
||||
|
||||
BigInteger modulus = parser.read().getInteger();
|
||||
BigInteger publicExp = parser.read().getInteger();
|
||||
|
||||
keySpec = new RSAPublicKeySpec(modulus, publicExp);
|
||||
}
|
||||
}
|
|
@ -40,8 +40,10 @@ import javax.annotation.Nullable;
|
|||
|
||||
import net.oauth.signature.pem.PEMReader;
|
||||
import net.oauth.signature.pem.PKCS1EncodedKeySpec;
|
||||
import net.oauth.signature.pem.PKCS1EncodedPublicKeySpec;
|
||||
|
||||
import org.jclouds.crypto.Pems.PemProcessor.ResultParser;
|
||||
import org.jclouds.io.InputSuppliers;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
@ -55,6 +57,11 @@ import com.google.common.io.InputSupplier;
|
|||
*/
|
||||
@Beta
|
||||
public class Pems {
|
||||
public static final String PRIVATE_PKCS1_MARKER = "-----BEGIN RSA PRIVATE KEY-----";
|
||||
public static final String PRIVATE_PKCS8_MARKER = "-----BEGIN PRIVATE KEY-----";
|
||||
public static final String CERTIFICATE_X509_MARKER = "-----BEGIN CERTIFICATE-----";
|
||||
public static final String PUBLIC_X509_MARKER = "-----BEGIN PUBLIC KEY-----";
|
||||
public static final String PUBLIC_PKCS1_MARKER = "-----BEGIN RSA PUBLIC KEY-----";
|
||||
|
||||
public static class PemProcessor<T> implements com.google.common.io.ByteProcessor<T> {
|
||||
public interface ResultParser<T> {
|
||||
|
@ -81,7 +88,7 @@ public class Pems {
|
|||
return parsers.get(reader.getBeginMarker()).parseResult(bytes);
|
||||
} else {
|
||||
throw new IOException(String.format("Invalid PEM file: no parsers for marker %s in %s", reader
|
||||
.getBeginMarker(), parsers.keySet()));
|
||||
.getBeginMarker(), parsers.keySet()));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -90,7 +97,8 @@ public class Pems {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the object of generic type {@code T} that is pem encoded in the supplier.
|
||||
* Returns the object of generic type {@code T} that is pem encoded in the
|
||||
* supplier.
|
||||
*
|
||||
* @param supplier
|
||||
* the input stream factory
|
||||
|
@ -98,12 +106,13 @@ public class Pems {
|
|||
* header that begins the PEM block
|
||||
* @param processor
|
||||
* how to parser the object from a byte array
|
||||
* @return the object of generic type {@code T} which was PEM encoded in the stream
|
||||
* @return the object of generic type {@code T} which was PEM encoded in the
|
||||
* stream
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
public static <T> T fromPem(InputSupplier<? extends InputStream> supplier, PemProcessor<T> processor)
|
||||
throws IOException {
|
||||
throws IOException {
|
||||
try {
|
||||
return com.google.common.io.ByteStreams.readBytes(supplier, processor);
|
||||
} catch (RuntimeException e) {
|
||||
|
@ -126,45 +135,75 @@ public class Pems {
|
|||
*/
|
||||
public static KeySpec privateKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||
return fromPem(supplier, new PemProcessor<KeySpec>(ImmutableMap.<String, ResultParser<KeySpec>> of(
|
||||
PEMReader.PRIVATE_PKCS1_MARKER, new ResultParser<KeySpec>() {
|
||||
PRIVATE_PKCS1_MARKER, new ResultParser<KeySpec>() {
|
||||
|
||||
public KeySpec parseResult(byte[] bytes) throws IOException {
|
||||
return (new PKCS1EncodedKeySpec(bytes)).getKeySpec();
|
||||
}
|
||||
public KeySpec parseResult(byte[] bytes) throws IOException {
|
||||
return (new PKCS1EncodedKeySpec(bytes)).getKeySpec();
|
||||
}
|
||||
|
||||
}, PEMReader.PRIVATE_PKCS8_MARKER, new ResultParser<KeySpec>() {
|
||||
}, PRIVATE_PKCS8_MARKER, new ResultParser<KeySpec>() {
|
||||
|
||||
public KeySpec parseResult(byte[] bytes) throws IOException {
|
||||
return new PKCS8EncodedKeySpec(bytes);
|
||||
}
|
||||
public KeySpec parseResult(byte[] bytes) throws IOException {
|
||||
return new PKCS8EncodedKeySpec(bytes);
|
||||
}
|
||||
|
||||
})));
|
||||
})));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link X509EncodedKeySpec} that is pem encoded in the supplier.
|
||||
* Executes {@link Pems#privateKeySpec(InputSupplier)} on the string which
|
||||
* contains an encoded private key in PEM format.
|
||||
*
|
||||
* @param pem
|
||||
* private key in pem encoded format.
|
||||
* @see Pems#privateKeySpec(InputSupplier)
|
||||
*/
|
||||
public static KeySpec privateKeySpec(String pem) throws IOException {
|
||||
return privateKeySpec(InputSuppliers.of(pem));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link KeySpec} that is pem encoded in the supplier.
|
||||
*
|
||||
* @param supplier
|
||||
* the input stream factory
|
||||
*
|
||||
* @return the {@link X509EncodedKeySpec} which was PEM encoded in the stream
|
||||
* @return the {@link KeySpec} which was PEM encoded in the stream
|
||||
* @throws IOException
|
||||
* if an I/O error occurs
|
||||
*/
|
||||
public static X509EncodedKeySpec publicKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||
return fromPem(supplier, new PemProcessor<X509EncodedKeySpec>(ImmutableMap
|
||||
.<String, ResultParser<X509EncodedKeySpec>> of(PEMReader.PUBLIC_X509_MARKER,
|
||||
new ResultParser<X509EncodedKeySpec>() {
|
||||
public static KeySpec publicKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||
return fromPem(supplier, new PemProcessor<KeySpec>(ImmutableMap.<String, ResultParser<KeySpec>> of(
|
||||
PUBLIC_PKCS1_MARKER, new ResultParser<KeySpec>() {
|
||||
|
||||
public X509EncodedKeySpec parseResult(byte[] bytes) throws IOException {
|
||||
return new X509EncodedKeySpec(bytes);
|
||||
}
|
||||
public KeySpec parseResult(byte[] bytes) throws IOException {
|
||||
return (new PKCS1EncodedPublicKeySpec(bytes)).getKeySpec();
|
||||
}
|
||||
|
||||
})));
|
||||
}, PUBLIC_X509_MARKER, new ResultParser<KeySpec>() {
|
||||
|
||||
public X509EncodedKeySpec parseResult(byte[] bytes) throws IOException {
|
||||
return new X509EncodedKeySpec(bytes);
|
||||
}
|
||||
|
||||
})));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link X509EncodedKeySpec} that is pem encoded in the supplier.
|
||||
* Executes {@link Pems#publicKeySpec(InputSupplier)} on the string which
|
||||
* contains an encoded public key in PEM format.
|
||||
*
|
||||
* @param pem
|
||||
* public key in pem encoded format.
|
||||
* @see Pems#publicKeySpec(InputSupplier)
|
||||
*/
|
||||
public static KeySpec publicKeySpec(String pem) throws IOException {
|
||||
return publicKeySpec(InputSuppliers.of(pem));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link X509EncodedKeySpec} that is pem encoded in the
|
||||
* supplier.
|
||||
*
|
||||
* @param supplier
|
||||
* the input stream factory
|
||||
|
@ -177,24 +216,24 @@ public class Pems {
|
|||
* @throws CertificateException
|
||||
*/
|
||||
public static X509Certificate x509Certificate(InputSupplier<? extends InputStream> supplier,
|
||||
@Nullable CertificateFactory certFactory) throws IOException, CertificateException {
|
||||
@Nullable CertificateFactory certFactory) throws IOException, CertificateException {
|
||||
final CertificateFactory finalCertFactory = certFactory != null ? certFactory : CertificateFactory
|
||||
.getInstance("X.509");
|
||||
.getInstance("X.509");
|
||||
try {
|
||||
return fromPem(supplier, new PemProcessor<X509Certificate>(ImmutableMap
|
||||
.<String, ResultParser<X509Certificate>> of(PEMReader.CERTIFICATE_X509_MARKER,
|
||||
new ResultParser<X509Certificate>() {
|
||||
.<String, ResultParser<X509Certificate>> of(CERTIFICATE_X509_MARKER,
|
||||
new ResultParser<X509Certificate>() {
|
||||
|
||||
public X509Certificate parseResult(byte[] bytes) throws IOException {
|
||||
try {
|
||||
return (X509Certificate) finalCertFactory
|
||||
.generateCertificate(new ByteArrayInputStream(bytes));
|
||||
} catch (CertificateException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public X509Certificate parseResult(byte[] bytes) throws IOException {
|
||||
try {
|
||||
return (X509Certificate) finalCertFactory.generateCertificate(new ByteArrayInputStream(
|
||||
bytes));
|
||||
} catch (CertificateException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
})));
|
||||
})));
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getCause() != null && e.getCause() instanceof CertificateException) {
|
||||
throw (CertificateException) e.getCause();
|
||||
|
@ -203,6 +242,18 @@ public class Pems {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes {@link Pems#x509Certificate(InputSupplier, CertificateFactory)}
|
||||
* on the string which contains an X.509 certificate in PEM format.
|
||||
*
|
||||
* @param pem
|
||||
* certificate in pem encoded format.
|
||||
* @see Pems#x509Certificate(InputSupplier, CertificateFactory)
|
||||
*/
|
||||
public static X509Certificate x509Certificate(String pem) throws IOException, CertificateException {
|
||||
return x509Certificate(InputSuppliers.of(pem), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* encodes the {@link X509Certificate} to PEM format.
|
||||
*
|
||||
|
@ -214,8 +265,8 @@ public class Pems {
|
|||
*/
|
||||
public static String pem(X509Certificate cert) throws IOException, CertificateEncodingException {
|
||||
return new StringBuilder("-----BEGIN CERTIFICATE-----\n").append(
|
||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(cert.getEncoded()))).append(
|
||||
"\n-----END CERTIFICATE-----\n").toString();
|
||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(cert.getEncoded()))).append(
|
||||
"\n-----END CERTIFICATE-----\n").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,8 +280,8 @@ public class Pems {
|
|||
*/
|
||||
public static String pem(PublicKey key) throws IOException {
|
||||
return new StringBuilder("-----BEGIN PUBLIC KEY-----\n").append(
|
||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(key.getEncoded()))).append(
|
||||
"\n-----END PUBLIC KEY-----\n").toString();
|
||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(key.getEncoded()))).append(
|
||||
"\n-----END PUBLIC KEY-----\n").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,8 +295,8 @@ public class Pems {
|
|||
*/
|
||||
public static String pem(PrivateKey key) throws IOException {
|
||||
return new StringBuilder("-----BEGIN PRIVATE KEY-----\n").append(
|
||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(key.getEncoded()))).append(
|
||||
"\n-----END PRIVATE KEY-----\n").toString();
|
||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(key.getEncoded()))).append(
|
||||
"\n-----END PRIVATE KEY-----\n").toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue