com.nimbusds.jose.jwk.PEMEncodedKeyParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nimbus-jose-jwt Show documentation
Show all versions of nimbus-jose-jwt Show documentation
Java library for Javascript Object Signing and Encryption (JOSE) and
JSON Web Tokens (JWT)
/*
* nimbus-jose-jwt
*
* Copyright 2012-2016, Connect2id Ltd and contributors.
*
* 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 com.nimbusds.jose.jwk;
import java.io.Reader;
import java.io.StringReader;
import java.security.*;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.util.ArrayList;
import java.util.List;
import com.nimbusds.jose.JOSEException;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.openssl.PEMException;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
/**
* PEM-encoded public / private key parser. Requires Bouncy Castle.
*
* @author Stefan Larsson
*/
class PEMEncodedKeyParser {
// JcaPEMKeyConverter looks threadsafe
private static final JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
private PEMEncodedKeyParser() {
// prevent construction of utility class
}
/**
* Parses one or more PEM-encoded certificates, public and / or private
* keys. The input is assumed to be not password-protected.
*
* @param pemEncodedKeys String of one or more PEM-encoded keys.
*
* @return The found keys.
*
* @throws JOSEException If parsing failed.
*/
static List parseKeys(final String pemEncodedKeys)
throws JOSEException {
// Strips the "---- {BEGIN,END} {CERTIFICATE,PUBLIC/PRIVATE KEY} -----"-like header and footer lines,
// base64-decodes the body,
// then uses the proper key specification format to turn it into a JCA Key instance
final Reader pemReader = new StringReader(pemEncodedKeys);
final PEMParser parser = new PEMParser(pemReader);
final List keys = new ArrayList<>();
try {
Object pemObj;
do {
pemObj = parser.readObject();
// if public key, use as-is
if (pemObj instanceof SubjectPublicKeyInfo) {
keys.add(toKeyPair((SubjectPublicKeyInfo) pemObj));
continue;
}
// if certificate, use the public key which is signed
if (pemObj instanceof X509CertificateHolder) {
keys.add(toKeyPair((X509CertificateHolder) pemObj));
continue;
}
// if EC private key given, it arrives here as a keypair
if (pemObj instanceof PEMKeyPair) {
keys.add(toKeyPair((PEMKeyPair) pemObj));
continue;
}
// if (RSA) private key given, return it
if (pemObj instanceof PrivateKeyInfo) {
keys.add(toKeyPair((PrivateKeyInfo) pemObj));
// continue implicitly
}
} while (pemObj != null);
return keys;
} catch (Exception e) {
throw new JOSEException(e.getMessage(), e);
}
}
private static KeyPair toKeyPair(final SubjectPublicKeyInfo spki)
throws PEMException {
return new KeyPair(pemConverter.getPublicKey(spki), null);
}
private static KeyPair toKeyPair(final X509CertificateHolder pemObj)
throws PEMException {
final SubjectPublicKeyInfo spki = pemObj.getSubjectPublicKeyInfo();
return new KeyPair(pemConverter.getPublicKey(spki), null);
}
private static KeyPair toKeyPair(final PEMKeyPair pair)
throws PEMException {
return pemConverter.getKeyPair(pair);
}
private static KeyPair toKeyPair(final PrivateKeyInfo pki)
throws PEMException, NoSuchAlgorithmException, InvalidKeySpecException {
final PrivateKey privateKey = pemConverter.getPrivateKey(pki);
// If it's RSA, we can use the modulus and public exponents as BigIntegers to create a public key
if (privateKey instanceof RSAPrivateCrtKey) {
final RSAPublicKeySpec publicKeySpec =
new RSAPublicKeySpec(((RSAPrivateCrtKey) privateKey).getModulus(),
((RSAPrivateCrtKey) privateKey).getPublicExponent());
final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
final PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
return new KeyPair(publicKey, privateKey);
}
// If was a private EC key, it would already have been received as a PEMKeyPair
return new KeyPair(null, privateKey);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy