Java tutorial
/************************************************************************* * * * CESeCore: CE Security Core * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or any later version. * * * * See terms of license at gnu.org. * * * *************************************************************************/ package org.cesecore.certificates.util; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Provider; import java.security.PublicKey; import java.security.Security; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; import java.security.spec.EllipticCurve; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x9.X9ObjectIdentifiers; import org.bouncycastle.cms.CMSSignedGenerator; import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; import org.cesecore.config.CesecoreConfiguration; import org.cesecore.keys.util.KeyTools; import org.cesecore.util.CertTools; import org.ejbca.cvc.AlgorithmUtil; import org.ejbca.cvc.CVCPublicKey; import org.ejbca.cvc.CardVerifiableCertificate; import org.ejbca.cvc.OIDField; /** * Various helper methods for handling the mappings between different key and * signature algorithms. * * This class has to be updated when new key or signature algorithms are * added to EJBCA. * * @see AlgorithmConstants * @see CertTools#getSignatureAlgorithm * @see KeyTools#getKeyLength * * @version $Id: AlgorithmTools.java 20578 2015-01-20 09:25:30Z mikekushner $ */ public abstract class AlgorithmTools { /** Log4j instance */ private static final Logger log = Logger.getLogger(AlgorithmTools.class); /** String used for an unknown keyspec in CA token properties */ public static final String KEYSPEC_UNKNOWN = "unknown"; /** Signature algorithms supported by RSA keys */ private static final Collection<String> SIG_ALGS_RSA; /** Signature algorithms supported by DSA keys */ private static final Collection<String> SIG_ALGS_DSA; /** Signature algorithms supported by ECDSA keys */ private static final Collection<String> SIG_ALGS_ECDSA; /** Signature algorithms supported by GOST keys */ private static final Collection<String> SIG_ALGS_ECGOST3410; /** Signature algorithms supported by DSTU4145 keys */ private static final Collection<String> SIG_ALGS_DSTU4145; static { SIG_ALGS_RSA = new LinkedList<String>(); SIG_ALGS_RSA.add(AlgorithmConstants.SIGALG_SHA1_WITH_RSA); SIG_ALGS_RSA.add(AlgorithmConstants.SIGALG_SHA1_WITH_RSA_AND_MGF1); SIG_ALGS_RSA.add(AlgorithmConstants.SIGALG_SHA256_WITH_RSA); SIG_ALGS_RSA.add(AlgorithmConstants.SIGALG_SHA256_WITH_RSA_AND_MGF1); SIG_ALGS_DSA = new LinkedList<String>(); SIG_ALGS_DSA.add(AlgorithmConstants.SIGALG_SHA1_WITH_DSA); SIG_ALGS_ECDSA = new LinkedList<String>(); SIG_ALGS_ECDSA.add(AlgorithmConstants.SIGALG_SHA1_WITH_ECDSA); SIG_ALGS_ECDSA.add(AlgorithmConstants.SIGALG_SHA224_WITH_ECDSA); SIG_ALGS_ECDSA.add(AlgorithmConstants.SIGALG_SHA256_WITH_ECDSA); SIG_ALGS_ECDSA.add(AlgorithmConstants.SIGALG_SHA384_WITH_ECDSA); SIG_ALGS_ECDSA.add(AlgorithmConstants.SIGALG_SHA512_WITH_ECDSA); SIG_ALGS_ECGOST3410 = new LinkedList<String>(); SIG_ALGS_ECGOST3410.add(AlgorithmConstants.SIGALG_GOST3411_WITH_ECGOST3410); SIG_ALGS_DSTU4145 = new LinkedList<String>(); SIG_ALGS_DSTU4145.add(AlgorithmConstants.SIGALG_GOST3411_WITH_DSTU4145); } /** * Returns a signing algorithm to use selecting from a list of possible algorithms. * * @param sigalgs the list of possible algorithms, ;-separated. Example "SHA1WithRSA;SHA1WithECDSA". * @param pk public key of signer, so we can choose between RSA, DSA and ECDSA algorithms * @return A single algorithm to use Example: SHA1WithRSA, SHA1WithDSA or SHA1WithECDSA */ public static String getSigningAlgFromAlgSelection(String sigalgs, PublicKey pk) { String sigAlg = null; String[] algs = StringUtils.split(sigalgs, ';'); for (int i = 0; i < algs.length; i++) { if (AlgorithmTools.isCompatibleSigAlg(pk, algs[i])) { sigAlg = algs[i]; break; } } log.debug("Using signature algorithm for response: " + sigAlg); return sigAlg; } /** * Gets the name of matching key algorithm from a public key as defined by * <i>AlgorithmConstants</i>. * @param publickey Public key to find matching key algorithm for. * @return Name of the matching key algorithm or null if no match. * @see AlgorithmConstants#KEYALGORITHM_RSA * @see AlgorithmConstants#KEYALGORITHM_DSA * @see AlgorithmConstants#KEYALGORITHM_ECDSA */ public static String getKeyAlgorithm(final PublicKey publickey) { String keyAlg = null; if (publickey instanceof RSAPublicKey) { keyAlg = AlgorithmConstants.KEYALGORITHM_RSA; } else if (publickey instanceof DSAPublicKey) { keyAlg = AlgorithmConstants.KEYALGORITHM_DSA; } else if (publickey instanceof ECPublicKey) { final String algo = publickey.getAlgorithm(); if (StringUtils.equals(algo, AlgorithmConstants.KEYALGORITHM_ECGOST3410)) { keyAlg = AlgorithmConstants.KEYALGORITHM_ECGOST3410; } else if (StringUtils.equals(algo, AlgorithmConstants.KEYALGORITHM_DSTU4145)) { keyAlg = AlgorithmConstants.KEYALGORITHM_DSTU4145; } else { keyAlg = AlgorithmConstants.KEYALGORITHM_ECDSA; } } return keyAlg; } /** * Gets a collection of signature algorithm names supported by the given * key. * @param publickey key to find supported algorithms for. * @return Collection of zero or more signature algorithm names * @see AlgorithmConstants */ public static Collection<String> getSignatureAlgorithms(final PublicKey publickey) { final Collection<String> ret; if (publickey instanceof RSAPublicKey) { ret = SIG_ALGS_RSA; } else if (publickey instanceof DSAPublicKey) { ret = SIG_ALGS_DSA; } else if (publickey instanceof ECPublicKey) { final String algo = publickey.getAlgorithm(); if (StringUtils.equals(algo, AlgorithmConstants.KEYALGORITHM_ECGOST3410)) { ret = SIG_ALGS_ECGOST3410; } else if (StringUtils.equals(algo, AlgorithmConstants.KEYALGORITHM_DSTU4145)) { ret = SIG_ALGS_DSTU4145; } else { ret = SIG_ALGS_ECDSA; } } else { ret = Collections.emptyList(); } return ret; } /** * Gets the key algorithm matching a specific signature algorithm. * @param signatureAlgorithm to get matching key algorithm for * @return The key algorithm matching the signature or algorithm or * the default if no matching was found. * @see AlgorithmConstants */ public static String getKeyAlgorithmFromSigAlg(final String signatureAlgorithm) { final String ret; if (signatureAlgorithm.contains("ECDSA")) { ret = AlgorithmConstants.KEYALGORITHM_ECDSA; } else if (signatureAlgorithm.contains("GOST3410")) { ret = AlgorithmConstants.KEYALGORITHM_ECGOST3410; } else if (signatureAlgorithm.contains("DSTU4145")) { ret = AlgorithmConstants.KEYALGORITHM_DSTU4145; } else if (signatureAlgorithm.contains("DSA")) { ret = AlgorithmConstants.KEYALGORITHM_DSA; } else { ret = AlgorithmConstants.KEYALGORITHM_RSA; } return ret; } /** * Gets the key specification from a public key. Example: "2048" for a RSA * or DSA key or "secp256r1" for EC key. The EC curve is only detected * if <i>publickey</i> is an object known by the bouncy castle provider. * @param publicKey The public key to get the key specification from * @return The key specification, "unknown" if it could not be determined and * null if the key algorithm is not supported */ public static String getKeySpecification(final PublicKey publicKey) { if (log.isTraceEnabled()) { log.trace(">getKeySpecification"); } String keyspec = null; if (publicKey instanceof RSAPublicKey) { keyspec = Integer.toString(((RSAPublicKey) publicKey).getModulus().bitLength()); } else if (publicKey instanceof DSAPublicKey) { keyspec = Integer.toString(((DSAPublicKey) publicKey).getParams().getP().bitLength()); } else if (publicKey instanceof ECPublicKey) { final ECPublicKey ecPublicKey = (ECPublicKey) publicKey; if (ecPublicKey.getParams() instanceof ECNamedCurveSpec) { keyspec = ((ECNamedCurveSpec) ecPublicKey.getParams()).getName(); // Prefer to return a curve name alias that also works with the default and BC provider for (String keySpecAlias : getEcKeySpecAliases(keyspec)) { if (isNamedECKnownInDefaultProvider(keySpecAlias)) { keyspec = keySpecAlias; break; } } } else { keyspec = KEYSPEC_UNKNOWN; // Try to detect if it is a curve name known by BC even though the public key isn't a BC key final ECParameterSpec namedCurve = ecPublicKey.getParams(); if (namedCurve != null) { final int c1 = namedCurve.getCofactor(); final EllipticCurve ec1 = namedCurve.getCurve(); final BigInteger a1 = ec1.getA(); final BigInteger b1 = ec1.getB(); final int fs1 = ec1.getField().getFieldSize(); //final byte[] s1 = ec1.getSeed(); final ECPoint g1 = namedCurve.getGenerator(); final BigInteger ax1 = g1.getAffineX(); final BigInteger ay1 = g1.getAffineY(); final BigInteger o1 = namedCurve.getOrder(); if (log.isDebugEnabled()) { log.debug("a1=" + a1 + " b1=" + b1 + " fs1=" + fs1 + " ax1=" + ax1 + " ay1=" + ay1 + " o1=" + o1 + " c1=" + c1); } @SuppressWarnings("unchecked") final Enumeration<String> ecNamedCurves = ECNamedCurveTable.getNames(); while (ecNamedCurves.hasMoreElements()) { final String ecNamedCurveBc = ecNamedCurves.nextElement(); final ECNamedCurveParameterSpec parameterSpec2 = ECNamedCurveTable .getParameterSpec(ecNamedCurveBc); final ECCurve ec2 = parameterSpec2.getCurve(); final BigInteger a2 = ec2.getA().toBigInteger(); final BigInteger b2 = ec2.getB().toBigInteger(); final int fs2 = ec2.getFieldSize(); final org.bouncycastle.math.ec.ECPoint g2 = parameterSpec2.getG(); final BigInteger ax2 = g2.getX().toBigInteger(); final BigInteger ay2 = g2.getY().toBigInteger(); final BigInteger h2 = parameterSpec2.getH(); final BigInteger n2 = parameterSpec2.getN(); if (a1.equals(a2) && ax1.equals(ax2) && b1.equals(b2) && ay1.equals(ay2) && fs1 == fs2 && o1.equals(n2) && c1 == h2.intValue()) { // We have a matching curve here! if (log.isDebugEnabled()) { log.debug("a2=" + a2 + " b2=" + b2 + " fs2=" + fs2 + " ax2=" + ax2 + " ay2=" + ay2 + " h2=" + h2 + " n2=" + n2 + " " + ecNamedCurveBc); } // Since this public key is a SUN PKCS#11 pub key if we get here, we only return an alias if it is recognized by the provider if (isNamedECKnownInDefaultProvider(ecNamedCurveBc)) { keyspec = ecNamedCurveBc; break; } } } } } } if (log.isTraceEnabled()) { log.trace("<getKeySpecification: " + keyspec); } return keyspec; } /** Check if the curve name is known by the first found PKCS#11 provider or default (if none was found)*/ public static boolean isNamedECKnownInDefaultProvider(String ecNamedCurveBc) { final Provider[] providers = Security.getProviders("KeyPairGenerator.EC"); String providerName = providers[0].getName(); try { for (Provider ecProvider : providers) { //This will list something like: SunPKCS11-NSS, BC, SunPKCS11-<library>-slot<slotnumber> if (log.isDebugEnabled()) { log.debug("Found EC capable provider named: " + ecProvider.getName()); } if (ecProvider.getName().startsWith("SunPKCS11-") && !ecProvider.getName().startsWith("SunPKCS11-NSS")) { providerName = ecProvider.getName(); break; } } final KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", providerName); kpg.initialize(new ECGenParameterSpec(ecNamedCurveBc)); return true; } catch (InvalidAlgorithmParameterException e) { if (log.isDebugEnabled()) { log.debug(ecNamedCurveBc + " is not available in provider " + providerName); } } catch (NoSuchAlgorithmException e) { throw new RuntimeException( "EC capable provider " + providerName + " could no longer handle elliptic curve algorithm..", e); } catch (NoSuchProviderException e) { throw new RuntimeException("EC capable provider " + providerName + " disappeard unexpectedly.", e); } return false; } /** @return a list of aliases for the provided curve name (including the provided name) */ public static List<String> getEcKeySpecAliases(final String namedEllipticCurve) { final ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec(namedEllipticCurve); final List<String> ret = new ArrayList<String>(); ret.add(namedEllipticCurve); if (parameterSpec != null) { // GOST and DSTU aren't present in ECNamedCurveTable (and don't have aliases) @SuppressWarnings("unchecked") final Enumeration<String> ecNamedCurves = ECNamedCurveTable.getNames(); while (ecNamedCurves.hasMoreElements()) { final String currentCurve = ecNamedCurves.nextElement(); if (!namedEllipticCurve.equals(currentCurve)) { final ECNamedCurveParameterSpec parameterSpec2 = ECNamedCurveTable .getParameterSpec(currentCurve); if (parameterSpec.equals(parameterSpec2)) { ret.add(currentCurve); } } } } return ret; } /** * Gets the algorithm to use for encryption given a specific signature algorithm. * Some signature algorithms (i.e. DSA and ECDSA) can not be used for * encryption so they are instead substituted with RSA with equivalent hash * algorithm. * @param signatureAlgorithm to find a encryption algorithm for * @return an other encryption algorithm or same as signature algorithm if it * can be used for encryption */ public static String getEncSigAlgFromSigAlg(final String signatureAlgorithm) { String encSigAlg = signatureAlgorithm; if (signatureAlgorithm.equals(AlgorithmConstants.SIGALG_SHA512_WITH_ECDSA)) { encSigAlg = AlgorithmConstants.SIGALG_SHA256_WITH_RSA; } else if (signatureAlgorithm.equals(AlgorithmConstants.SIGALG_SHA384_WITH_ECDSA)) { // Even though SHA384 is used for ECDSA, pay it safe and use SHA256 for RSA since we do not trust all PKCS#11 implementations // to be so new to support SHA384WithRSA encSigAlg = AlgorithmConstants.SIGALG_SHA256_WITH_RSA; } else if (signatureAlgorithm.equals(AlgorithmConstants.SIGALG_SHA256_WITH_ECDSA)) { encSigAlg = AlgorithmConstants.SIGALG_SHA256_WITH_RSA; } else if (signatureAlgorithm.equals(AlgorithmConstants.SIGALG_SHA224_WITH_ECDSA)) { encSigAlg = AlgorithmConstants.SIGALG_SHA256_WITH_RSA; } else if (signatureAlgorithm.equals(AlgorithmConstants.SIGALG_SHA1_WITH_ECDSA)) { encSigAlg = AlgorithmConstants.SIGALG_SHA1_WITH_RSA; } else if (signatureAlgorithm.equals(AlgorithmConstants.SIGALG_SHA1_WITH_DSA)) { encSigAlg = AlgorithmConstants.SIGALG_SHA1_WITH_RSA; } else if (signatureAlgorithm.equals(AlgorithmConstants.SIGALG_GOST3411_WITH_ECGOST3410)) { encSigAlg = AlgorithmConstants.SIGALG_SHA1_WITH_RSA; } else if (signatureAlgorithm.equals(AlgorithmConstants.SIGALG_GOST3411_WITH_DSTU4145)) { encSigAlg = AlgorithmConstants.SIGALG_SHA1_WITH_RSA; } return encSigAlg; } /** * Answers if the key can be used together with the given signature algorithm. * @param publicKey public key to use * @param signatureAlgorithm algorithm to test * @return true if signature algorithm can be used with the public key algorithm */ public static boolean isCompatibleSigAlg(final PublicKey publicKey, final String signatureAlgorithm) { String algname = publicKey.getAlgorithm(); if (algname == null) algname = ""; boolean isGost3410 = algname.contains("GOST3410"); boolean isDstu4145 = algname.contains("DSTU4145"); boolean isSpecialECC = isGost3410 || isDstu4145; boolean ret = false; if (StringUtils.contains(signatureAlgorithm, AlgorithmConstants.KEYALGORITHM_RSA)) { if (publicKey instanceof RSAPublicKey) { ret = true; } } else if (StringUtils.contains(signatureAlgorithm, AlgorithmConstants.KEYALGORITHM_ECDSA)) { if (publicKey instanceof ECPublicKey && !isSpecialECC) { ret = true; } } else if (StringUtils.contains(signatureAlgorithm, AlgorithmConstants.KEYALGORITHM_DSA)) { if (publicKey instanceof DSAPublicKey) { ret = true; } } else if (StringUtils.contains(signatureAlgorithm, AlgorithmConstants.KEYALGORITHM_ECGOST3410)) { if (publicKey instanceof ECPublicKey && isGost3410) { ret = true; } } else if (StringUtils.contains(signatureAlgorithm, AlgorithmConstants.KEYALGORITHM_DSTU4145)) { if (publicKey instanceof ECPublicKey && isDstu4145) { ret = true; } } return ret; } /** * Simple methods that returns the signature algorithm value from the certificate. Not usable for setting signature algorithms names in EJBCA, * only for human presentation. * * @return Signature algorithm name from the certificate as a human readable string, for example SHA1WithRSA. */ public static String getCertSignatureAlgorithmNameAsString(Certificate cert) { String certSignatureAlgorithm = null; if (cert instanceof X509Certificate) { X509Certificate x509cert = (X509Certificate) cert; certSignatureAlgorithm = x509cert.getSigAlgName(); if (log.isDebugEnabled()) { log.debug("certSignatureAlgorithm is: " + certSignatureAlgorithm); } } else if (StringUtils.equals(cert.getType(), "CVC")) { CardVerifiableCertificate cvccert = (CardVerifiableCertificate) cert; CVCPublicKey cvcpk; try { cvcpk = cvccert.getCVCertificate().getCertificateBody().getPublicKey(); OIDField oid = cvcpk.getObjectIdentifier(); certSignatureAlgorithm = AlgorithmUtil.getAlgorithmName(oid); } catch (NoSuchFieldException e) { log.error("NoSuchFieldException: ", e); } } // Try to make it easier to display some signature algorithms that cert.getSigAlgName() does not have a good string for. if (certSignatureAlgorithm.equalsIgnoreCase("1.2.840.113549.1.1.10")) { // Figure out if it is SHA1 or SHA256 // If we got this value we should have a x509 cert if (cert instanceof X509Certificate) { X509Certificate x509cert = (X509Certificate) cert; certSignatureAlgorithm = x509cert.getSigAlgName(); byte[] params = x509cert.getSigAlgParams(); if ((params != null) && (params.length == 2)) { certSignatureAlgorithm = AlgorithmConstants.SIGALG_SHA1_WITH_RSA_AND_MGF1; } else { certSignatureAlgorithm = AlgorithmConstants.SIGALG_SHA256_WITH_RSA_AND_MGF1; } } } // SHA256WithECDSA does not work to be translated in JDK5. if (certSignatureAlgorithm.equalsIgnoreCase("1.2.840.10045.4.3.2")) { certSignatureAlgorithm = AlgorithmConstants.SIGALG_SHA256_WITH_ECDSA; } // GOST3410 if (isGost3410Enabled() && certSignatureAlgorithm.equalsIgnoreCase(CesecoreConfiguration.getOidGost3410())) { certSignatureAlgorithm = AlgorithmConstants.SIGALG_GOST3411_WITH_ECGOST3410; } // DSTU4145 if (isDstu4145Enabled() && certSignatureAlgorithm.startsWith(CesecoreConfiguration.getOidDstu4145() + ".")) { certSignatureAlgorithm = AlgorithmConstants.SIGALG_GOST3411_WITH_DSTU4145; } return certSignatureAlgorithm; } /** * Simple method that looks at the certificate and determines, from EJBCA's standpoint, which signature algorithm it is * * @param cert the cert to examine * @return Signature algorithm name from AlgorithmConstants.SIGALG_SHA1_WITH_RSA etc. */ public static String getSignatureAlgorithm(Certificate cert) { String signatureAlgorithm = null; String certSignatureAlgorithm = getCertSignatureAlgorithmNameAsString(cert); // The signature string returned from the certificate is often not usable as the signature algorithm we must // specify for a CA in EJBCA, for example SHA1WithECDSA is returned as only ECDSA, so we need some magic to fix it up. PublicKey publickey = cert.getPublicKey(); if (publickey instanceof RSAPublicKey) { if (certSignatureAlgorithm.indexOf("MGF1") == -1) { if (certSignatureAlgorithm.indexOf("MD5") != -1) { signatureAlgorithm = "MD5WithRSA"; } else if (certSignatureAlgorithm.indexOf("SHA1") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA1_WITH_RSA; } else if (certSignatureAlgorithm.indexOf("256") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA256_WITH_RSA; } else if (certSignatureAlgorithm.indexOf("384") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA384_WITH_RSA; } else if (certSignatureAlgorithm.indexOf("512") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA512_WITH_RSA; } } else { if (certSignatureAlgorithm.indexOf("SHA1") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA1_WITH_RSA_AND_MGF1; } else { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA256_WITH_RSA_AND_MGF1; } } } else if (publickey instanceof DSAPublicKey) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA1_WITH_DSA; } else { if (certSignatureAlgorithm.indexOf("256") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA256_WITH_ECDSA; } else if (certSignatureAlgorithm.indexOf("224") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA224_WITH_ECDSA; } else if (certSignatureAlgorithm.indexOf("384") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA384_WITH_ECDSA; } else if (certSignatureAlgorithm.indexOf("512") != -1) { signatureAlgorithm = AlgorithmConstants.SIGALG_SHA512_WITH_ECDSA; } else if (certSignatureAlgorithm.indexOf("ECDSA") != -1) { // From x509cert.getSigAlgName(), SHA1withECDSA only returns name ECDSA signatureAlgorithm = AlgorithmConstants.SIGALG_SHA1_WITH_ECDSA; } else if (isGost3410Enabled() && certSignatureAlgorithm .equalsIgnoreCase(AlgorithmConstants.SIGALG_GOST3411_WITH_ECGOST3410)) { signatureAlgorithm = AlgorithmConstants.SIGALG_GOST3411_WITH_ECGOST3410; } else if (isDstu4145Enabled() && certSignatureAlgorithm.equalsIgnoreCase(AlgorithmConstants.SIGALG_GOST3411_WITH_DSTU4145)) { signatureAlgorithm = AlgorithmConstants.SIGALG_GOST3411_WITH_DSTU4145; } } if (log.isDebugEnabled()) { log.debug("getSignatureAlgorithm: " + signatureAlgorithm); } return signatureAlgorithm; } // getSignatureAlgorithm /** * Get the digest algorithm corresponding to the signature algorithm. This is used for the creation of * PKCS7 file. SHA1 shall always be used, but it is not working with GOST which needs GOST3411 digest. * */ public static String getDigestFromSigAlg(String sigAlg) { if (sigAlg.toUpperCase().contains("GOST") || sigAlg.toUpperCase().contains("DSTU")) { return CMSSignedGenerator.DIGEST_GOST3411; } else { if (sigAlg.equals(X9ObjectIdentifiers.ecdsa_with_SHA1.getId()) || sigAlg.equals(PKCSObjectIdentifiers.sha1WithRSAEncryption.getId())) { return CMSSignedGenerator.DIGEST_SHA1; } else if (sigAlg.equals(X9ObjectIdentifiers.ecdsa_with_SHA224.getId()) || sigAlg.equals(PKCSObjectIdentifiers.sha224WithRSAEncryption.getId())) { return CMSSignedGenerator.DIGEST_SHA224; } else if (sigAlg.equals(X9ObjectIdentifiers.ecdsa_with_SHA256.getId()) || sigAlg.equals(PKCSObjectIdentifiers.sha256WithRSAEncryption.getId())) { return CMSSignedGenerator.DIGEST_SHA256; } else if (sigAlg.equals(X9ObjectIdentifiers.ecdsa_with_SHA384.getId()) || sigAlg.equals(PKCSObjectIdentifiers.sha384WithRSAEncryption.getId())) { return CMSSignedGenerator.DIGEST_SHA384; } else if (sigAlg.equals(X9ObjectIdentifiers.ecdsa_with_SHA512.getId()) || sigAlg.equals(PKCSObjectIdentifiers.sha512WithRSAEncryption.getId())) { return CMSSignedGenerator.DIGEST_SHA512; } else if (sigAlg.equals(PKCSObjectIdentifiers.md5WithRSAEncryption.getId())) { return CMSSignedGenerator.DIGEST_MD5; } else if (sigAlg.equals(CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001.getId())) { return CMSSignedGenerator.DIGEST_GOST3411; } } return CMSSignedGenerator.DIGEST_SHA1; } /** Calculates which signature algorithm to use given a key type and a digest algorithm * * @param digestAlg objectId of a digest algorithm, CMSSignedGenerator.DIGEST_SHA256 etc * @param keyAlg RSA, EC, DSA * @return ASN1ObjectIdentifier with the id of PKCSObjectIdentifiers.sha1WithRSAEncryption, X9ObjectIdentifiers.ecdsa_with_SHA1, X9ObjectIdentifiers.id_dsa_with_sha1, etc */ public static ASN1ObjectIdentifier getSignAlgOidFromDigestAndKey(final String digestAlg, final String keyAlg) { if (log.isTraceEnabled()) { log.trace(">getSignAlg(" + digestAlg + "," + keyAlg + ")"); } // Default to SHA1WithRSA if everything else fails ASN1ObjectIdentifier oid = PKCSObjectIdentifiers.sha1WithRSAEncryption; if (keyAlg.equals(AlgorithmConstants.KEYALGORITHM_EC) || keyAlg.equals(AlgorithmConstants.KEYALGORITHM_ECDSA)) { oid = X9ObjectIdentifiers.ecdsa_with_SHA1; } else if (keyAlg.equals(AlgorithmConstants.KEYALGORITHM_DSA)) { oid = X9ObjectIdentifiers.id_dsa_with_sha1; } else if (keyAlg.equals(AlgorithmConstants.KEYALGORITHM_ECGOST3410)) { oid = CryptoProObjectIdentifiers.gostR3411_94_with_gostR3410_2001; } else if (keyAlg.equals(AlgorithmConstants.KEYALGORITHM_DSTU4145)) { oid = new ASN1ObjectIdentifier(CesecoreConfiguration.getOidDstu4145()); } if (digestAlg != null) { if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA256) && keyAlg.equals(AlgorithmConstants.KEYALGORITHM_RSA)) { oid = PKCSObjectIdentifiers.sha256WithRSAEncryption; } else if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA512) && keyAlg.equals(AlgorithmConstants.KEYALGORITHM_RSA)) { oid = PKCSObjectIdentifiers.sha512WithRSAEncryption; } else if (digestAlg.equals(CMSSignedGenerator.DIGEST_MD5) && keyAlg.equals(AlgorithmConstants.KEYALGORITHM_RSA)) { oid = PKCSObjectIdentifiers.md5WithRSAEncryption; } else if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA256) && (keyAlg.equals(AlgorithmConstants.KEYALGORITHM_ECDSA) || keyAlg.equals(AlgorithmConstants.KEYALGORITHM_EC))) { oid = X9ObjectIdentifiers.ecdsa_with_SHA256; } else if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA224) && (keyAlg.equals(AlgorithmConstants.KEYALGORITHM_ECDSA) || keyAlg.equals(AlgorithmConstants.KEYALGORITHM_EC))) { oid = X9ObjectIdentifiers.ecdsa_with_SHA224; } else if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA384) && (keyAlg.equals(AlgorithmConstants.KEYALGORITHM_ECDSA) || keyAlg.equals(AlgorithmConstants.KEYALGORITHM_EC))) { oid = X9ObjectIdentifiers.ecdsa_with_SHA384; } else if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA512) && (keyAlg.equals(AlgorithmConstants.KEYALGORITHM_ECDSA) || keyAlg.equals(AlgorithmConstants.KEYALGORITHM_EC))) { oid = X9ObjectIdentifiers.ecdsa_with_SHA512; } else if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA256) && keyAlg.equals(AlgorithmConstants.KEYALGORITHM_DSA)) { oid = NISTObjectIdentifiers.dsa_with_sha256; } else if (digestAlg.equals(CMSSignedGenerator.DIGEST_SHA512) && keyAlg.equals(AlgorithmConstants.KEYALGORITHM_DSA)) { oid = NISTObjectIdentifiers.dsa_with_sha512; } } if (log.isDebugEnabled()) { log.debug("getSignAlgOidFromDigestAndKey: " + oid.getId()); } return oid; } public static String getAlgorithmNameFromDigestAndKey(final String digestAlg, final String keyAlg) { return getAlgorithmNameFromOID(getSignAlgOidFromDigestAndKey(digestAlg, keyAlg)); } public static boolean isGost3410Enabled() { return CesecoreConfiguration.getOidGost3410() != null; } public static boolean isDstu4145Enabled() { return CesecoreConfiguration.getOidDstu4145() != null; } public static boolean isSigAlgEnabled(String sigAlg) { if (AlgorithmConstants.SIGALG_GOST3411_WITH_ECGOST3410.equals(sigAlg)) { return isGost3410Enabled(); } else if (AlgorithmConstants.SIGALG_GOST3411_WITH_DSTU4145.equals(sigAlg)) { return isDstu4145Enabled(); } else { return true; } } /** * Returns the name of the algorithm corresponding to the specified OID * @param sigAlgOid * @return The name of the algorithm corresponding sigAlgOid or null if the algorithm is not recognized. */ public static String getAlgorithmNameFromOID(ASN1ObjectIdentifier sigAlgOid) { if (sigAlgOid.equals(PKCSObjectIdentifiers.md5WithRSAEncryption)) { return AlgorithmConstants.SIGALG_MD5_WITH_RSA; } if (sigAlgOid.equals(PKCSObjectIdentifiers.sha1WithRSAEncryption)) { return AlgorithmConstants.SIGALG_SHA1_WITH_RSA; } if (sigAlgOid.equals(PKCSObjectIdentifiers.sha256WithRSAEncryption)) { return AlgorithmConstants.SIGALG_SHA256_WITH_RSA; } if (sigAlgOid.equals(PKCSObjectIdentifiers.sha384WithRSAEncryption)) { return AlgorithmConstants.SIGALG_SHA384_WITH_RSA; } if (sigAlgOid.equals(PKCSObjectIdentifiers.sha512WithRSAEncryption)) { return AlgorithmConstants.SIGALG_SHA512_WITH_RSA; } if (sigAlgOid.equals(X9ObjectIdentifiers.ecdsa_with_SHA1)) { return AlgorithmConstants.SIGALG_SHA1_WITH_ECDSA; } if (sigAlgOid.equals(X9ObjectIdentifiers.ecdsa_with_SHA224)) { return AlgorithmConstants.SIGALG_SHA224_WITH_ECDSA; } if (sigAlgOid.equals(X9ObjectIdentifiers.ecdsa_with_SHA256)) { return AlgorithmConstants.SIGALG_SHA256_WITH_ECDSA; } if (sigAlgOid.equals(X9ObjectIdentifiers.ecdsa_with_SHA384)) { return AlgorithmConstants.SIGALG_SHA384_WITH_ECDSA; } if (sigAlgOid.equals(X9ObjectIdentifiers.ecdsa_with_SHA512)) { return AlgorithmConstants.SIGALG_SHA512_WITH_ECDSA; } // GOST3410 if (isGost3410Enabled() && sigAlgOid.getId().equalsIgnoreCase(CesecoreConfiguration.getOidGost3410())) { return AlgorithmConstants.SIGALG_GOST3411_WITH_ECGOST3410; } // DSTU4145 if (isDstu4145Enabled() && sigAlgOid.getId().startsWith(CesecoreConfiguration.getOidDstu4145() + ".")) { return AlgorithmConstants.SIGALG_GOST3411_WITH_DSTU4145; } return null; } }