We have client applications (Applets and Silverlight) that create a PKCS1 v2.1 digital signature. The digital signature is created as PKCS1 since the original content is not downloaded to the client, only the contents' hash is sent to the client to conserve bandwidth.
We are attempting to create a PKCS7/CMS container server side, based on the information from this post:
- Reading certificate and loading as X509Certificate type
- Reading PKCS1 signature as base64 and loading as byte array
- Instantiating new ASN1ObjectIdentifier and setting PKCS1 OID (1.2.840.113549.1.1)
- Creating new CMSTypedData CMSProcessableByteArray, using asn1 object and signare byte[] as parameters
- Create new CMSSignedGenerator and add certificates
- Create new CMSSignedData as detached signature using CMSTypedData type
However, when getting to steps 5 and 6 things break, as the BC CMSSignedGenerator and CMSSignedData classes do not support adding signers without the private key:
CMS creation:
// Add BC to environment
Security.addProvider(new BouncyCastleProvider());
// Read certificate and convert to X509Certificate
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
Path certPath = Paths.get("C:\\MyCertificate.cer");
byte[] certData = Files.readAllBytes(certPath);
InputStream in = new ByteArrayInputStream(certData);
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);
// Add signer certificates to List and add them to store
List<X509Certificate> certList = new ArrayList<X509Certificate>();
certList.add(cert);
Store certs = new JcaCertStore(certList);
// Get signature in Base64, decode and convert to byte array
// Signature signature = Signature.getInstance("SHA1WithRSA", "BC");
String signatureBase64 = "gjTbsD0vSOi6nMlRVbpTLRQ5j+g2h8iEH1DgQx93PDBuwzWT47urKxMAS+75dAhQrkreLt9TGZaDN85e5xEpIF12mK1G+AgCNc370I1bjxOvUU67IVxHkZ+IX8kzSiD2uNuQtk3IrwUqyL30TIo+LDAXmY1AQVZwXAaOYG4bXxI=";
BASE64Decoder decoder = new BASE64Decoder();
byte[] signatureByte = decoder.decodeBuffer(signatureBase64);
// Instantiate new ANS1ObjectIdentifier to identify PKCS1 signature
ASN1ObjectIdentifier asn1OidPkcs1 = new ASN1ObjectIdentifier("1.2.840.113549.1.1");
// Table generator
/*AttributeTable attrT = new AttributeTable();
SimpleAttributeTableGenerator sAttrTGen = new SimpleAttributeTableGenerator();*/
// Instantiate new CMSProcessable object
CMSTypedData msg = new CMSProcessableByteArray(asn1OidPkcs1, signatureByte);
// Instantiate new CMSSignedDataGenerator object
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
// ContentSigner sha1Signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").s
gen.addCertificates(certs);
CMSSignedData sigData = gen.generate(msg, false);
// BASE64Encoder encoder = new BASE64Encoder();
new File("C:\\MyCMS.p7s");
FileOutputStream fileOuputStream = new FileOutputStream("C:\\Users\\gregwerner\\Documents\\Archivos\\miFirma.p7s");
fileOuputStream.write(sigData.getEncoded());
fileOuputStream.flush();
fileOuputStream.close();
}
Any ideas on how to complete CMS container? Perhaps using AttributeTable to add muliple OID's for time stamps, etc., but that doesn't seem to work either.