使用 Kotlin 和 Nodejs 解析公钥时出错

问题描述 投票:0回答:1

我正在尝试与Android和Nodejs建立一个加密通信桥梁。在这两种情况下,它都可以使用私钥和公钥生成密钥对。仅当生成共享密钥时,我才会收到错误消息,并显示以下消息“解析公钥时出错”。

我会一步步解释:

第1步:在Android(Kotlin)中生成密钥对

private fun generateKeyPair(): KeyPair {
val keyPairGenerator = KeyPairGenerator.getInstance("EC")
keyPairGenerator.initialize(ECGenParameterSpec("secp256r1"))
return keyPairGenerator.generateKeyPair()
}
val pk = generateKeyPair()
val publicKey = Base64.getEncoder().encodeToString(pk.public.encoded)
//Send "publicKey" to NodeJS Server

第2步:生成密钥对+在NodeJS中生成共享密钥

const publicKey = post.publicKey; //get public key of android device

const keyPair = crypto.createECDH('prime256v1');
keyPair.generateKeys();

// Define the EC public key schema
const ECPublicKey = asn1.define('ECPublicKey', function() {
    this.seq().obj(
        this.key('algorithm').seq().obj(
            this.key('id').objid(),
            this.key('curve').objid()
        ),
        this.key('pub').bitstr()
    );
});

fun getAESKey(sharedSecret: ByteArray): ByteArray {
     val digest = MessageDigest.getInstance("SHA-512")
     return digest.digest(sharedSecret).copyOfRange(0, 32)
}

const publicKeyDer = Buffer.from(publicKey, 'base64');
const publicKeyParsed = ECPublicKey.decode(publicKeyDer, 'der');
const publicKeyBuffer = Buffer.from(publicKeyParsed.pub.data, 'base64');
const sharedSecret = keyPair.computeSecret(publicKeyBuffer);
console.log("This is the sharedSecret:",sharedSecret.toString('base64'))
const pubKeyBase = keyPair.getPublicKey().toString('base64')
//reply the value of "pubKeyBase" to android device

第 3 步:在 Android 中生成共享密钥

val publicKeyB: String = "PUBLICKEY-OF-NODEJS"
val decKey: ByteArray = Base64.getDecoder().decode(publicKeyB)

val keyFactory = KeyFactory.getInstance("EC")
val genPublicKey = keyFactory.generatePublic(X509EncodedKeySpec(decKey)) //Error: java.security.spec.InvalidKeySpecException

val sharedSecret = getSharedSecret(pk.private, genPublicKey)
val aesKey = getAESKey(sharedSecret)

在第 3 行中: keyFactory.generatePublic(X509EncodedKeySpec(decKey)) 这是我收到错误的地方:

java.security.spec.InvalidKeySpecException: com.android.org.conscrypt.OpenSSLX509CertificateFactory$ParsingException: Error parsing public key

我查了一下,但似乎我使用了错误的EncodesKeySPec? 我哪里出错了?

android node.js kotlin encryption cryptojs
1个回答
0
投票
Kotlin 代码中的

X509EncodedKeySpec()
需要 X.509/SPKI 格式的 DER 编码密钥。相比之下,NodeJS 代码中的
keyPair.getPublicKey()
是未压缩格式的公钥。

未压缩格式的公钥可以使用例如 X.509/SPKI 格式转换为 PEM 编码密钥eckey-utils 包和

generatePem()
函数。

然后,通过删除页眉、页脚和换行符并对其余部分进行 Base64 解码,可以轻松将 PEM 编码密钥转换为 DER 编码密钥。或者,可以使用

createPublicKey()
export()
与加密模块进行转换。

示例代码:

const crypto = require('crypto')
const ecKeyUtils = require('eckey-utils');

// create key pair
const keyPair = crypto.createECDH('prime256v1')
keyPair.generateKeys()

// get public key
const publicKey = keyPair.getPublicKey()

// export as hex encoded uncompressed key (0x04 + <x> + <y>)
console.log(publicKey.toString('hex'))

// export as PEM encoded key in X.509/SPKI format: -----BEGIN PUBLIC KEY-----...
var x509Pem = ecKeyUtils.generatePem({curveName: 'prime256v1', publicKey: publicKey}).publicKey // PEM encoded
console.log(x509Pem)

// export as Base64 encoded DER encoded key in X.509/SPKI format (X509EncodedKeySpec() requires the DER encoded key in X.509/SPKI format)
var x509Der = crypto.createPublicKey(x509Pem).export({type: 'spki', format: 'der'}) // DER encoded
var x509DerB64 = x509Der.toString('base64') // Base64 encoded DER encoded
console.log(x509DerB64) 

Kotlin 端的导入成功:

...
val x509DerB64 = "MFkwEw..."
val decKey = Base64.getDecoder().decode(x509DerB64)
val keyFactory = KeyFactory.getInstance("EC")
val genPublicKey = keyFactory.generatePublic(X509EncodedKeySpec(decKey)) 
...
© www.soinside.com 2019 - 2024. All rights reserved.