I use the smart card to generate the private-public key pair on the card, get the public key modulus from the card, generate a CSR for a user, compute the MD5 Hash using SHA1, give this hash to the card for signing the hash with the private key, append this signature to the CSR, and verify this CSR using org.bouncycastle.jce.PKCS10CertificationRequest. Below is my program which has the code for CSR generation and verification. I have hardcoded the public modulus (String modulusStr) and the corresponding signature ( String signedCSR) received from the card for the CSR generated using the public key modulus. The values used are for 256 modulus, and the verification fails. You also see a commented set of values for the same variables, for 128 byte modulus. Verification succeeds for 128 byte modulus. Can someone explain why this is happening? thanks, Kannan import java.io.ByteArrayInputStream; import java.io.IOException; import java.math.BigInteger; import java.security.Key; import java.security.KeyFactory; import java.security.PublicKey; import java.security.Security; import java.security.Signature; import java.security.spec.RSAPublicKeySpec;
import javax.security.auth.x500.X500Principal; import org.bouncycastle.asn1.ASN1EncodableVector; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.DERSet; import org.bouncycastle.asn1.pkcs.CertificationRequestInfo; import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; import org.bouncycastle.asn1.x509.X509Name; import org.bouncycastle.jce.PKCS10CertificationRequest; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Base64; import sun.security.pkcs.PKCS10Attributes; import sun.security.util.DerOutputStream; import sun.security.util.DerValue; import sun.security.x509.X500Name; import sun.security.x509.X500Signer; public class GenerateCSR { private static SubjectPublicKeyInfo getPublicKeyInfo(Key publicKey) throws IOException { ByteArrayInputStream bIn = new ByteArrayInputStream(publicKey.getEncoded()); ASN1InputStream dIn = new ASN1InputStream(bIn); return new SubjectPublicKeyInfo((ASN1Sequence) dIn.readObject()); } /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { //128 byte modulus // String modulusStr = "AB198AC3A10AF5A7B7546F719D5FEB67797BC5A03CD0AFEAF2A8F370719F6E992BB7FBAF6F55E7D44610B6CBC962172A9AFF36859426E9B17A5BDD3A87A7583E153A6F6838ED4BC0BB268F2A5A51388A42B02417C17BBFF2D95C20C8C208A13FA043B46A4762C9927692232B405857570418D98AE7EB442D4697D3A9CA53BE81"; //256 byte modulus String modulusStr = "95E1ABBFFCA1AAB6CEAEF05EC534A87A8FBF3315619FDDF2C83D20FCBA7FBB06C077439D82DC62BB383309684672EC19CEDB594EAA5F2347C1FE3BEF52CAC9CA76018D5BF2D5569796E7493B02B29A7434DBEA18725CBF70C8814FD99528706F936EB9177AF21E6736E4B30A2156AFF39B77B4CCF9696A564D6977CA2DBCA8881CDDE03369EA41F04DC37F79F5AE1D9890F4596053158E35FD4CCE5C00EA55EAE8182D3DE081AF473A8A8EDD211B1BF0206891CE674623177BCEDED39698915B08B77CC475413301DAF97058B620B3E866167C67672697028B864B1B5C11F195143A5241E022CB4797C918B24EFDEFF8D4576A789EBC78A40A1D25FF2EDF6CE1"; byte[] modulus = HexString.hexToBuffer(modulusStr); String sigAlg = "SHA1WithRSA"; String userDN = "cn=ob2,o=arcot"; RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(1,modulus), new BigInteger("65537")); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(publicKeySpec); SubjectPublicKeyInfo ski = getPublicKeyInfo(publicKey); ASN1EncodableVector v = new ASN1EncodableVector(); CertificationRequestInfo reqInfo = new CertificationRequestInfo(new X509Name(userDN), ski, new DERSet(v)); // Build an instance of pkcs10 with the public key from the card. sun.security.pkcs.PKCS10 pkcs10 = new sun.security.pkcs.PKCS10(publicKey); DerOutputStream out, scratch; byte [] certificateRequestInfo; Signature signature = null; // signature is not initialized because CSR is not going to be signed here; if not on the card. signature = Signature.getInstance(sigAlg); // Build the info. X500Principal x500 = new X500Principal(userDN); X500Name x500name = new X500Name(x500.getEncoded()); X500Signer requester = new X500Signer(signature, x500name); X500Name subject = requester.getSigner(); // Encode CSR info, wrap in a sequence for being signed. scratch = new DerOutputStream(); // PKCS #10 v1.0. scratch.putInteger(BigInteger.ZERO); // X.500 name. subject.encode(scratch); // Public key. Key subjectPublicKeyInfo = pkcs10.getSubjectPublicKeyInfo(); scratch.write(subjectPublicKeyInfo.getEncoded()); PKCS10Attributes attributeSet = new PKCS10Attributes(); attributeSet.encode(scratch); out = new DerOutputStream(); // Wrap it. out.write(DerValue.tag_Sequence, scratch); certificateRequestInfo = out.toByteArray(); scratch = out; requester.getAlgorithmId().encode(scratch); //CSR hash signed with the private key of the smart card. //for 128 byte modulus // String signedCSR = "9333B5D6841A62D208B9715DD1464B695FAE533244D554012B4CABD47339C86666D0876544F7B297D1531DDDB2BA030918A2F42672DC7C934267AD98C4BF17BCB7C7FCF8D75B600452E6F2775525F761C6612410632D5F598F009E9A6E0A6EEF7947172A367780869500861193D2D7216DE22C1E6EA7D85E1C237982E07A2A50"; //for 256 byte modulus String signedCSR = "1E69173E015C253EDB881D7006E008E72B8545BDDEEA33F39955409A6606806C6AE845771466369862CE26A056AB7DED46355C6454B07FB89B37333EF7FD3555B09788C32BA3A1D8367A2F9D746FB40117D09D5A60D2CC90383A9B9EE0800B99575180E462D0A0032DFA0FDD3A3B744E77A48F43718B7E2C9D357B76E072EC223D696E47F0476B8D5822DD7A33A49D33B1B8D65DF7FC24F0AD5AD52B7C3FA2C11E312257CB95221B9D35F2EB72A5A679044B58412D15741FCE100C278E976601C9E0DEE77555590A0B1D22F5EE232D3C15F53CE195D12FC1765A46999702E115026120AECCB9C845F9091EBECA83ABBFED6DB0B070040192CFAF9060A93E27CE"; scratch.putBitString(HexString.hexToBuffer(signedCSR)); out = new DerOutputStream(); out.write(DerValue.tag_Sequence, scratch); String b64CSR = new String( Base64.encode(out.toByteArray())); System.out.println("\nCSR to be submitted to CA:\n" + b64CSR); Security.addProvider(new BouncyCastleProvider()); PKCS10CertificationRequest p10req = new PKCS10CertificationRequest(out.toByteArray()); boolean verified = p10req.verify(); if(!verified) System.out.println("\nVerify failed"); else System.out.println("\nVerify succeeded"); } }