Fatemeh Fatemeh - 1 month ago 14
Android Question

error generating signed CSR with javacard (asn1 bad tag value)

I have generated key pair in a java card and return public key. I generate public key again in android app and then the CSR in android

private byte[] CertReqGeneration() throws Exception
{
if(publickeyobj==null)
return null;

String info = "CN=cn, OU=ou, O=o, C=cn, ST=city";
X500Principal x500 = new X500Principal(info);

X500Name x500name;
x500name= X500Name.getInstance(x500.getEncoded());

CertificationRequestInfo csrInfo = new CertificationRequestInfo(x500name, publickeyobj, new DERSet());

ASN1EncodableVector v = new ASN1EncodableVector();
v.add(csrInfo);
ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier("0.0");
v.add(new DERSequence(oid));
v.add(new DERBitString(new byte[] {}));
byte[] encoded = new DERSequence(v).getEncoded();
byte[] PKCS10= DataSignGeneration(encoded);

byte[] encoded = Base64.encode(PKCS10);
String base64=new String(encoded);
return base64;

}


but when I want to issue it in ca I get error asn1 bad tag value met
0x8009310b


It's my code for sign in applet:

//sign
Signature signature=Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1,false);
signature.init(thePrivateKey,Signature.MODE_SIGN);
signLength=signature.sign(buffer,(short)(ISO7816.OFFSET_CDATA & 0xFF), inputlength, buffer, (short)(0));


this is a signed csr that my code generated

G1Xsg/fetpr1/RfbUzWmDqRqu2GvymoQwXUJS/tB36l1SAvrRyDtwCgVHB3ukYFSZJeavFISQ9+R4zD1qxjO6r/E2/3o9UfARm2GeTwEZFv8LVgULAPc/e64v5xkiQYO05QwHa5PtmaXXD4NtuSNvF9xgNjtdAkosKqEPLcme5k=

Answer

@Abraham analysis seems correct: the generated CSR content is not valid

I guess the purpose of this code is building the ASN.1 structure to sign, but bouncycastle do it for you.

ASN1EncodableVector v = new ASN1EncodableVector();
v.add(csrInfo);
ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier("0.0");
v.add(new DERSequence(oid));
v.add(new DERBitString(new byte[] {}));
byte[] encoded = new DERSequence(v).getEncoded();
byte[] PKCS10= DataSignGeneration(encoded);

After comments we can see that it is needed to create an unsigned PKCS10 request to send to javacard to be signed there, and get the result to build the signed PKCS10 request

Bouncycastle does not provide an API to perform the operation. I suggest to checkout the PKCS10 example and the source code of PKCS10CertificateRequestBuilder to adapt to use your Java card. If you want to use in android you need the special distribution spongycastle.

This is a working example to create an unsigned request (without java card, but it should be easy to adapt. Just the signature process)

public byte[] generateCSR (X500Name subject, PublicKey publicKey, String signatureAlgorithm) throws Exception{
    //Create the unsigned CSR
    CertificationRequestInfo info = new CertificationRequestInfo(
                    x500name, SubjectPublicKeyInfo.getInstance(publicKey.getEncoded()),new DERSet());

    //The CSR bytes to be signed
    byte dataToSign[] = info.getEncoded(ASN1Encoding.DER);

    //Send the CSR to the card
    byte signedData[] = signOnJavaCard (dataToSign,signatureAlgorithm);

    //Build the signed CSR
    AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(signatureAlgorithm);
    PKCS10CertificationRequest csr = new PKCS10CertificationRequest(
                    new CertificationRequest(info, sigAlgId, new DERBitString(signedData)));
    byte signedCSR = csr.getEncoded();

    //Verify signature validity
    ContentVerifierProvider verifier = new JcaContentVerifierProviderBuilder().setProvider(new BouncyCastleProvider()).build(publicKey);
    boolean valid = csr.isSignatureValid(verifier);

    return signedCSR;
}

To test the code I have used a local signature method

public byte signOnJavaCard (byte dataToSign[], String signatureAlgorithm)
    Signature signature = Signature.getInstance(signatureAlgorithm);
    signature.initSign(privateKey); //get the private key in some way...
    signature.update(dataToSign);
    return signature.sign();
}