Мне нужна фиксированная длина 64 байтовой ECDSA-сигнатуры с кривой NIST P-256.Фиксированная длина 64 байта EC P-256 Подпись с JCE
Реализация должна использовать 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 Bytes tokenSignature Теперь ??? я не знаю, как преобразовать 64 байт tokenSignature обратно в нужный формат
ver.initVerify(publicKey);
ver.update(data);
if (ver.verify(???) == false)
{
throw new Exception("Signature Verification failed");
}
я достиг проверки подписи 64 байт с BouncyCastle ECDSASigner. Но я не могу использовать ECDSASigner, потому что он не расширяет SignatureSpi и, следовательно, не работает с криптовым сервером JCE complient.
Положите два целых числа в последовательности, используя 'DEROutputStream'? –
Спасибо, Маартен, теперь я понял. Я уже пробовал это с помощью DEROutputStream и не смог выполнить первый раз. – Hollerweger
@MaartenBodewes Вы можете добавить свой комментарий к ответе :-) – Hollerweger