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

标签 android kotlin cryptography bouncycastle ecdsa

我需要生成这样的公钥并对字节进行额外的签名(这将包括之前生成的 key )

我需要构造字节: 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 个字节

最佳答案

以压缩格式对 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)

您没有包括有关如何签署 key 和对签名进行编码的所有必要详细信息,但我最好的猜测是使用标准编码对公钥进行标准 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 并将它们连接起来)。

关于android - 如何生成 33 字节压缩的 NIST P-256 公钥?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53629537/

相关文章:

java-me - 网络安全

cryptography - 您采用哪种安全软件开发实践?

java - 在 Java 中扩展多个类的替换

java - Android:在不耗尽内存的情况下将流转换为字符串

java - RecyclerView 手势监听器

android - 在 Kotlin 中使用正则表达式获取字符串中模式的索引

android - 在 Kotlin for Android 中触发接口(interface)

python - Pycryptodome 官方例子不清楚

android - Kotlin:使用不同的子类多次实现泛型接口(interface)(基类是约束)

android - 在android中创建另一个字符串xml值文件