椭圆曲线数字签名格式
Elliptic curve digital signature formats
有一个基于 Java 库 github/esig/dss 构建的应用程序,目标是向 PDF 文件添加远程签名。
不同的方法创建不同格式的签名。它们之间如何转换?特别是如何将pkcs11格式转换为ASN1格式?
If PKCS11 is used with smart card then sha256 hash 53EDC760B7A66E1F4D8B0C5715725EE447B79C02F7759C52AD3D36EADD29C10A produces signature like 3066023100ba193a7a87666ebd0f923b7368beeb536b88de47834049d3ed3baf70a23635ac9b73f671beef944b36332754a434f9de023100d4984ef9f4ef61eec28f73cee6f5d8f7a391420c8f21fcc018641f5b54f600458f2d2f823e632ab017fa041e58d48a3f using algorithm ECDSA_SHA256
这是正确的 ASN1 结构
$ 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
然而,使用 pkcs11-tool 从 CLI 创建签名时,签名长度不同,因此格式不同。如何将此格式转换为ASN1 der格式?
$ echo "53EDC760B7A66E1F4D8B0C5715725EE447B79C02F7759C52AD3D36EADD29C10A" |pkcs11-tool -s --slot 1 -p <PIN> |xxd -p -c96
Using signature algorithm ECDSA
3f8c7060430cae99a048618035548bb7449fd9795cad2d8b3b8888fff78593da79cf39a41314a832dd8bae0b5f86c165775fcee045a477809fa8bb3245330abec22443aa8b5bccb775c32238eda1e8ce31a2a84d67b58dc9e3697c3eb8497f43
经过更多研究,我从 BouncyCastle 库中找到了答案。 byte[] 签名是 RS 编码签名,return 值将是 ASN.1 编码签名。
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();
}
有一个基于 Java 库 github/esig/dss 构建的应用程序,目标是向 PDF 文件添加远程签名。 不同的方法创建不同格式的签名。它们之间如何转换?特别是如何将pkcs11格式转换为ASN1格式?
If PKCS11 is used with smart card then sha256 hash 53EDC760B7A66E1F4D8B0C5715725EE447B79C02F7759C52AD3D36EADD29C10A produces signature like 3066023100ba193a7a87666ebd0f923b7368beeb536b88de47834049d3ed3baf70a23635ac9b73f671beef944b36332754a434f9de023100d4984ef9f4ef61eec28f73cee6f5d8f7a391420c8f21fcc018641f5b54f600458f2d2f823e632ab017fa041e58d48a3f using algorithm ECDSA_SHA256
这是正确的 ASN1 结构
$ 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
然而,使用 pkcs11-tool 从 CLI 创建签名时,签名长度不同,因此格式不同。如何将此格式转换为ASN1 der格式?
$ echo "53EDC760B7A66E1F4D8B0C5715725EE447B79C02F7759C52AD3D36EADD29C10A" |pkcs11-tool -s --slot 1 -p <PIN> |xxd -p -c96
Using signature algorithm ECDSA
3f8c7060430cae99a048618035548bb7449fd9795cad2d8b3b8888fff78593da79cf39a41314a832dd8bae0b5f86c165775fcee045a477809fa8bb3245330abec22443aa8b5bccb775c32238eda1e8ce31a2a84d67b58dc9e3697c3eb8497f43
经过更多研究,我从 BouncyCastle 库中找到了答案。 byte[] 签名是 RS 编码签名,return 值将是 ASN.1 编码签名。
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();
}