package ee.sk.hwcrypto.demo.signature;
import ee.sk.hwcrypto.demo.model.FileWrapper;
import ee.sk.hwcrypto.demo.model.SigningSessionData;
import eu.europa.ec.markt.dss.DSSXMLUtils;
import eu.europa.ec.markt.dss.signature.DSSDocument;
import eu.europa.ec.markt.dss.signature.InMemoryDocument;
import eu.europa.ec.markt.dss.signature.MimeType;
import eu.europa.ec.markt.dss.ws.signature.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.xml.bind.DatatypeConverter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Date;
@Service
public class FileSigner {
private static final Logger log = LoggerFactory.getLogger(FileSigner.class);
private static final ObjectFactory FACTORY = new ObjectFactory();
private static final String DIGEST_ALGORITHM = "SHA-256";
private static final DigestAlgorithm DIGEST_TYPE = DigestAlgorithm.SHA256;
@Autowired
SignatureServiceConnector signatureServiceConnector;
@Autowired
SigningSessionData sessionData;
public String getDataToSign(FileWrapper fileToSign, String certificateInHex) {
WsDocument containerToSign = createContainerToSign(fileToSign);
WsParameters signatureParameters = createSignatureParameters(certificateInHex);
byte[] dataToSign = signatureServiceConnector.getDataToSign(containerToSign, signatureParameters);
byte[] hashToSign = calculateHash(dataToSign, DIGEST_ALGORITHM);
String dataToSignInHex = DatatypeConverter.printHexBinary(hashToSign);
sessionData.setSignatureContainer(containerToSign);
sessionData.setSignatureParameters(signatureParameters);
return dataToSignInHex;
}
public FileWrapper signDocument(String signatureInHex) {
WsDocument containerToSign = sessionData.getSignatureContainer();
WsParameters signatureParameters = sessionData.getSignatureParameters();
byte[] signatureBytes = DatatypeConverter.parseHexBinary(signatureInHex);
WsDocument signedDocument = signatureServiceConnector.signDocument(containerToSign, signatureParameters, signatureBytes);
return FileWrapper.create(signedDocument);
}
private WsDocument createContainerToSign(FileWrapper fileToSign) {
DSSDocument documentToSign = new InMemoryDocument(fileToSign.getBytes(), fileToSign.getFileName());
WsDocument container = new WsDocument();
container.setBytes(documentToSign.getBytes());
container.setName(documentToSign.getName());
container.setAbsolutePath(documentToSign.getAbsolutePath());
MimeType mimeType = documentToSign.getMimeType();
eu.europa.ec.markt.dss.ws.signature.MimeType wsMimeType = FACTORY.createMimeType();
String mimeTypeString = mimeType.getMimeTypeString();
wsMimeType.setMimeTypeString(mimeTypeString);
container.setMimeType(wsMimeType);
return container;
}
private WsParameters createSignatureParameters(String certificateInHex) {
WsParameters parameters = new WsParameters();
parameters.setSignatureLevel(SignatureLevel.ASiC_E_BASELINE_B);
parameters.setSignaturePackaging(SignaturePackaging.DETACHED);
parameters.setEncryptionAlgorithm(EncryptionAlgorithm.RSA);
parameters.setAsicMimeType(MimeType.ASICE.getMimeTypeString());
parameters.setDigestAlgorithm(DIGEST_TYPE);
parameters.setSigningDate(DSSXMLUtils.createXMLGregorianCalendar(new Date()));
byte[] certificateBytes = DatatypeConverter.parseHexBinary(certificateInHex);
parameters.setSigningCertificateBytes(certificateBytes);
parameters.setDeterministicId("S0");
return parameters;
}
private byte[] calculateHash(byte[] data, String digestType) {
try {
MessageDigest sha = MessageDigest.getInstance(digestType, "BC");
sha.update(data);
return sha.digest();
} catch (NoSuchAlgorithmException | NoSuchProviderException e) {
log.error("Error calculating hash with " + digestType, e);
throw new HashCalculationException(e);
}
}
public static class HashCalculationException extends RuntimeException {
public HashCalculationException(Throwable cause) {
super(cause);
}
}
}