I am trying to send a Certificate Signing Request from an Android device to a server. The server is working properly with iOS devices and follows a SCEP procedure with OpenSSL.
So here is my problem : I can send the signed enveloped CSR but the server can't read the enveloped CSR. I have the following error from the server :
pki.rb:26:in initialize: Could not parse the PKCS7: header too long (ArgumentError)
Related ruby server code :
#receive object and put it in object data
[...]
# Verify Input Data
p7sign = OpenSSL::PKCS7.new(data)
store = OpenSSL::X509::Store.new
p7sign.verify(nil, store, nil, OpenSSL::PKCS7::NOVERIFY)
signers = p7sign.signers
# Encrypted data (LINE 26 :)
p7enc = OpenSSL::PKCS7.new(p7sign.data)
# Certificate Signing Request
csr = p7enc.decrypt(ssl.key, ssl.certificate)
# Signed Certificate
request = OpenSSL::X509::Request.new(csr)
Java Code (Android) :
I am using Bouncy Castle to generate the CSR and Volley (Google) to send it.
Main :
//Generate PEM formated CSR
byte[] pemCsr = getPemFromCsr(generateCSR());
//Envelop it in a PKCS#7 object
byte[] envelopedData = getDerFromCMSEnvelopedData(envelopData(pemCsr));
//Sign it in a PKCS#7 object
byte[] signedData = getDerFromCMSSignedData(signData(envelopedData));
sendCsrRequest(signedData);
CSR :
//Generate the CSR
private static PKCS10CertificationRequest genrateCertificationRequest(){
// Build the CN for the cert we
X500NameBuilder nameBld = new X500NameBuilder(BCStyle.INSTANCE);
nameBld.addRDN(BCStyle.CN, "cn");
nameBld.addRDN(BCStyle.O, "o");
nameBld.addRDN(BCStyle.NAME, "name");
X500Name principal = nameBld.build();
// Generate the certificate signing request (csr = PKCS10)
String sigAlg = "SHA1withRSA";
JcaContentSignerBuilder csb = new JcaContentSignerBuilder(sigAlg);
ContentSigner cs = csb.build(privateKey);
DERPrintableString password = new DERPrintableString("mychallenge");
PKCS10CertificationRequestBuilder crb = new JcaPKCS10CertificationRequestBuilder(principal, publicKey);
crb.addAttribute((ASN1ObjectIdentifier) PKCSObjectIdentifiers.pkcs_9_at_challengePassword, password);
PKCS10CertificationRequest csr = crb.build(cs);
return csr;
}
//Envelop the CSR
private static CMSEnvelopedData envelopData(byte[] pemCsr) {
CMSTypedData msg = new CMSProcessableByteArray(pemCsr);
CMSEnvelopedDataGenerator edGen = new CMSEnvelopedDataGenerator();
edGen.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator(x509Certificate).setProvider("BC"));
CMSEnvelopedData ed = edGen.generate(msg,new JceCMSContentEncryptorBuilder(CMSAlgorithm.DES_EDE3_CBC).setProvider("BC").build());
return ed;
}
//Sign the enveloped CSR
private static CMSSignedData signData(byte[] data){
ContentSigner signer = new JcaContentSignerBuilder("SHA1withRSA").setProvider("BC").build(privateKey);
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(signer, (X509Certificate) x509Certificate));
CMSTypedData cmsdata = new CMSProcessableByteArray(data);
CMSSignedData signedData = generator.generate(cmsdata, true);
return signedData;
}
I have other code ready to paste (the Volley request, the utils converter) but maybe it is enough for the moment.
SCEP is already working with iOS devices, so the server is clean. Ruby can create the signed PKCS#7 so I guess that my signing step is OK. But if I send an empty signed PKCS#7, I surprisingly have the same error.
Thanks in advance for any help.
It seems that the ASN1 of the envelop isn't correct for OpenSSL.
In parallel, Google Volley automatically adds "\n" in the response which also raises problems.
来源:https://stackoverflow.com/questions/24019594/generate-a-csr-request-in-java-via-scep