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");
}

}

Reply via email to