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

Commit 1e7ebf2

Browse files
authored
Pkcs7 (#109)
* Standard pkcs7 signature implementation * Add method to use StandardSignature
1 parent 1f823d5 commit 1e7ebf2

File tree

5 files changed

+292
-0
lines changed

5 files changed

+292
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
package com.genexus.cryptography.asymmetric;
2+
3+
import com.genexus.cryptography.asymmetric.utils.AsymmetricSigningAlgorithm;
4+
import com.genexus.cryptography.asymmetric.utils.SignatureStandard;
5+
import com.genexus.cryptography.asymmetric.utils.SignatureStandardOptions;
6+
import com.genexus.cryptography.commons.StandardSignerObject;
7+
import com.genexus.securityapicommons.config.EncodingUtil;
8+
import com.genexus.securityapicommons.keys.CertificateX509;
9+
import com.genexus.securityapicommons.keys.PrivateKeyManager;
10+
import com.genexus.securityapicommons.utils.SecurityUtils;
11+
import org.bouncycastle.cert.X509CertificateHolder;
12+
import org.bouncycastle.cert.jcajce.JcaCertStore;
13+
import org.bouncycastle.cms.*;
14+
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
15+
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder;
16+
import org.bouncycastle.operator.ContentSigner;
17+
import org.bouncycastle.operator.DigestCalculatorProvider;
18+
import org.bouncycastle.operator.OperatorCreationException;
19+
import org.bouncycastle.operator.bc.BcContentSignerBuilder;
20+
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
21+
import org.bouncycastle.util.Store;
22+
import org.bouncycastle.util.encoders.Base64;
23+
24+
import java.io.IOException;
25+
import java.security.GeneralSecurityException;
26+
import java.security.cert.CertificateEncodingException;
27+
import java.security.cert.CertificateException;
28+
import java.security.cert.X509Certificate;
29+
import java.util.ArrayList;
30+
import java.util.Collection;
31+
import java.util.Iterator;
32+
import java.util.List;
33+
34+
public class StandardSigner extends StandardSignerObject {
35+
36+
public StandardSigner() {
37+
super();
38+
}
39+
40+
/******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/
41+
42+
public String sign(String plainText, SignatureStandardOptions options)
43+
{
44+
this.error.cleanError();
45+
46+
/******* INPUT VERIFICATION - BEGIN *******/
47+
SecurityUtils.validateObjectInput("signatureStandardOptions", options, this.error);
48+
SecurityUtils.validateObjectInput("private key", options.getPrivateKey(), this.error);
49+
SecurityUtils.validateObjectInput("certificate", options.getCertificate(), this.error);
50+
SecurityUtils.validateStringInput("plainText", plainText, this.error);
51+
if (this.hasError()) {
52+
return "";
53+
}
54+
55+
/******* INPUT VERIFICATION - END *******/
56+
57+
EncodingUtil eu = new EncodingUtil();
58+
byte[] inputText = eu.getBytes(plainText);
59+
if (eu.hasError()) {
60+
this.error = eu.getError();
61+
return "";
62+
}
63+
64+
String result = "";
65+
try {
66+
result = sign_internal(inputText, options.getPrivateKey(), options.getCertificate(), options.getSignatureStandard(), options.getEncapsulated());
67+
} catch (Exception e) {
68+
error.setError("SS002", e.getMessage());
69+
result = "";
70+
}
71+
72+
return result;
73+
}
74+
75+
public boolean verify(String signed, String plainText, SignatureStandardOptions options)
76+
{
77+
this.error.cleanError();
78+
79+
/******* INPUT VERIFICATION - BEGIN *******/
80+
SecurityUtils.validateObjectInput("signatureStandardOptions", options, this.error);
81+
//SecurityUtils.validateStringInput("plainText", plainText, this.error);
82+
SecurityUtils.validateStringInput("signed", signed, this.error);
83+
if (this.hasError()) {
84+
return false;
85+
}
86+
87+
/******* INPUT VERIFICATION - END *******/
88+
89+
EncodingUtil eu = new EncodingUtil();
90+
byte[] plainText_bytes = eu.getBytes(plainText);
91+
if (eu.hasError()) {
92+
this.error = eu.getError();
93+
return false;
94+
}
95+
96+
boolean result = false;
97+
try {
98+
result = verify_internal(Base64.decode(signed), plainText_bytes, options.getEncapsulated());
99+
} catch (Exception e) {
100+
error.setError("SS002", e.getMessage());
101+
result = false;
102+
}
103+
104+
return result;
105+
}
106+
107+
/******** EXTERNAL OBJECT PUBLIC METHODS - END ********/
108+
109+
private String sign_internal(byte[] input, PrivateKeyManager key, CertificateX509 cert, SignatureStandard signatureStandard, boolean encapsulated) throws OperatorCreationException, CertificateEncodingException, CMSException, IOException {
110+
PrivateKeyManager keyMan = (PrivateKeyManager) key;
111+
if (keyMan.hasError()) {
112+
this.error = keyMan.getError();
113+
return "";
114+
}
115+
CertificateX509 certificate = (CertificateX509) cert;
116+
if (certificate.hasError()) {
117+
this.error = certificate.getError();
118+
return "";
119+
}
120+
AsymmetricSigningAlgorithm asymmetricSigningAlgorithm = AsymmetricSigningAlgorithm
121+
.getAsymmetricSigningAlgorithm(keyMan.getAlgorithm(), this.error);
122+
BcContentSignerBuilder bcContentSignerBuilder = AsymmetricSigningAlgorithm.getBcContentSignerBuilder(asymmetricSigningAlgorithm, certificate, this.error);
123+
if (this.hasError())
124+
return "";
125+
126+
List<X509Certificate> certList = new ArrayList<X509Certificate>();
127+
certList.add(cert.Cert());
128+
Store certs = new JcaCertStore(certList);
129+
130+
DigestCalculatorProvider digestCalculatorProvider = new BcDigestCalculatorProvider();
131+
JcaSignerInfoGeneratorBuilder signerInfoGeneratorBuilder = new JcaSignerInfoGeneratorBuilder(digestCalculatorProvider);
132+
ContentSigner signer = bcContentSignerBuilder.build(keyMan.getAsymmetricKeyParameter());
133+
134+
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
135+
136+
gen.addSignerInfoGenerator(signerInfoGeneratorBuilder.build(signer, cert.Cert()));
137+
138+
gen.addCertificates(certs);
139+
140+
CMSTypedData msg = new CMSProcessableByteArray(input);
141+
byte[] encoded = gen.generate(msg,encapsulated).getEncoded();
142+
return Base64.toBase64String(encoded);
143+
}
144+
145+
private boolean verify_internal(byte[] cmsSignedData, byte[] data, boolean encapsulated)
146+
throws GeneralSecurityException, OperatorCreationException, CMSException, CertificateException {
147+
148+
CMSSignedData signedData = encapsulated ? new CMSSignedData(cmsSignedData): new CMSSignedData(new CMSProcessableByteArray(data), cmsSignedData);
149+
150+
Store certStore = signedData.getCertificates();
151+
SignerInformationStore signers = signedData.getSignerInfos();
152+
153+
Collection c = signers.getSigners();
154+
Iterator it = c.iterator();
155+
156+
while (it.hasNext())
157+
{
158+
159+
SignerInformation signer = (SignerInformation)it.next();
160+
Collection certCollection = certStore.getMatches(signer.getSID());
161+
162+
Iterator certIt = certCollection.iterator();
163+
X509CertificateHolder cert1 = (X509CertificateHolder)certIt.next();
164+
165+
SignerInformationVerifier signerInformationVerifier = new JcaSimpleSignerInfoVerifierBuilder()
166+
.build(cert1);
167+
boolean verifies = signer.verify(signerInformationVerifier);
168+
if(!verifies)
169+
{
170+
return false;
171+
}
172+
}
173+
return true;
174+
}
175+
176+
}

GeneXusCryptography/src/main/java/com/genexus/cryptography/asymmetric/utils/AsymmetricSigningAlgorithm.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package com.genexus.cryptography.asymmetric.utils;
22

3+
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
34
import org.bouncycastle.crypto.Digest;
45
import org.bouncycastle.crypto.Signer;
56
import org.bouncycastle.crypto.signers.DSADigestSigner;
67
import org.bouncycastle.crypto.signers.ECDSASigner;
78
import org.bouncycastle.crypto.signers.RSADigestSigner;
89

910
import com.genexus.securityapicommons.commons.Error;
11+
import com.genexus.securityapicommons.keys.CertificateX509;
12+
import org.bouncycastle.operator.DefaultDigestAlgorithmIdentifierFinder;
13+
import org.bouncycastle.operator.DefaultSignatureAlgorithmIdentifierFinder;
14+
import org.bouncycastle.operator.bc.BcContentSignerBuilder;
15+
import org.bouncycastle.operator.bc.BcECContentSignerBuilder;
16+
import org.bouncycastle.operator.bc.BcRSAContentSignerBuilder;
1017

1118
/**
1219
* @author sgrampone
@@ -79,4 +86,24 @@ public static Signer getSigner(AsymmetricSigningAlgorithm asymmetricSigningAlgor
7986
}
8087
return sig;
8188
}
89+
90+
public static BcContentSignerBuilder getBcContentSignerBuilder(AsymmetricSigningAlgorithm asymmetricSigningAlgorithm, CertificateX509 cert, Error error)
91+
{
92+
AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder().find(
93+
cert.Cert().getSigAlgName());
94+
AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find(signatureAlgorithm);
95+
96+
BcContentSignerBuilder sig = null;
97+
switch (asymmetricSigningAlgorithm) {
98+
case RSA:
99+
sig = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm);
100+
break;
101+
case ECDSA:
102+
sig = new BcECContentSignerBuilder(signatureAlgorithm, digestAlgorithm);
103+
break;
104+
default:
105+
error.setError("AE007", "Unrecognized AsymmetricSigningAlgorithm");
106+
}
107+
return sig;
108+
}
82109
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.genexus.cryptography.asymmetric.utils;
2+
3+
import com.genexus.securityapicommons.commons.Error;
4+
public enum SignatureStandard {
5+
CMS,;
6+
public static SignatureStandard getSignatureStandard(String signatureStandard,
7+
Error error) {
8+
switch (signatureStandard.toUpperCase().trim()) {
9+
case "CMS":
10+
return SignatureStandard.CMS;
11+
default:
12+
error.setError("SS001", "Unrecognized SignatureStandard");
13+
return null;
14+
}
15+
}
16+
public static String valueOf(SignatureStandard signatureStandard, Error error) {
17+
switch (signatureStandard) {
18+
case CMS:
19+
return "CMS";
20+
default:
21+
error.setError("SS002", "Unrecognized SignatureStandard");
22+
return "";
23+
}
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.genexus.cryptography.asymmetric.utils;
2+
3+
import com.genexus.securityapicommons.commons.SecurityAPIObject;
4+
import com.genexus.securityapicommons.keys.CertificateX509;
5+
import com.genexus.securityapicommons.keys.PrivateKeyManager;
6+
public class SignatureStandardOptions extends SecurityAPIObject{
7+
8+
private CertificateX509 certificate;
9+
private PrivateKeyManager privateKey;
10+
11+
private SignatureStandard signatureStandard;
12+
13+
private boolean encapsulated;
14+
15+
16+
public SignatureStandardOptions()
17+
{
18+
this.signatureStandard = SignatureStandard.CMS;
19+
this.encapsulated = false;
20+
}
21+
/******** EXTERNAL OBJECT PUBLIC METHODS - BEGIN ********/
22+
public void setPrivateKey(PrivateKeyManager key) {
23+
this.privateKey = key;
24+
}
25+
26+
public void setCertificate(CertificateX509 cert) {
27+
this.certificate = cert;
28+
}
29+
30+
public boolean setSignatureStandard(String standard)
31+
{
32+
this.signatureStandard = SignatureStandard.getSignatureStandard(standard, this.error);
33+
return this.hasError() ? false: true;
34+
}
35+
36+
public void setEncapsulated(boolean value) {this.encapsulated = value; }
37+
38+
/******** EXTERNAL OBJECT PUBLIC METHODS - END ********/
39+
40+
public PrivateKeyManager getPrivateKey() {
41+
return this.privateKey;
42+
}
43+
44+
public CertificateX509 getCertificate() { return this.certificate;}
45+
46+
public SignatureStandard getSignatureStandard() { return this.signatureStandard;}
47+
48+
public boolean getEncapsulated() { return this.encapsulated; }
49+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.genexus.cryptography.commons;
2+
3+
import com.genexus.cryptography.asymmetric.utils.SignatureStandardOptions;
4+
import com.genexus.securityapicommons.commons.SecurityAPIObject;
5+
6+
public abstract class StandardSignerObject extends SecurityAPIObject {
7+
8+
public StandardSignerObject()
9+
{
10+
super();
11+
}
12+
13+
public abstract String sign(String plainText, SignatureStandardOptions options);
14+
public abstract boolean verify(String signed, String plainText, SignatureStandardOptions options);
15+
}

0 commit comments

Comments
 (0)