Как создать 33-байтовый открытый ключ NIST P-256? - PullRequest
0 голосов
/ 05 декабря 2018

Мне нужно сгенерировать такой открытый ключ и сделать дополнительную подпись байтов (которая будет включать в себя этот сгенерированный ранее ключ)

Мне нужно построить байты из: Префикс ASN.1 + подпись (33-сжатый байт открытый ключ NIST P-256)

Сигнатура должна доставляться из другого определенного закрытого ключа

Характеристики ECDSA:

● Кривая:

NIST P-256 В противном случае известен как secp256r1 и prime256v1 (openssl)

● Формат подписи ASN.1.Значения r и s подписи ECDSA должны быть положительными целыми числами и должны кодироваться как 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 голосов
/ 05 декабря 2018

Чтобы закодировать открытый ключ эллиптической кривой 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, форматирует и сериализует его в качестве кодировки DER структуры ASN.1 ECDSASignature.

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

r и s будут натуральными числами и закодированы с помощью DER.Есть и другие способы сделать это, но это, безусловно, самый распространенный способ (единственный другой распространенный формат подписи ECDSA - это просто заполнение нулями r и s и их объединение).

...