The TSL signature is an enveloped signature, that can be described by the following picture:
First let's assume that we have some previously initialized variables:
- tslDER - Unsigned TSL object (instance of DEREncodable)
- privateKey - Private key being used to sign
- cert - PKI Certificate of the signer (this one is optional, but recommended)
AlgorithmIdentifier sigAlg = new AlgorithmIdentifier(ObjectIdentifiers.getAlgorithmOID(sigAlgorithm));
ASN1Set sigAlgs = new DERSet(sigAlg);
AlgorithmIdentifier digestAlg = new AlgorithmIdentifier(ObjectIdentifiers.getAlgorithmOID(digestAlgorithm));
ASN1Set digestAlgs = new DERSet(digestAlg);
The getAlgorithmOID is a method that given a String returns the matching Object Identifier or throws an Exception.
After that, let's define the identification of the signer:
SignerIdentifier sid = null;
String[] names = cert.getIssuerDN().getName().split(",");
ASN1EncodableVector vec = new ASN1EncodableVector();
for (String name : names)
{
ASN1EncodableVector nameVec = new ASN1EncodableVector();
String[] vals = name.split("=");
nameVec.add((DEREncodable) X509Name.DefaultLookUp.get(vals[0].trim().toLowerCase()));
nameVec.add(new DERPrintableString(vals[1]));
vec.add(new DERSequence(nameVec));
}
ASN1Set attr = new DERSet(vec);
X509Name issuer = new X509Name(new DERSequence(attr));
sid = new SignerIdentifier(new IssuerAndSerialNumber(issuer, cert.getSerialNumber()));
Now the encapsulated content info:
ContentInfo encapContent = new ContentInfo(ObjectIdentifiers.id_eContentType_signedTSL, tslDER);
The next step is building the byte array to be signed:
MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
md.reset();
md.update(tslDER.getDERObject().getEncoded());
ASN1EncodableVector attrs = new ASN1EncodableVector();
ASN1EncodableVector contentTypeAttr = new ASN1EncodableVector();
contentTypeAttr.add(ObjectIdentifiers.id_contentType);
contentTypeAttr.add(ObjectIdentifiers.id_eContentType_signedTSL);
attrs.add(new DERSequence(contentTypeAttr));
ASN1EncodableVector messageDigestAttr = new ASN1EncodableVector();
messageDigestAttr.add(ObjectIdentifiers.id_messageDigest);
messageDigestAttr.add(new DEROctetString(md.digest()));
attrs.add(new DERSequence(messageDigestAttr));
ASN1Set signedAttr = new DERSet(attrs);
md.reset();
md.update(tslDER.getDERObject().getDEREncoded());
md.update(signedAttr.getDEREncoded());
byte[] data = md.digest();
And to finalize the signature:
Signature sig = Signature.getInstance(sigAlgorithm);
sig.initSign(privateKey);
sig.update(data);
byte[] signed = sig.sign();
SignerInfo signerInfo = new SignerInfo(sid, digestAlg, signedAttr, sigAlg, new DEROctetString(signed), null);
ASN1Set signerInfos = new DERSet(signerInfo);
ASN1Set certs = new DERSet(new DEROctetString(cert.getEncoded()));
SignedData signedData = new SignedData(digestAlgs, encapContent, certs, null, signerInfos);
ContentInfo content = new ContentInfo(CMSObjectIdentifiers.signedData, signedData);
1 comment:
Post a Comment