【发布时间】:2015-12-03 10:37:36
【问题描述】:
我需要一个带有 NIST P-256 曲线的固定长度 64 字节 ECDSA 签名。
实现必须使用JCE。
以下代码示例可以生成签名并进行验证。
Provider provSign = new SunEC();
Provider provVerify = new SunEC();
// generate EC key
KeyPairGenerator kg = KeyPairGenerator.getInstance("EC", provSign);
ECGenParameterSpec ecParam = new ECGenParameterSpec("secp256r1");
kg.initialize(ecParam);
KeyPair keyPair = kg.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
try
{
// export public key
KeyFactory kf = KeyFactory.getInstance("EC", provSign);
ECPublicKeySpec publicKeySpec = kf.getKeySpec(keyPair.getPublic(), ECPublicKeySpec.class);
// import public key into other provider
kf = KeyFactory.getInstance("EC", provVerify);
publicKey = (PublicKey)kf.generatePublic(publicKeySpec);
}
catch (InvalidKeySpecException ex)
{
ex.printStackTrace();
}
// do test
Signature sig = Signature.getInstance("SHA256withECDSA", provSign);
Signature ver = Signature.getInstance("SHA256withECDSA", provVerify);
byte[] data = new byte[64];
// sign
sig.initSign(privateKey);
sig.update(data);
byte [] sign = sig.sign();
// Working Signature verification
ver.initVerify(publicKey);
ver.update(data);
if (ver.verify(sign) == false)
{
throw new Exception("Signature Verification failed");
}
问题是符号以某种方式编码(我认为是 DER 格式),长度在 70 到 72 字节之间,但我需要 64 字节(未编码/原始)签名。
我尝试过的: 转换为固定长度的 64 字节签名
DerInputStream derInputStream = new DerInputStream(sign);
DerValue[] values = derInputStream.getSequence(2);
byte[] random = values[0].getPositiveBigInteger().toByteArray();
byte[] signature = values[1].getPositiveBigInteger().toByteArray();
// r and s each occupy half the array
// Remove padding bytes
byte[] tokenSignature = new byte[64];
System.arraycopy(random, random.length > 32 ? 1 : 0, tokenSignature, random.length < 32 ? 1 : 0,
random.length > 32 ? 32 : random.length);
System.arraycopy(signature, signature.length > 32 ? 1 : 0, tokenSignature, signature.length < 32 ? 33 : 32,
signature.length > 32 ? 32 : signature.length);
System.out.println("Full Signature length: "+tokenSignature.length+" r length: "+random.length+" s length"+signature.length);
现在如何检查 64 字节的 tokenSignature ??? 我不知道如何将 64 字节的 tokenSignature 转换回正确的格式
ver.initVerify(publicKey);
ver.update(data);
if (ver.verify(???) == false)
{
throw new Exception("Signature Verification failed");
}
我已经使用 BouncyCastle ECDSASigner 实现了 64 字节签名验证。但我不能使用 ECDSASigner,因为它没有扩展 SignatureSpi,因此不能与 JCE 兼容的加密服务器一起使用。
【问题讨论】:
-
使用
DEROutputStream将两个整数排列成一个序列? -
感谢 Maarten 现在我明白了。我已经用 DEROutputStream 试过了,第一次就失败了。
-
@MaartenBodewes 您可以将您的评论添加为答案:-)
-
我今天会尝试,但如果它没有出现,您可能需要添加您的代码作为答案。
-
@MaartenBodewes 好的,我已经添加了答案
标签: java cryptography jce elliptic-curve ecdsa