CLOUDSTACK-5296: Add certificate chain support for netscaler.

adds support for trust chains in the netscaler
This commit is contained in:
Syed Ahmed 2013-12-12 12:11:20 +05:30 committed by Murali Reddy
parent 326a46d0ac
commit fb89a2d8f6
7 changed files with 326 additions and 84 deletions

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
G# Licensed to the Apache Software Foundation (ASF) under one
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file

View File

@ -439,16 +439,17 @@ public class LoadBalancingRule {
public static class LbSslCert {
private String cert;
private String key;
private String password=null;
private String chain=null;
private String password = null;
private String chain = null;
private String fingerprint = null;
private boolean revoked;
public LbSslCert(String cert, String key, String password, String chain, boolean revoked) {
public LbSslCert(String cert, String key, String password, String chain, String fingerprint, boolean revoked) {
this.cert = cert;
this.key = key;
this.password = password;
this.chain = chain;
this.fingerprint = fingerprint;
this.revoked = revoked;
}
@ -469,7 +470,11 @@ public class LoadBalancingRule {
return chain;
}
public boolean isRevoked(){
public String getFingerprint() {
return fingerprint;
}
public boolean isRevoked() {
return revoked;
}
}

View File

@ -34,7 +34,7 @@ public class SslCertDaoImpl extends GenericDaoBase<SslCertVO, Long> implements S
listByAccountId = createSearchBuilder();
listByAccountId.and("accountId", listByAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
listByAccountId.done();
}
}
@Override
public List<SslCertVO> listByAccountId(Long accountId) {

View File

@ -16,6 +16,9 @@
// under the License.
package com.cloud.network.resource;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.HashMap;
@ -26,9 +29,14 @@ import java.util.Map;
import javax.naming.ConfigurationException;
import com.citrix.netscaler.nitro.resource.config.ssl.sslcertkey;
import com.citrix.netscaler.nitro.resource.config.ssl.sslcertkey_sslvserver_binding;
import com.citrix.netscaler.nitro.resource.config.ssl.sslcertlink;
import com.citrix.netscaler.nitro.resource.config.ssl.sslvserver_sslcertkey_binding;
import com.cloud.network.lb.LoadBalancingRule.LbSslCert;
import com.cloud.utils.security.CertificateHelper;
import com.cloud.utils.ssh.SshHelper;
import com.google.common.collect.Lists;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.log4j.Logger;
import com.citrix.netscaler.nitro.exception.nitro_exception;
@ -119,6 +127,7 @@ import com.cloud.utils.NumbersUtil;
import com.cloud.utils.Pair;
import com.cloud.utils.exception.ExecutionException;
import com.cloud.utils.net.NetUtils;
import org.bouncycastle.openssl.PEMWriter;
class NitroError {
static final int NS_RESOURCE_EXISTS = 273;
@ -664,25 +673,61 @@ public class NetscalerResource implements ServerResource {
}
if(sslCert != null && lbProtocol.equals(NetUtils.SSL_PROTO)) {
if ( sslCert.isRevoked() ){
if (sslCert != null && lbProtocol.equalsIgnoreCase(NetUtils.SSL_PROTO)) {
if (sslCert.isRevoked()) {
deleteCert = true;
} else{
String certName = generateSslCertName(srcIp, srcPort);
String keyName = generateSslKeyName(srcIp, srcPort);
String certKeyName = generateSslCertKeyName(srcIp, srcPort);
// If there is a chain, that should go first to the NS
if ( SSL.isSslCertKeyPresent(_netscalerService, certKeyName)){
SSL.deleteSslCertKey(_netscalerService, certKeyName);
String previousCertKeyName = null;
if ( sslCert.getChain() != null ) {
List<Certificate> chainList = CertificateHelper.parseChain(sslCert.getChain());
// go from ROOT to intermediate CAs
for ( Certificate intermediateCert : Lists.reverse(chainList)){
String fingerPrint=CertificateHelper.generateFingerPrint(intermediateCert);
String intermediateCertKeyName = generateSslCertKeyName(fingerPrint);
String intermediateCertFileName = intermediateCertKeyName + ".pem";
if (! SSL.isSslCertKeyPresent(_netscalerService, intermediateCertKeyName)) {
byte[] certData= intermediateCert.getEncoded();
StringWriter textWriter = new StringWriter();
PEMWriter pemWriter = new PEMWriter(textWriter);
pemWriter.writeObject(intermediateCert);
pemWriter.flush();
SSL.uploadCert(_ip, _username, _password, intermediateCertFileName, textWriter.toString().getBytes());
SSL.createSslCertKey(_netscalerService, intermediateCertFileName, null, intermediateCertKeyName, null);
}
if ( previousCertKeyName != null && ! SSL.certLinkExists(_netscalerService, intermediateCertKeyName, previousCertKeyName)){
SSL.linkCerts(_netscalerService, intermediateCertKeyName, previousCertKeyName);
}
previousCertKeyName = intermediateCertKeyName;
}
}
String certFilename = generateSslCertName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
String keyFilename = generateSslKeyName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
String certKeyName = generateSslCertKeyName(sslCert.getFingerprint());
SSL.uploadCert(_ip, _username, _password, certName, sslCert.getCert().getBytes());
SSL.uploadKey(_ip, _username, _password, keyName, sslCert.getKey().getBytes());
ByteArrayOutputStream certDataStream = new ByteArrayOutputStream( );
certDataStream.write(sslCert.getCert().getBytes());
if (! SSL.isSslCertKeyPresent(_netscalerService, certKeyName)) {
SSL.uploadCert(_ip, _username, _password, certFilename, certDataStream.toByteArray());
SSL.uploadKey(_ip, _username, _password, keyFilename, sslCert.getKey().getBytes());
SSL.createSslCertKey(_netscalerService, certFilename, keyFilename, certKeyName, sslCert.getPassword());
}
if (previousCertKeyName != null && ! SSL.certLinkExists(_netscalerService, certKeyName, previousCertKeyName)){
SSL.linkCerts(_netscalerService, certKeyName, previousCertKeyName);
}
SSL.createSslCertKey(_netscalerService, certName, keyName, certKeyName, sslCert.getPassword());
SSL.bindCertKeyToVserver(_netscalerService, certKeyName, nsVirtualServerName);
}
@ -773,18 +818,50 @@ public class NetscalerResource implements ServerResource {
}
if ( sslCert != null && deleteCert){
String certName = generateSslCertName(srcIp, srcPort);
String keyName = generateSslKeyName(srcIp, srcPort);
String certKeyName = generateSslCertKeyName(srcIp, srcPort);
String certFilename = generateSslCertName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
String keyFilename = generateSslKeyName(sslCert.getFingerprint()) + ".pem"; //netscaler uses ".pem" format for "bundle" files
String certKeyName = generateSslCertKeyName(sslCert.getFingerprint());
// unbind before deleting
if ( nsVirtualServerExists(nsVirtualServerName) ){
if (nsVirtualServerExists(nsVirtualServerName) &&
SSL.isSslCertKeyPresent(_netscalerService, certKeyName) &&
SSL.isBoundToVserver(_netscalerService, certKeyName, nsVirtualServerName)) {
SSL.unbindCertKeyFromVserver(_netscalerService, certKeyName, nsVirtualServerName);
}
SSL.deleteSslCertKey(_netscalerService, certKeyName);
SSL.deleteCertFile(_ip, _username, _password, certName);
SSL.deleteKeyFile(_ip, _username, _password, keyName);
if (SSL.isSslCertKeyPresent(_netscalerService, certKeyName)) {
SSL.deleteSslCertKey(_netscalerService, certKeyName);
SSL.deleteCertFile(_ip, _username, _password, certFilename);
SSL.deleteKeyFile(_ip, _username, _password, keyFilename);
}
/*
* Check and delete intermediate certs:
* we can delete an intermediate cert if no other
* cert references it as the athority
*/
if ( sslCert.getChain() != null ) {
List<Certificate> chainList = CertificateHelper.parseChain(sslCert.getChain());
//go from intermediate CAs to ROOT
for ( Certificate intermediateCert : chainList){
String fingerPrint=CertificateHelper.generateFingerPrint(intermediateCert);
String intermediateCertKeyName = generateSslCertKeyName(fingerPrint);
String intermediateCertFileName = intermediateCertKeyName + ".pem";
if (SSL.isSslCertKeyPresent(_netscalerService, intermediateCertKeyName) &&
! SSL.isCaforCerts(_netscalerService, intermediateCertKeyName)) {
SSL.deleteSslCertKey(_netscalerService, intermediateCertKeyName);
SSL.deleteCertFile(_ip, _username, _password, intermediateCertFileName);
}else {
break;// if this cert has another certificate as a child then stop at this point because we need the whole chain
}
}
}
}
}
@ -1737,7 +1814,7 @@ public class NetscalerResource implements ServerResource {
return false;
}
private static void deleteSslCertKey(nitro_service ns, String certKeyName) throws ExecutionException {
private static void deleteSslCertKey(nitro_service ns, String certKeyName) throws ExecutionException {
try {
sslcertkey certkey = new sslcertkey();
@ -1752,21 +1829,23 @@ public class NetscalerResource implements ServerResource {
}
private static void deleteCertFile(String nsIp, String username, String password, String certName) throws Exception {
SshHelper.sshExecute(nsIp,SSH_PORT,username,null,password,"shell rm " + SSL_CERT_PATH + certName);
private static void deleteCertFile(String nsIp, String username, String password, String certFilename) throws Exception {
SshHelper.sshExecute(nsIp,SSH_PORT,username,null,password,"shell rm " + SSL_CERT_PATH + certFilename);
}
private static void deleteKeyFile(String nsIp, String username, String password, String keyName) throws Exception {
SshHelper.sshExecute(nsIp,SSH_PORT,username,null,password,"shell rm " + SSL_CERT_PATH + keyName);
private static void deleteKeyFile(String nsIp, String username, String password, String keyFilename) throws Exception {
SshHelper.sshExecute(nsIp, SSH_PORT, username, null, password, "shell rm " + SSL_CERT_PATH + keyFilename);
}
private static void createSslCertKey(nitro_service ns, String certName, String keyName, String certKeyName, String password) throws ExecutionException {
private static void createSslCertKey(nitro_service ns, String certFilename, String keyFilename, String certKeyName, String password) throws ExecutionException {
s_logger.debug("Adding cert to netscaler");
try {
sslcertkey certkey = new sslcertkey();
certkey.set_certkey(certKeyName);
certkey.set_cert(SSL_CERT_PATH + certName);
certkey.set_key(SSL_CERT_PATH + keyName);
certkey.set_cert(SSL_CERT_PATH + certFilename);
if ( keyFilename != null )
certkey.set_key(SSL_CERT_PATH + keyFilename);
if( password != null ) {
certkey.set_passplain(password);
@ -1832,19 +1911,18 @@ public class NetscalerResource implements ServerResource {
}
private static void uploadCert(String nsIp, String user, String password, String certName, byte[] certData) throws ExecutionException {
private static void uploadCert(String nsIp, String user, String password, String certFilename, byte[] certData) throws ExecutionException {
try {
SshHelper.scpTo(nsIp,SSH_PORT,user,null,password, SSL_CERT_PATH, certData, certName, null);
SshHelper.scpTo(nsIp,SSH_PORT,user,null,password, SSL_CERT_PATH, certData, certFilename, null);
} catch (Exception e){
throw new ExecutionException("Failed to copy private key to device " + e.getMessage());
}
}
private static void uploadKey(String nsIp, String user, String password, String keyName, byte[] keyData) throws ExecutionException {
private static void uploadKey(String nsIp, String user, String password, String keyFilename, byte[] keyData) throws ExecutionException {
try {
SshHelper.scpTo(nsIp, SSH_PORT, user, null, password, SSL_CERT_PATH, keyData, keyName, null);
} catch (Exception e){
SshHelper.scpTo(nsIp, SSH_PORT, user, null, password, SSL_CERT_PATH, keyData, keyFilename, null);
} catch (Exception e) {
throw new ExecutionException("Failed to copy private key to device " + e.getMessage());
}
}
@ -1853,7 +1931,7 @@ public class NetscalerResource implements ServerResource {
private static void enableSslFeature(nitro_service ns) throws ExecutionException {
try {
base_response result = ns.enable_features(new String[]{"SSL"});
if( result.errorcode != 0 )
if (result.errorcode != 0)
throw new ExecutionException("Unable to enable SSL on LB");
} catch (nitro_exception e){
throw new ExecutionException("Failed to enable ssl feature on load balancer due to " + e.getMessage());
@ -1880,7 +1958,80 @@ public class NetscalerResource implements ServerResource {
}
}
public static boolean certLinkExists(nitro_service ns, String userCertName, String caCertName) throws ExecutionException {
try {
// check if there is a link from userCertName to caCertName
sslcertkey userCert = sslcertkey.get(ns,userCertName);
String nsCaCert = userCert.get_linkcertkeyname();
if (nsCaCert != null && nsCaCert.equals(caCertName))
return true;
} catch (nitro_exception e) {
throw new ExecutionException("Failed to check cert link on load balancer to " + e.getMessage());
} catch (Exception e) {
throw new ExecutionException("Failed to check cert link on load balancer due to " + e.getMessage());
}
return false;
}
public static void linkCerts(nitro_service ns, String userCertName, String caCertName) throws ExecutionException {
try {
// the assumption is that that both userCertName and caCertName are present on NS
sslcertkey caCert = sslcertkey.get(ns, caCertName);
sslcertkey userCert = sslcertkey.get(ns, userCertName);
sslcertkey linkResource = new sslcertkey();
// link user cert to CA cert
linkResource.set_certkey(userCert.get_certkey());
linkResource.set_linkcertkeyname(caCert.get_certkey());
sslcertkey.link(ns, linkResource);
} catch (nitro_exception e) {
throw new ExecutionException("Failed to check cert link on load balancer to " + e.getMessage());
} catch (Exception e) {
throw new ExecutionException("Failed to check cert link on load balancer due to " + e.getMessage());
}
}
public static boolean isCaforCerts(nitro_service ns, String caCertName) throws ExecutionException {
// check if this certificate serves as a CA for other certificates
try {
sslcertlink[] childLinks = sslcertlink.get_filtered(ns,"linkcertkeyname:" + caCertName);
if(childLinks != null && childLinks.length > 0){
return true;
}
} catch (nitro_exception e) {
throw new ExecutionException("Failed to check cert link on load balancer to " + e.getMessage());
} catch (Exception e) {
throw new ExecutionException("Failed to check cert link on load balancer due to " + e.getMessage());
}
return false;
}
public static boolean isBoundToVserver(nitro_service ns, String certKeyName, String nsVirtualServerName) throws ExecutionException {
try {
sslcertkey_sslvserver_binding[] cert_vs_binding = sslcertkey_sslvserver_binding.get_filtered(ns, certKeyName, "vservername:" + nsVirtualServerName);
if(cert_vs_binding != null && cert_vs_binding.length > 0){
return true;
}
} catch (nitro_exception e) {
throw new ExecutionException("Failed to check cert link on load balancer to " + e.getMessage());
} catch (Exception e) {
throw new ExecutionException("Failed to check cert link on load balancer due to " + e.getMessage());
}
return false;
}
}
@ -3624,16 +3775,22 @@ public class NetscalerResource implements ServerResource {
return counterName.replace(' ', '_');
}
private String generateSslCertName(String srcIp, long srcPort) {
private String generateSslCertName(String fingerPrint) {
// maximum length supported by NS is 31
return genObjectName("Cloud-Cert", srcIp, srcPort);
// the first 20 characters of the SHA-1 checksum are the unique id
String uniqueId = fingerPrint.replace(":","").substring(0,20);
return genObjectName("Cloud-Cert", uniqueId);
}
private String generateSslKeyName(String srcIp, long srcPort) {
return genObjectName("Cloud-Key", srcIp, srcPort);
private String generateSslKeyName(String fingerPrint) {
String uniqueId = fingerPrint.replace(":","").substring(0,20);
return genObjectName("Cloud-Key", uniqueId);
}
private String generateSslCertKeyName(String srcIp, long srcPort) {
return genObjectName("Cloud-CertKey", srcIp, srcPort);
private String generateSslCertKeyName(String fingerPrint){
String uniqueId = fingerPrint.replace(":","").substring(0,20);
return genObjectName("Cloud-Cert", uniqueId);
}
private String genObjectName(Object... args) {

View File

@ -1121,8 +1121,7 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
return null;
}
return new LbSslCert(certVO.getCertificate(), certVO.getKey(),
certVO.getChain(), certVO.getPassword(), lbCertMap.isRevoke());
return new LbSslCert(certVO.getCertificate(), certVO.getKey(), certVO.getPassword(), certVO.getChain(), certVO.getFingerPrint(), lbCertMap.isRevoke());
}
@Override
@ -1174,11 +1173,6 @@ public class LoadBalancingRulesManagerImpl<Type> extends ManagerBase implements
LoadBalancerCertMapVO certMap = new LoadBalancerCertMapVO(lbRuleId,certId,false);
_lbCertMapDao.persist(certMap);
applyLoadBalancerConfig(loadBalancer.getId());
/*s_logger.warn("Failed to apply Ssl Cert to LB " + loadBalancer.getId());
CloudRuntimeException ex = new CloudRuntimeException(
"Failed to apply Ssl Cert to LB " + loadBalancer.getId());
ex.addProxyObject(loadBalancer.getUuid(), "loadBalancerId");
throw ex;*/
success = true;
} catch (ResourceUnavailableException e) {
if (isRollBackAllowedForProvider(loadBalancer)) {

View File

@ -16,14 +16,60 @@
// under the License.
package org.apache.cloudstack.network.lb;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertPathBuilderException;
import java.security.cert.CertStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.ejb.Local;
import javax.inject.Inject;
import com.cloud.event.ActionEvent;
import com.cloud.event.EventTypes;
import com.cloud.network.dao.*;
import com.cloud.network.dao.LoadBalancerCertMapDao;
import com.cloud.network.dao.LoadBalancerCertMapVO;
import com.cloud.network.dao.LoadBalancerVO;
import com.cloud.network.dao.SslCertDao;
import com.cloud.network.dao.SslCertVO;
import com.cloud.network.lb.CertService;
import com.cloud.network.rules.LoadBalancer;
import com.cloud.user.dao.AccountDao;
import com.cloud.utils.db.EntityManager;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PasswordFinder;
import org.apache.cloudstack.api.command.user.loadbalancer.DeleteSslCertCmd;
import org.apache.cloudstack.api.command.user.loadbalancer.ListSslCertsCmd;
@ -37,30 +83,6 @@ import com.cloud.utils.db.DB;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.context.CallContext;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PasswordFinder;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.ejb.Local;
import javax.inject.Inject;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Local(value = {CertService.class})
public class CertServiceImpl implements CertService {
@ -68,10 +90,14 @@ public class CertServiceImpl implements CertService {
private static final Logger s_logger = Logger.getLogger(CertServiceImpl.class);
@Inject AccountManager _accountMgr;
@Inject AccountDao _accountDao;
@Inject SslCertDao _sslCertDao;
@Inject LoadBalancerCertMapDao _lbCertDao;
@Inject EntityManager _entityMgr;
@Inject
AccountDao _accountDao;
@Inject
SslCertDao _sslCertDao;
@Inject
LoadBalancerCertMapDao _lbCertDao;
@Inject
EntityManager _entityMgr;
@ -92,6 +118,7 @@ public class CertServiceImpl implements CertService {
validate(cert, key, password, chain);
s_logger.debug("Certificate Validation succeeded");
String fingerPrint = generateFingerPrint(parseCertificate(cert));
Long accountId = CallContext.current().getCallingAccount().getId();
@ -365,14 +392,17 @@ public class CertServiceImpl implements CertService {
params = new PKIXBuilderParameters(anchors, target);
params.setRevocationEnabled(false);
params.addCertStore(CertStore.getInstance("Collection", new CollectionCertStoreParameters(certs)));
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
builder.build(params);
} catch (InvalidAlgorithmParameterException e) {
throw new IllegalArgumentException("Invalid certificate chain", e);
} catch (CertPathBuilderException e) {
throw new IllegalArgumentException("Invalid certificate chain", e);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("Invalid certificate chain", e);
} catch (NoSuchProviderException e) {
throw new CloudRuntimeException("No provider for certificate validation", e);
}
}
@ -485,4 +515,4 @@ public class CertServiceImpl implements CertService {
return password_requested;
}
}
}
}

View File

@ -20,21 +20,28 @@ import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
import java.util.List;
import com.cloud.utils.exception.CloudRuntimeException;
import org.apache.commons.codec.binary.Base64;
import com.cloud.utils.Ternary;
import org.bouncycastle.openssl.PEMReader;
public class CertificateHelper {
public static byte[] buildAndSaveKeystore(String alias, String cert, String privateKey, String storePassword) throws KeyStoreException, CertificateException,
@ -105,4 +112,53 @@ public class CertificateHelper {
PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec (Base64.decodeBase64(base64EncodedKeyContent));
return kf.generatePrivate (keysp);
}
public static List<Certificate> parseChain(String chain) throws IOException {
List<Certificate> certs = new ArrayList<Certificate>();
PEMReader reader = new PEMReader(new StringReader(chain));
Certificate crt = null;
while ((crt = (Certificate)reader.readObject()) != null) {
if (crt instanceof X509Certificate) {
certs.add(crt);
}
}
if (certs.size() == 0)
throw new IllegalArgumentException("Unable to decode certificate chain");
return certs;
}
public static String generateFingerPrint(Certificate cert) {
final char[] HEX = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
StringBuilder buffer = new StringBuilder(60);
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
byte[] data = md.digest(cert.getEncoded());
for (int i = 0; i < data.length; i++) {
if (buffer.length() > 0) {
buffer.append(":");
}
buffer.append(HEX[(0xF0 & data[i]) >>> 4]);
buffer.append(HEX[0x0F & data[i]]);
}
} catch (CertificateEncodingException e) {
throw new CloudRuntimeException("Bad certificate encoding");
} catch (NoSuchAlgorithmException e) {
throw new CloudRuntimeException("Bad certificate algorithm");
}
return buffer.toString();
}
}