我需要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的加密服务器一起使用。