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.PEMReader;
|
||||||
import net.oauth.signature.pem.PKCS1EncodedKeySpec;
|
import net.oauth.signature.pem.PKCS1EncodedKeySpec;
|
||||||
|
import net.oauth.signature.pem.PKCS1EncodedPublicKeySpec;
|
||||||
|
|
||||||
import org.jclouds.crypto.Pems.PemProcessor.ResultParser;
|
import org.jclouds.crypto.Pems.PemProcessor.ResultParser;
|
||||||
|
import org.jclouds.io.InputSuppliers;
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
import com.google.common.annotations.Beta;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
@ -55,6 +57,11 @@ import com.google.common.io.InputSupplier;
|
||||||
*/
|
*/
|
||||||
@Beta
|
@Beta
|
||||||
public class Pems {
|
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 static class PemProcessor<T> implements com.google.common.io.ByteProcessor<T> {
|
||||||
public interface ResultParser<T> {
|
public interface ResultParser<T> {
|
||||||
|
@ -81,7 +88,7 @@ public class Pems {
|
||||||
return parsers.get(reader.getBeginMarker()).parseResult(bytes);
|
return parsers.get(reader.getBeginMarker()).parseResult(bytes);
|
||||||
} else {
|
} else {
|
||||||
throw new IOException(String.format("Invalid PEM file: no parsers for marker %s in %s", reader
|
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) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(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
|
* @param supplier
|
||||||
* the input stream factory
|
* the input stream factory
|
||||||
|
@ -98,12 +106,13 @@ public class Pems {
|
||||||
* header that begins the PEM block
|
* header that begins the PEM block
|
||||||
* @param processor
|
* @param processor
|
||||||
* how to parser the object from a byte array
|
* 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
|
* @throws IOException
|
||||||
* if an I/O error occurs
|
* if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public static <T> T fromPem(InputSupplier<? extends InputStream> supplier, PemProcessor<T> processor)
|
public static <T> T fromPem(InputSupplier<? extends InputStream> supplier, PemProcessor<T> processor)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
return com.google.common.io.ByteStreams.readBytes(supplier, processor);
|
return com.google.common.io.ByteStreams.readBytes(supplier, processor);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
@ -126,45 +135,75 @@ public class Pems {
|
||||||
*/
|
*/
|
||||||
public static KeySpec privateKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
|
public static KeySpec privateKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||||
return fromPem(supplier, new PemProcessor<KeySpec>(ImmutableMap.<String, ResultParser<KeySpec>> of(
|
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 {
|
public KeySpec parseResult(byte[] bytes) throws IOException {
|
||||||
return (new PKCS1EncodedKeySpec(bytes)).getKeySpec();
|
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 {
|
public KeySpec parseResult(byte[] bytes) throws IOException {
|
||||||
return new PKCS8EncodedKeySpec(bytes);
|
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
|
* @param supplier
|
||||||
* the input stream factory
|
* 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
|
* @throws IOException
|
||||||
* if an I/O error occurs
|
* if an I/O error occurs
|
||||||
*/
|
*/
|
||||||
public static X509EncodedKeySpec publicKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
|
public static KeySpec publicKeySpec(InputSupplier<? extends InputStream> supplier) throws IOException {
|
||||||
return fromPem(supplier, new PemProcessor<X509EncodedKeySpec>(ImmutableMap
|
return fromPem(supplier, new PemProcessor<KeySpec>(ImmutableMap.<String, ResultParser<KeySpec>> of(
|
||||||
.<String, ResultParser<X509EncodedKeySpec>> of(PEMReader.PUBLIC_X509_MARKER,
|
PUBLIC_PKCS1_MARKER, new ResultParser<KeySpec>() {
|
||||||
new ResultParser<X509EncodedKeySpec>() {
|
|
||||||
|
|
||||||
public X509EncodedKeySpec parseResult(byte[] bytes) throws IOException {
|
public KeySpec parseResult(byte[] bytes) throws IOException {
|
||||||
return new X509EncodedKeySpec(bytes);
|
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
|
* @param supplier
|
||||||
* the input stream factory
|
* the input stream factory
|
||||||
|
@ -177,24 +216,24 @@ public class Pems {
|
||||||
* @throws CertificateException
|
* @throws CertificateException
|
||||||
*/
|
*/
|
||||||
public static X509Certificate x509Certificate(InputSupplier<? extends InputStream> supplier,
|
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
|
final CertificateFactory finalCertFactory = certFactory != null ? certFactory : CertificateFactory
|
||||||
.getInstance("X.509");
|
.getInstance("X.509");
|
||||||
try {
|
try {
|
||||||
return fromPem(supplier, new PemProcessor<X509Certificate>(ImmutableMap
|
return fromPem(supplier, new PemProcessor<X509Certificate>(ImmutableMap
|
||||||
.<String, ResultParser<X509Certificate>> of(PEMReader.CERTIFICATE_X509_MARKER,
|
.<String, ResultParser<X509Certificate>> of(CERTIFICATE_X509_MARKER,
|
||||||
new ResultParser<X509Certificate>() {
|
new ResultParser<X509Certificate>() {
|
||||||
|
|
||||||
public X509Certificate parseResult(byte[] bytes) throws IOException {
|
public X509Certificate parseResult(byte[] bytes) throws IOException {
|
||||||
try {
|
try {
|
||||||
return (X509Certificate) finalCertFactory
|
return (X509Certificate) finalCertFactory.generateCertificate(new ByteArrayInputStream(
|
||||||
.generateCertificate(new ByteArrayInputStream(bytes));
|
bytes));
|
||||||
} catch (CertificateException e) {
|
} catch (CertificateException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
})));
|
})));
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
if (e.getCause() != null && e.getCause() instanceof CertificateException) {
|
if (e.getCause() != null && e.getCause() instanceof CertificateException) {
|
||||||
throw (CertificateException) e.getCause();
|
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.
|
* encodes the {@link X509Certificate} to PEM format.
|
||||||
*
|
*
|
||||||
|
@ -214,8 +265,8 @@ public class Pems {
|
||||||
*/
|
*/
|
||||||
public static String pem(X509Certificate cert) throws IOException, CertificateEncodingException {
|
public static String pem(X509Certificate cert) throws IOException, CertificateEncodingException {
|
||||||
return new StringBuilder("-----BEGIN CERTIFICATE-----\n").append(
|
return new StringBuilder("-----BEGIN CERTIFICATE-----\n").append(
|
||||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(cert.getEncoded()))).append(
|
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(cert.getEncoded()))).append(
|
||||||
"\n-----END CERTIFICATE-----\n").toString();
|
"\n-----END CERTIFICATE-----\n").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -229,8 +280,8 @@ public class Pems {
|
||||||
*/
|
*/
|
||||||
public static String pem(PublicKey key) throws IOException {
|
public static String pem(PublicKey key) throws IOException {
|
||||||
return new StringBuilder("-----BEGIN PUBLIC KEY-----\n").append(
|
return new StringBuilder("-----BEGIN PUBLIC KEY-----\n").append(
|
||||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(key.getEncoded()))).append(
|
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(key.getEncoded()))).append(
|
||||||
"\n-----END PUBLIC KEY-----\n").toString();
|
"\n-----END PUBLIC KEY-----\n").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -244,8 +295,8 @@ public class Pems {
|
||||||
*/
|
*/
|
||||||
public static String pem(PrivateKey key) throws IOException {
|
public static String pem(PrivateKey key) throws IOException {
|
||||||
return new StringBuilder("-----BEGIN PRIVATE KEY-----\n").append(
|
return new StringBuilder("-----BEGIN PRIVATE KEY-----\n").append(
|
||||||
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(key.getEncoded()))).append(
|
CryptoStreams.base64Encode(ByteStreams.newInputStreamSupplier(key.getEncoded()))).append(
|
||||||
"\n-----END PRIVATE KEY-----\n").toString();
|
"\n-----END PRIVATE KEY-----\n").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue