如何生成33字节的压缩NIST P-256公钥?

时间:2018-12-05 09:57:26

标签: android kotlin cryptography bouncycastle ecdsa

我需要生成这样的公共密钥,并对字节进行附加签名(这将包括此先前生成的密钥)

我需要构造以下字节: ASN.1前缀+(33字节压缩NIST P-256公钥)的签名

签名应从其他已定义的私钥传递

ECDSA规范:

●曲线:

NIST P-256,也称为secp256r1和prime256v1(openssl)

●签名格式 ASN.1。 ECDSA签名的r和s值必须为正 整数,并进行DER编码。

Android中是否有API可以执行此过程?那我怎么用呢?

我尝试过的:

 try {
        val generator = KeyPairGenerator.getInstance("ECDSA")
        val ecSpec = ECNamedCurveTable
                .getParameterSpec("prime256v1")
        generator.initialize(ecSpec)
        val keyPair = generator.generateKeyPair()

        val privKey = keyPair.private
        val encodedPrivKey = privKey.encoded
        System.out.println(toHex(encodedPrivKey))

        val pubKey = keyPair.public
        val encodedPubKey = pubKey.encoded
        System.out.println(toHex(encodedPubKey))

        val keyFactory = KeyFactory.getInstance("ECDSA")
        val pubKey2 = keyFactory.generatePublic(X509EncodedKeySpec(encodedPubKey))
        if (Arrays.equals(pubKey2.getEncoded(), encodedPubKey)) {
            println("That worked for the public key")
        }

        val privKey2 = keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedPrivKey))
        if (Arrays.equals(privKey2.getEncoded(), encodedPrivKey)) {
            println("That worked for the private key")
        }

    } catch (e: GeneralSecurityException) {
        throw IllegalStateException(e)
    }

在这里-编码的公共密钥的长度为90个字节,我想我希望它为33个字节

1 个答案:

答案 0 :(得分:3)

以压缩格式编码Bouncy Castle椭圆曲线公钥:

Security.addProvider(BouncyCastleProvider())  

generator = KeyPairGenerator.getInstance("ECDSA")
val ecSpec = ECNamedCurveTable.getParameterSpec("prime256v1")        
generator.initialize(ecSpec)
val keyPair = generator.generateKeyPair()

val publicKey = keyPair.public as org.bouncycastle.jce.interfaces.ECPublicKey
val compressedPublicKey = publicKey.q.getEncoded(true)

您未提供有关如何对密钥进行签名和对签名进行编码的所有必要详细信息,但我最好的猜测是在公钥上使用标准编码的标准ECDSA签名:

val signer = Signature.getInstance("SHA256withECDSA")
signer.initSign(otherPrivateKey)
signer.update(compressedPublicKey)
val signature = signer.sign()

这将使用SHA256哈希公钥,使用ECDSA对其进行签名并进行格式化,并将其序列化为ASN.1结构ECDSASignature的DER编码。

ECDSASignature ::= SEQUENCE {
    r   INTEGER,
    s   INTEGER
}

rs将为正整数,并使用DER进行编码。还有其他方法,但这是最常用的方法(唯一的其他常见ECDSA签名格式是用零填充r和s并将它们串联)。