Skip to content
This repository was archived by the owner on Apr 10, 2025. It is now read-only.
Merged

Pkcs7 #109

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package com.genexus.cryptography.asymmetric;

import com.genexus.cryptography.asymmetric.utils.AsymmetricSigningAlgorithm;
import com.genexus.cryptography.asymmetric.utils.SignatureStandard;
import com.genexus.cryptography.asymmetric.utils.SignatureStandardOptions;
import com.genexus.cryptography.commons.StandardSignerObject;
import com.genexus.securityapicommons.config.EncodingUtil;
import com.genexus.securityapicommons.keys.CertificateX509;
import com.genexus.securityapicommons.keys.PrivateKeyManager;
import com.genexus.securityapicommons.utils.SecurityUtils;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.*;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.DigestCalculatorProvider;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.bc.BcContentSignerBuilder;
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
import org.bouncycastle.util.Store;
import org.bouncycastle.util.encoders.Base64;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

public class StandardSigner extends StandardSignerObject {

public StandardSigner() {
super();
}

/******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/

public String sign(String plainText, SignatureStandardOptions options)
{
this.error.cleanError();

/******* INPUT VERIFICATION - BEGIN *******/
SecurityUtils.validateObjectInput("signatureStandardOptions", options, this.error);
SecurityUtils.validateObjectInput("private key", options.getPrivateKey(), this.error);
SecurityUtils.validateObjectInput("certificate", options.getCertificate(), this.error);
SecurityUtils.validateStringInput("plainText", plainText, this.error);
if (this.hasError()) {
return "";
}

/******* INPUT VERIFICATION - END *******/

EncodingUtil eu = new EncodingUtil();
byte[] inputText = eu.getBytes(plainText);
if (eu.hasError()) {
this.error = eu.getError();
return "";
}

String result = "";
try {
result = sign_internal(inputText, options.getPrivateKey(), options.getCertificate(), options.getSignatureStandard(), options.getEncapsulated());
} catch (Exception e) {
error.setError("SS002", e.getMessage());
result = "";
}

return result;
}

public boolean verify(String signed, String plainText, SignatureStandardOptions options)
{
this.error.cleanError();

/******* INPUT VERIFICATION - BEGIN *******/
SecurityUtils.validateObjectInput("signatureStandardOptions", options, this.error);
//SecurityUtils.validateStringInput("plainText", plainText, this.error);
SecurityUtils.validateStringInput("signed", signed, this.error);
if (this.hasError()) {
return false;
}

/******* INPUT VERIFICATION - END *******/

EncodingUtil eu = new EncodingUtil();
byte[] plainText_bytes = eu.getBytes(plainText);
if (eu.hasError()) {
this.error = eu.getError();
return false;
}

boolean result = false;
try {
result = verify_internal(Base64.decode(signed), plainText_bytes, options.getEncapsulated());
} catch (Exception e) {
error.setError("SS002", e.getMessage());
result = false;
}

return result;
}

/******** EXTERNAL OBJECT PUBLIC METHODS - END ********/

private String sign_internal(byte[] input, PrivateKeyManager key, CertificateX509 cert, SignatureStandard signatureStandard, boolean encapsulated) throws OperatorCreationException, CertificateEncodingException, CMSException, IOException {
PrivateKeyManager keyMan = (PrivateKeyManager) key;
if (keyMan.hasError()) {
this.error = keyMan.getError();
return "";
}
CertificateX509 certificate = (CertificateX509) cert;
if (certificate.hasError()) {
this.error = certificate.getError();
return "";
}
AsymmetricSigningAlgorithm asymmetricSigningAlgorithm = AsymmetricSigningAlgorithm
.getAsymmetricSigningAlgorithm(keyMan.getAlgorithm(), this.error);
BcContentSignerBuilder bcContentSignerBuilder = AsymmetricSigningAlgorithm.getBcContentSignerBuilder(asymmetricSigningAlgorithm, certificate, this.error);
if (this.hasError())
return "";

List<X509Certificate> certList = new ArrayList<X509Certificate>();
certList.add(cert.Cert());
Store certs = new JcaCertStore(certList);

DigestCalculatorProvider digestCalculatorProvider = new BcDigestCalculatorProvider();
JcaSignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(digestCalculatorProvider);
ContentSigner signer = bcContentSignerBuilder.build(keyMan.getAsymmetricKeyParameter());

CMSSignedDataGenerator gen = new CMSSignedDataGenerator();

gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(signer, cert.Cert()));

gen.addCertificates(certs);

CMSTypedData msg = new CMSProcessableByteArray(input);
byte[] encoded = gen.generate(msg,encapsulated).getEncoded();
return Base64.toBase64String(encoded);
}

private boolean verify_internal(byte[] cmsSignedData, byte[] data, boolean encapsulated)
throws GeneralSecurityException, OperatorCreationException, CMSException, CertificateException {

CMSSignedData signedData = encapsulated ? new CMSSignedData(cmsSignedData): new CMSSignedData(new CMSProcessableByteArray(data), cmsSignedData);

Store certStore = signedData.getCertificates();
SignerInformationStore signers = signedData.getSignerInfos();

Collection c = signers.getSigners();
Iterator it = c.iterator();

while (it.hasNext())
{

SignerInformation signer = (SignerInformation)it.next();
Collection certCollection = certStore.getMatches(signer.getSID());

Iterator certIt = certCollection.iterator();
X509CertificateHolder cert1 = (X509CertificateHolder)certIt.next();

SignerInformationVerifier signerInformationVerifier = new JcaSimpleSignerInfoVerifierBuilder()
.build(cert1);
boolean verifies = signer.verify(signerInformationVerifier);
if(!verifies)
{
return false;
}
}
return true;
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package com.genexus.cryptography.asymmetric.utils;

import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.Signer;
import org.bouncycastle.crypto.signers.DSADigestSigner;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.RSADigestSigner;

import com.genexus.securityapicommons.commons.Error;
import com.genexus.securityapicommons.keys.CertificateX509;
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
import org.bouncycastle.operator.bc.BcContentSignerBuilder;
import org.bouncycastle.operator.bc.BcECContentSignerBuilder;
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;

/**
* @author sgrampone
Expand Down Expand Up @@ -79,4 +86,24 @@ public static Signer getSigner(AsymmetricSigningAlgorithm asymmetricSigningAlgor
}
return sig;
}

public static BcContentSignerBuilder getBcContentSignerBuilder(AsymmetricSigningAlgorithm asymmetricSigningAlgorithm, CertificateX509 cert, Error error)
{
AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder().find(
cert.Cert().getSigAlgName());
AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find(signatureAlgorithm);

BcContentSignerBuilder sig = null;
switch (asymmetricSigningAlgorithm) {
case RSA:
sig = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm);
break;
case ECDSA:
sig = new BcECContentSignerBuilder(signatureAlgorithm, digestAlgorithm);
break;
default:
error.setError("AE007", "Unrecognized AsymmetricSigningAlgorithm");
}
return sig;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.genexus.cryptography.asymmetric.utils;

import com.genexus.securityapicommons.commons.Error;
public enum SignatureStandard {
CMS,;
public static SignatureStandard getSignatureStandard(String signatureStandard,
Error error) {
switch (signatureStandard.toUpperCase().trim()) {
case "CMS":
return SignatureStandard.CMS;
default:
error.setError("SS001", "Unrecognized SignatureStandard");
return null;
}
}
public static String valueOf(SignatureStandard signatureStandard, Error error) {
switch (signatureStandard) {
case CMS:
return "CMS";
default:
error.setError("SS002", "Unrecognized SignatureStandard");
return "";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.genexus.cryptography.asymmetric.utils;

import com.genexus.securityapicommons.commons.SecurityAPIObject;
import com.genexus.securityapicommons.keys.CertificateX509;
import com.genexus.securityapicommons.keys.PrivateKeyManager;
public class SignatureStandardOptions extends SecurityAPIObject{

private CertificateX509 certificate;
private PrivateKeyManager privateKey;

private SignatureStandard signatureStandard;

private boolean encapsulated;


public SignatureStandardOptions()
{
this.signatureStandard = SignatureStandard.CMS;
this.encapsulated = false;
}
/******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/
public void setPrivateKey(PrivateKeyManager key) {
this.privateKey = key;
}

public void setCertificate(CertificateX509 cert) {
this.certificate = cert;
}

public boolean setSignatureStandard(String standard)
{
this.signatureStandard = SignatureStandard.getSignatureStandard(standard, this.error);
return this.hasError() ? false: true;
}

public void setEncapsulated(boolean value) {this.encapsulated = value; }

/******** EXTERNAL OBJECT PUBLIC METHODS - END ********/

public PrivateKeyManager getPrivateKey() {
return this.privateKey;
}

public CertificateX509 getCertificate() { return this.certificate;}

public SignatureStandard getSignatureStandard() { return this.signatureStandard;}

public boolean getEncapsulated() { return this.encapsulated; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.genexus.cryptography.commons;

import com.genexus.cryptography.asymmetric.utils.SignatureStandardOptions;
import com.genexus.securityapicommons.commons.SecurityAPIObject;

public abstract class StandardSignerObject extends SecurityAPIObject {

public StandardSignerObject()
{
super();
}

public abstract String sign(String plainText, SignatureStandardOptions options);
public abstract boolean verify(String signed, String plainText, SignatureStandardOptions options);
}