org.digidoc4j.signers.PKCS12SignatureToken Maven / Gradle / Ivy
/* DigiDoc4J library
*
* This software is released under either the GNU Library General Public
* License (see LICENSE.LGPL).
*
* Note that the only valid version of the LGPL license as far as this
* project is concerned is the original GNU Library General Public License
* Version 2.1, February 1999
*/
package org.digidoc4j.signers;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.List;
import javax.crypto.Cipher;
import org.bouncycastle.asn1.ASN1Encoding;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DigestInfo;
import org.digidoc4j.DigestAlgorithm;
import org.digidoc4j.SignatureToken;
import org.digidoc4j.X509Cert;
import org.digidoc4j.exceptions.DigiDoc4JException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.europa.esig.dss.EncryptionAlgorithm;
import eu.europa.esig.dss.SignatureAlgorithm;
import eu.europa.esig.dss.SignatureValue;
import eu.europa.esig.dss.ToBeSigned;
import eu.europa.esig.dss.token.DSSPrivateKeyEntry;
import eu.europa.esig.dss.token.KSPrivateKeyEntry;
import eu.europa.esig.dss.token.KeyStoreSignatureTokenConnection;
import eu.europa.esig.dss.token.Pkcs12SignatureToken;
/**
* Implements PKCS12 signer.
*/
public class PKCS12SignatureToken implements SignatureToken {
private static final Logger logger = LoggerFactory.getLogger(PKCS12SignatureToken.class);
protected KeyStoreSignatureTokenConnection signatureTokenConnection = null;
protected KSPrivateKeyEntry keyEntry = null;
/**
* Constructs PKCS12 signer object. If more than one key is provided then first NON_REPUDIATION key is used.
*
* @param fileName .p12 file name and path
* @param password keystore password as char array
*/
public PKCS12SignatureToken(String fileName, char[] password) {
init(fileName, String.valueOf(password), X509Cert.KeyUsage.NON_REPUDIATION, null);
}
/**
* Constructs PKCS12 signer object. If more than one key is provided then first NON_REPUDIATION key is used.
*
* @param fileName .p12 file name and path
* @param password keystore password as String
*/
public PKCS12SignatureToken(String fileName, String password) {
init(fileName, password, X509Cert.KeyUsage.NON_REPUDIATION, null);
}
/**
* Constructs PKCS12 signer object. Key is searched by given alias.
*
* @param fileName .p12 file name and path
* @param password keystore password as String
* @param alias known key alias
*/
public PKCS12SignatureToken(String fileName, String password, String alias) {
init(fileName, password, X509Cert.KeyUsage.NON_REPUDIATION, alias);
}
/**
* Constructs PKCS12 signer object. First key matching given keyUsage is used.
*
* @param fileName .p12 file name and path
* @param password keystore password as String
* @param keyUsage key usage value, default KeyUsageBit.nonRepudiation
*/
public PKCS12SignatureToken(String fileName, String password, X509Cert.KeyUsage keyUsage) {
init(fileName, password, keyUsage, null);
}
private void init(String fileName, String password, X509Cert.KeyUsage keyUsage, String alias) {
logger.info("Using PKCS#12 signature token from file: " + fileName);
try {
signatureTokenConnection = new Pkcs12SignatureToken(fileName, password);
} catch (IOException e) {
throw new DigiDoc4JException(e.getMessage());
}
if (alias != null) {
logger.debug("Searching key with alias: " + alias);
keyEntry = signatureTokenConnection.getKey(alias, password);
} else {
logger.debug("Searching key by usage: " + keyUsage.name());
List keys = signatureTokenConnection.getKeys();
X509CertSelector selector = new X509CertSelector();
selector.setKeyUsage(getUsageBitArray(keyUsage)); // TODO: Test this!
for (DSSPrivateKeyEntry key : keys) {
if (selector.match(key.getCertificate().getCertificate())) {
keyEntry = (KSPrivateKeyEntry) key;
break;
}
}
}
if (keyEntry == null && signatureTokenConnection.getKeys().size() > 0)
keyEntry = (KSPrivateKeyEntry)signatureTokenConnection.getKeys().get(0);
}
private boolean[] getUsageBitArray(X509Cert.KeyUsage keyUsage) {
sun.security.x509.KeyUsageExtension usage = new sun.security.x509.KeyUsageExtension();
try {
usage.set(keyUsage.name(), Boolean.TRUE);
} catch (IOException e) {
e.printStackTrace();
}
return usage.getBits();
}
/**
* Method for asking DSS signature token connection
* @return DSS signature token connection
*/
public KeyStoreSignatureTokenConnection getSignatureTokenConnection() {
return signatureTokenConnection;
}
@Override
public X509Certificate getCertificate() {
logger.debug("Using key with alias: ", getAlias());
return keyEntry.getCertificate().getCertificate();
}
@Override
public byte[] sign(org.digidoc4j.DigestAlgorithm digestAlgorithm, byte[] dataToSign) {
logger.info("Signing with PKCS#12 signature token, using digest algorithm: " + digestAlgorithm.name());
ToBeSigned toBeSigned = new ToBeSigned(dataToSign);
eu.europa.esig.dss.DigestAlgorithm dssDigestAlgorithm =
eu.europa.esig.dss.DigestAlgorithm.forXML(digestAlgorithm.toString());
SignatureValue signature = signatureTokenConnection.sign(toBeSigned, dssDigestAlgorithm, keyEntry);
return signature.getValue();
}
public byte[] sign2(DigestAlgorithm digestAlgorithm, byte[] dataToSign) throws Exception {
MessageDigest sha = MessageDigest.getInstance(digestAlgorithm.name(), "BC");
byte[] digest = sha.digest(dataToSign);
DERObjectIdentifier shaoid = new DERObjectIdentifier(digestAlgorithm.getDssDigestAlgorithm().getOid());
AlgorithmIdentifier shaaid = new AlgorithmIdentifier(shaoid, null);
DigestInfo di = new DigestInfo(shaaid, digest);
byte[] plainSig = di.getEncoded(ASN1Encoding.DER);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
cipher.init(Cipher.ENCRYPT_MODE, keyEntry.getPrivateKey());
byte[] signature = cipher.doFinal(plainSig);
return signature;
}
public byte[] sign3(DigestAlgorithm digestAlgorithm, byte[] dataToSign) {
byte[] result = new byte[512];
try {
EncryptionAlgorithm encryptionAlgorithm = keyEntry.getEncryptionAlgorithm();
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.getAlgorithm(encryptionAlgorithm, digestAlgorithm.getDssDigestAlgorithm());
String javaSignatureAlgorithm = signatureAlgorithm.getJCEId();
logger.debug(" ... Signing with PKCS#11 and " + javaSignatureAlgorithm);
java.security.Signature signature = java.security.Signature.getInstance(javaSignatureAlgorithm);
signature.initSign(keyEntry.getPrivateKey());
signature.update(dataToSign);
result = signature.sign();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
}
return result;
}
/**
* Returns key entry alias in keyStore.
*/
public String getAlias() {
return keyEntry.getAlias();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy