There is app built on Java library github/esig/dss and goal is to add remote signatures to PDF files. Different methods create different formats of signatures. How to convert between them? Especially how to convert pkcs11 format to ASN1?
If PKCS11 is used with smart card then sha256 hash 53EDC760B7A66E1F4D8B0C5715725EE447B79C02F7759C52AD3D36EADD29C10A produces signature like 3066023100ba193a7a87666ebd0f923b7368beeb536b88de47834049d3ed3baf70a23635ac9b73f671beef944b36332754a434f9de023100d4984ef9f4ef61eec28f73cee6f5d8f7a391420c8f21fcc018641f5b54f600458f2d2f823e632ab017fa041e58d48a3f using algorithm ECDSA_SHA256
This is proper ASN1 structure
$ openssl asn1parse -inform der -in signature.bin
0:d=0 hl=2 l= 102 cons: SEQUENCE
2:d=1 hl=2 l= 49 prim: INTEGER :BA193A7A87666EBD0F923B7368BEEB536B88DE47834049D3ED3BAF70A23635AC9B73F671BEEF944B36332754A434F9DE
53:d=1 hl=2 l= 49 prim: INTEGER :D4984EF9F4EF61EEC28F73CEE6F5D8F7A391420C8F21FCC018641F5B54F600458F2D2F823E632AB017FA041E58D48A3F
However creating signature from CLI using pkcs11-tool the signature length is different so its in different format. How to convert this format to ASN1 der format?
$ echo "53EDC760B7A66E1F4D8B0C5715725EE447B79C02F7759C52AD3D36EADD29C10A" |pkcs11-tool -s --slot 1 -p <PIN> |xxd -p -c96
Using signature algorithm ECDSA
3f8c7060430cae99a048618035548bb7449fd9795cad2d8b3b8888fff78593da79cf39a41314a832dd8bae0b5f86c165775fcee045a477809fa8bb3245330abec22443aa8b5bccb775c32238eda1e8ce31a2a84d67b58dc9e3697c3eb8497f43
After some more research I found the answer from the BouncyCastle library. byte[] signature is RS encoded signature and the return value will be ASN.1 encoded signature.
static byte[] concatenatedRSToASN1DER(final byte[] signature, int signLength) {
int len = signLength / 2;
int arraySize = len + 1;
byte[] r = new byte[arraySize];
byte[] s = new byte[arraySize];
System.arraycopy(signature, 0, r, 1, len);
System.arraycopy(signature, len, s, 1, len);
BigInteger rBigInteger = new BigInteger(r);
BigInteger sBigInteger = new BigInteger(s);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
DERSequenceGenerator seqGen = new DERSequenceGenerator(bos);
seqGen.addObject(new ASN1Integer(rBigInteger.toByteArray()));
seqGen.addObject(new ASN1Integer(sBigInteger.toByteArray()));
seqGen.close();
bos.close();
} catch (IOException e) {
throw new RuntimeException("Failed to generate ASN.1 DER signature", e);
}
return bos.toByteArray();
}