/**
* DSS - Digital Signature Services
* Copyright (C) 2015 European Commission, provided under the CEF programme
*
* This file is part of the "DSS - Digital Signature Services" project.
*
* This library 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 (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package eu.europa.esig.dss;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* Supported signature algorithms.
*
*/
public enum SignatureAlgorithm {
RSA_SHA1(EncryptionAlgorithm.RSA, DigestAlgorithm.SHA1),
RSA_SHA224(EncryptionAlgorithm.RSA, DigestAlgorithm.SHA224),
RSA_SHA256(EncryptionAlgorithm.RSA, DigestAlgorithm.SHA256),
RSA_SHA384(EncryptionAlgorithm.RSA, DigestAlgorithm.SHA384),
RSA_SHA512(EncryptionAlgorithm.RSA, DigestAlgorithm.SHA512),
RSA_RIPEMD160(EncryptionAlgorithm.RSA, DigestAlgorithm.RIPEMD160),
RSA_MD5(EncryptionAlgorithm.RSA, DigestAlgorithm.MD5),
RSA_MD2(EncryptionAlgorithm.RSA, DigestAlgorithm.MD2),
RSA_SSA_PSS(EncryptionAlgorithm.RSA, DigestAlgorithm.SHA1),
ECDSA_SHA1(EncryptionAlgorithm.ECDSA, DigestAlgorithm.SHA1),
ECDSA_SHA224(EncryptionAlgorithm.ECDSA, DigestAlgorithm.SHA224),
ECDSA_SHA256(EncryptionAlgorithm.ECDSA, DigestAlgorithm.SHA256),
ECDSA_SHA384(EncryptionAlgorithm.ECDSA, DigestAlgorithm.SHA384),
ECDSA_SHA512(EncryptionAlgorithm.ECDSA, DigestAlgorithm.SHA512),
ECDSA_RIPEMD160(EncryptionAlgorithm.ECDSA, DigestAlgorithm.RIPEMD160),
DSA_SHA1(EncryptionAlgorithm.DSA, DigestAlgorithm.SHA1),
DSA_SHA256(EncryptionAlgorithm.DSA, DigestAlgorithm.SHA256),
HMAC_SHA1(EncryptionAlgorithm.HMAC, DigestAlgorithm.SHA1),
HMAC_SHA224(EncryptionAlgorithm.HMAC, DigestAlgorithm.SHA224),
HMAC_SHA256(EncryptionAlgorithm.HMAC, DigestAlgorithm.SHA256),
HMAC_SHA384(EncryptionAlgorithm.HMAC, DigestAlgorithm.SHA384),
HMAC_SHA512(EncryptionAlgorithm.HMAC, DigestAlgorithm.SHA512),
HMAC_RIPEMD160(EncryptionAlgorithm.HMAC, DigestAlgorithm.RIPEMD160);
private final EncryptionAlgorithm encryptionAlgo;
private final DigestAlgorithm digestAlgo;
// http://www.w3.org/TR/2013/NOTE-xmlsec-algorithms-20130411/
private final static Map<String, SignatureAlgorithm> XML_ALGORITHMS = registerXmlAlgorithms();
private final static Map<SignatureAlgorithm, String> XML_ALGORITHMS_FOR_KEY = registerXmlAlgorithmsForKey();
private static Map<String, SignatureAlgorithm> registerXmlAlgorithms() {
Map<String, SignatureAlgorithm> xmlAlgorithms = new HashMap<String, SignatureAlgorithm>();
xmlAlgorithms.put("http://www.w3.org/2000/09/xmldsig#rsa-sha1", RSA_SHA1);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha224", RSA_SHA224);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", RSA_SHA256);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", RSA_SHA384);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", RSA_SHA512);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160", RSA_RIPEMD160);
// Support of not standard AT algorithm name
// http://www.rfc-editor.org/rfc/rfc4051.txt --> http://www.rfc-editor.org/errata_search.php?rfc=4051
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more/rsa-ripemd160", RSA_RIPEMD160);
// Following algorithms are not in ETSI TS 102 176-1 V2.0.0:
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#rsa-md5", RSA_MD5);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#rsa-md2", RSA_MD2);
// Following end.
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", ECDSA_SHA1);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224", ECDSA_SHA224);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", ECDSA_SHA256);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384", ECDSA_SHA384);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", ECDSA_SHA512);
xmlAlgorithms.put("http://www.w3.org/2007/05/xmldsig-more#ecdsa-ripemd160", ECDSA_RIPEMD160);
xmlAlgorithms.put("http://www.w3.org/2000/09/xmldsig#dsa-sha1", DSA_SHA1);
xmlAlgorithms.put("http://www.w3.org/2009/xmldsig11#dsa-sha256", DSA_SHA256);
// Following algorithms are not in ETSI TS 102 176-1 V2.0.0:
xmlAlgorithms.put("http://www.w3.org/2000/09/xmldsig#hmac-sha1", HMAC_SHA1);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#hmac-sha224", HMAC_SHA224);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#hmac-sha256", HMAC_SHA256);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#hmac-sha384", HMAC_SHA384);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#hmac-sha512", HMAC_SHA512);
xmlAlgorithms.put("http://www.w3.org/2001/04/xmldsig-more#hmac-ripemd160", HMAC_RIPEMD160);
// Following end.
return xmlAlgorithms;
}
private static Map<SignatureAlgorithm, String> registerXmlAlgorithmsForKey() {
Map<SignatureAlgorithm, String> xmlAlgorithms = new HashMap<SignatureAlgorithm, String>();
for (Entry<String, SignatureAlgorithm> entry : XML_ALGORITHMS.entrySet()) {
xmlAlgorithms.put(entry.getValue(), entry.getKey());
}
return xmlAlgorithms;
}
private final static Map<String, SignatureAlgorithm> OID_ALGORITHMS = registerOIDAlgorithms();
private static Map<String, SignatureAlgorithm> registerOIDAlgorithms() {
Map<String, SignatureAlgorithm> oidAlgorithms = new HashMap<String, SignatureAlgorithm>();
oidAlgorithms.put("1.2.840.113549.1.1.5", RSA_SHA1);
oidAlgorithms.put("1.3.14.3.2.29", RSA_SHA1);
oidAlgorithms.put("1.2.840.113549.1.1.14", RSA_SHA224);
oidAlgorithms.put("1.2.840.113549.1.1.11", RSA_SHA256);
oidAlgorithms.put("1.2.840.113549.1.1.12", RSA_SHA384);
oidAlgorithms.put("1.2.840.113549.1.1.13", RSA_SHA512);
oidAlgorithms.put("1.3.36.3.3.1.2", RSA_RIPEMD160);
oidAlgorithms.put("1.2.840.113549.1.1.4", RSA_MD5);
oidAlgorithms.put("1.2.840.113549.1.1.2", RSA_MD2);
/**
* RFC 2313:<br>
* "md2WithRSAEncryption", 1.2.840.113549.1.1.2<br>
* "md4WithRSAEncryption", 1.2.840.113549.1.1.3<br>
* "md5WithRSAEncryption", 1.2.840.113549.1.1.4<br>
*/
oidAlgorithms.put("1.2.840.10045.4.1", ECDSA_SHA1);
oidAlgorithms.put("1.2.840.10045.4.3.1", ECDSA_SHA224);
oidAlgorithms.put("1.2.840.10045.4.3.2", ECDSA_SHA256);
oidAlgorithms.put("1.2.840.10045.4.3.3", ECDSA_SHA384);
oidAlgorithms.put("1.2.840.10045.4.3.4", ECDSA_SHA512);
oidAlgorithms.put("0.4.0.127.0.7.1.1.4.1.6", ECDSA_RIPEMD160);
oidAlgorithms.put("1.2.840.10040.4.3", DSA_SHA1);
oidAlgorithms.put("1.2.14888.3.0.1", DSA_SHA1);
oidAlgorithms.put("2.16.840.1.101.3.4.3.2", DSA_SHA256);
oidAlgorithms.put("1.2.840.113549.2.7", HMAC_SHA1);
oidAlgorithms.put("1.2.840.113549.2.8", HMAC_SHA224);
oidAlgorithms.put("1.2.840.113549.2.9", HMAC_SHA256);
oidAlgorithms.put("1.2.840.113549.2.10", HMAC_SHA384);
oidAlgorithms.put("1.2.840.113549.2.11", HMAC_SHA512);
oidAlgorithms.put("1.3.6.1.5.5.8.1.4", HMAC_RIPEMD160);
oidAlgorithms.put("1.2.840.113549.1.1.10", RSA_SSA_PSS);
return oidAlgorithms;
}
private final static Map<String, SignatureAlgorithm> JAVA_ALGORITHMS = registerJavaAlgorithms();
private final static Map<SignatureAlgorithm, String> JAVA_ALGORITHMS_FOR_KEY = registerJavaAlgorithmsForKey();
private static Map<String, SignatureAlgorithm> registerJavaAlgorithms() {
Map<String, SignatureAlgorithm> javaAlgorithms = new HashMap<String, SignatureAlgorithm>();
javaAlgorithms.put("SHA1withRSA", RSA_SHA1);
javaAlgorithms.put("SHA224withRSA", RSA_SHA224);
javaAlgorithms.put("SHA256withRSA", RSA_SHA256);
javaAlgorithms.put("SHA384withRSA", RSA_SHA384);
javaAlgorithms.put("SHA512withRSA", RSA_SHA512);
javaAlgorithms.put("RIPEMD160withRSA", RSA_RIPEMD160);
javaAlgorithms.put("MD5withRSA", RSA_MD5);
javaAlgorithms.put("MD2withRSA", RSA_MD2);
javaAlgorithms.put("SHA1withECDSA", ECDSA_SHA1);
javaAlgorithms.put("SHA224withECDSA", ECDSA_SHA224);
javaAlgorithms.put("SHA256withECDSA", ECDSA_SHA256);
javaAlgorithms.put("SHA384withECDSA", ECDSA_SHA384);
javaAlgorithms.put("SHA512withECDSA", ECDSA_SHA512);
javaAlgorithms.put("RIPEMD160withECDSA", ECDSA_RIPEMD160);
javaAlgorithms.put("SHA1withDSA", DSA_SHA1);
javaAlgorithms.put("SHA256withDSA", DSA_SHA256);
javaAlgorithms.put("SHA1withHMAC", HMAC_SHA1);
javaAlgorithms.put("SHA224withHMAC", HMAC_SHA224);
javaAlgorithms.put("SHA256withHMAC", HMAC_SHA256);
javaAlgorithms.put("SHA384withHMAC", HMAC_SHA384);
javaAlgorithms.put("SHA512withHMAC", HMAC_SHA512);
javaAlgorithms.put("RIPEMD160withHMAC", HMAC_RIPEMD160);
return javaAlgorithms;
}
private static Map<SignatureAlgorithm, String> registerJavaAlgorithmsForKey() {
final Map<SignatureAlgorithm, String> javaAlgorithms = new HashMap<SignatureAlgorithm, String>();
for (Entry<String, SignatureAlgorithm> entry : JAVA_ALGORITHMS.entrySet()) {
javaAlgorithms.put(entry.getValue(), entry.getKey());
}
return javaAlgorithms;
}
public static SignatureAlgorithm forXML(final String xmlName) {
final SignatureAlgorithm algorithm = XML_ALGORITHMS.get(xmlName);
if (algorithm == null) {
throw new DSSException("Unsupported algorithm: " + xmlName);
}
return algorithm;
}
/**
* This method return the {@code SignatureAlgorithm} or the default value if the algorithm is unknown.
*
* TODO: (Bob: 2014 Feb 13) this method can return UNKNOWN ALGORITHM...
*
* @param xmlName XML URI of the given algorithm
* @param defaultValue the default value to be returned if not found
* @return {@code SignatureAlgorithm} or default value
*/
public static SignatureAlgorithm forXML(final String xmlName, final SignatureAlgorithm defaultValue) {
final SignatureAlgorithm algorithm = XML_ALGORITHMS.get(xmlName);
if (algorithm == null) {
return defaultValue;
}
return algorithm;
}
public static SignatureAlgorithm forOID(final String oid) {
final SignatureAlgorithm algorithm = OID_ALGORITHMS.get(oid);
if (algorithm == null) {
throw new DSSException("Unsupported algorithm: " + oid);
}
return algorithm;
}
/**
* For given signature algorithm & digest algorithm this function returns the Java form of the signature algorithm Signature Algorithms
*
* The algorithm names in this section can be specified when generating an instance of Signature.
*
* NONEwithRSA - The RSA signature algorithm which does not use a digesting algorithm (e.g. MD5/SHA1) before performing the RSA operation. For more information about the RSA
* Signature algorithms, please see PKCS1.
*
* MD2withRSA MD5withRSA - The MD2/MD5 with RSA Encryption signature algorithm which uses the MD2/MD5 digest algorithm and RSA to create and verify RSA digital signatures as
* defined in PKCS1.
*
* SHA1withRSA SHA256withRSA SHA384withRSA SHA512withRSA - The signature algorithm with SHA-* and the RSA encryption algorithm as defined in the OSI Interoperability Workshop,
* using the padding conventions described in PKCS1.
*
* NONEwithDSA - The Digital Signature Algorithm as defined in FIPS PUB 186-2. The data must be exactly 20 bytes in length. This algorithms is also known under the alias name
* of rawDSA.
*
* SHA1withDSA - The DSA with SHA-1 signature algorithm which uses the SHA-1 digest algorithm and DSA to create and verify DSA digital signatures as defined in FIPS PUB 186.
*
* NONEwithECDSA SHA1withECDSA SHA256withECDSA SHA384withECDSA SHA512withECDSA (ECDSA) - The ECDSA signature algorithms as defined in ANSI X9.62. Note:"ECDSA" is an ambiguous
* name for the "SHA1withECDSA" algorithm and should not be used. The formal name "SHA1withECDSA" should be used instead.
*
* <digest>with<encryption> - Use this to form a name for a signature algorithm with a particular message digest (such as MD2 or MD5) and algorithm (such as RSA or DSA), just
* as was done for the explicitly-defined standard names in this section (MD2withRSA, etc.). For the new signature schemes defined in PKCS1 v 2.0, for which the
* <digest>with<encryption> form is insufficient, <digest>with<encryption>and<mgf> can be used to form a name. Here, <mgf> should be replaced by a mask generation function
* such
* as MGF1. Example: MD5withRSAandMGF1.
*
* @param javaName
* @return
*/
public static SignatureAlgorithm forJAVA(final String javaName) {
final SignatureAlgorithm algorithm = JAVA_ALGORITHMS.get(javaName);
if (algorithm == null) {
throw new DSSException("Unsupported algorithm: " + javaName);
}
return algorithm;
}
/**
* For given encryption algorithm & digest algorithm this function returns the signature algorithm.
*
* @param encryptionAlgorithm
* @param digestAlgorithm
* @return
*/
public static SignatureAlgorithm getAlgorithm(final EncryptionAlgorithm encryptionAlgorithm, final DigestAlgorithm digestAlgorithm) {
String digestAlgorithm_ = digestAlgorithm.getName();
digestAlgorithm_ = digestAlgorithm_.replace("-", "");
final String javaName = digestAlgorithm_ + "with" + encryptionAlgorithm.getName();
return JAVA_ALGORITHMS.get(javaName);
}
/**
* The default constructor.
*
* @param encryptionAlgorithm
* @param digestAlgorithm
*/
private SignatureAlgorithm(final EncryptionAlgorithm encryptionAlgorithm, final DigestAlgorithm digestAlgorithm) {
this.encryptionAlgo = encryptionAlgorithm;
this.digestAlgo = digestAlgorithm;
}
/**
* This method returns the encryption algorithm.
*
* @return
*/
public EncryptionAlgorithm getEncryptionAlgorithm() {
return encryptionAlgo;
}
/**
* This method returns the digest algorithm.
*
* @return
*/
public DigestAlgorithm getDigestAlgorithm() {
return digestAlgo;
}
/**
* Returns the XML ID of the signature algorithm.
*
* @return
*/
public String getXMLId() {
return XML_ALGORITHMS_FOR_KEY.get(this);
}
/**
* Returns algorithm identifier corresponding to JAVA JCE class names.
*
* @return
*/
public String getJCEId() {
return JAVA_ALGORITHMS_FOR_KEY.get(this);
}
}