I want to sign a SHA-256 hash with DSA using PKCS#11 Java Wrapper for the PKCS#11 API of a hardware security module. For this purpose I selected the Mechanism CKM_DSA, load the corresponding DSA key from the token and have the data (read as byte-array) signed. The key I use for testing has 1024bit length.
Everything seems to work fine: The key is loaded, the Session.sign() yields a byte[] array of length 40. This corresponds to the PKCS#11 Spec, which says:
"For the purposes of this mechanism, a DSA signature is a 40-byte string, corresponding to the concatenation of the DSA values r and s, each represented most significant byte first."
Now I want to verify this signature using openSSL, i.e., using
openssl dgst -d -sha256 -verify ${PUBLIC_KEY} -signature signature.der <raw input file>
This works if I
a) created the signature using OpenSSL
b) created the signature using bouncycastle and encoding the result as ASN1 encoded DER sequence.
Now I want to do the same with the PKCS#11 signature. My question is: how to format this 40 byte array? I tried the following:
//sign data
byte[] signedData = this.pkcs11Session.sign(dataToSign);
//convert result
byte[] r = new byte[20];
byte[] s = new byte[20];
System.arraycopy(signedData, 0, r, 0, 20);
System.arraycopy(signedData, 19, s, 0, 20);
//encode result
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new ASN1Integer(r));
v.add(new ASN1Integer(s));
return new DERSequence(v).getEncoded(ASN1Encoding.DER);
The encoding part seems to be correct, because it works if I produce r and s directly with bouncycastle and another software key. Besides, openssl does accept the input format but the verification fails sometimes with an error, sometimes just with "Verification failure".
Thus, I assume the conversion of the PKCS#11 signature to r and s is wrong. Can someone help finding the mistake?