gpt4 book ai didi

javascript - 为什么nodejs加密签名功能只接受privateKey pem格式?

转载 作者:太空宇宙 更新时间:2023-11-04 03:00:25 24 4
gpt4 key购买 nike

首先,我们使用elliptic加密包。符号函数如下所示:

signByPriv = function (privKeyData, text) {
let msgHash = getmsgHash(text, "SHA-384");
let key = ec.keyFromPrivate(Buffer.from(privKeyData,'base64').toString('hex'), 'hex')
let signature = key.sign(msgHash);
return signature
}

然后我们想将其更改为nodejs版本,因为nodejs在底层使用openssl。所以它会更快

首先我的符号函数如下:

signByPriv = function (privKeyData, text) {
const sign1 = crypto.createSign('SHA384'); //hash do inside
sign1.write(text);
sign1.end();
const signature = sign1.sign(privKeyData, 'hex');
return signature;
}

它会提示错误:

internal/crypto/sig.js:86 const ret = this[kHandle].sign(data, format, type, passphrase, rsaPadding,

Error: error:0909006C:PEM routines:get_name:no start line

所以我查了nodejs文档,发现需要传递pem格式的privKey。

signByPriv = function (privKeyData, text) {
let key = turnBase64PrivToPemKey(privKeyData) //base64 => pem
const sign1 = crypto.createSign('SHA384'); //hash do inside
sign1.write(text);
sign1.end();
const signature = sign1.sign(privKeyData, 'hex');
return signature;
}
turnBase64PrivToPemKey = function (base64Priv) {
var key_hex = Buffer.from(base64Priv, 'base64').toString('hex');
ecdh.setPrivateKey(key_hex, 'hex')
var pubKey_hex = ecdh.getPublicKey().toString('hex');
//pem格式私钥文件是由固定字符加上私钥和公钥拼接而成==同一条曲线,固定字符相同
var mykey = '308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420' + key_hex + 'a144034200' + pubKey_hex;
privKey = '-----BEGIN PRIVATE KEY-----\n' + Buffer.from(mykey, 'hex').toString('base64') + '\n-----END PRIVATE KEY-----';
pubKey = crypto.createPublicKey(privKey); //也可恢复出公钥
let Key = {
privKey,
pubKey
}
return Key;
}

太棒了,签名和验证功能都很完美。

但是后端可能会做同样的愚蠢的事情......

the curve we chose is prime256v1

const ecdh = crypto.createECDH('prime256v1')

所以,我想知道为什么nodejs签名函数不能只接受base64 priv?

因为pem格式仅由私钥、公钥和其他固定字符串组成。

最佳答案

SignVerify不仅支持 PEM 格式,还支持 DER 格式(两者均在 @Maarten Bodewes 的 answer 中进行了描述)。此外,Pkcs8-( RFC 5208here )和 Sec1-EC key ( SECG SEC1, section C.4here )都可以使用。但是,不直接支持原始 EC key 。因此,如果 key 仅作为原始 key 可用,则始终需要进行转换。但这种转换比发布的代码更容易实现,因此(在我看来)没有显着额外的工作,例如签名:

var buf1 = Buffer.from('308141020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420', 'hex'); // specific byte-sequence for curve prime256v1
var buf2 = Buffer.from('<Raw private key as hex string>', 'hex'); // raw private key (32 bytes)
var privateKeyPkcs8Der = Buffer.concat([buf1, buf2], buf1.length + buf2.length);
var sign = crypto.createSign('SHA384');
sign.write(<data to sign>);
sign.end();
var signature = sign.sign({ key: privateKeyPkcs8Der, format: 'der', type: 'pkcs8' }); // specify format and type

用于签名的 key privateKeyPkcs8Der 是 DER 格式的 Pkcs8 key (没有原始公钥)。

与发布的代码相比:

  • 使用 DER 格式而不是 PEM 格式。
  • 只有原始私钥嵌入到 Pkcs8 容器中,嵌入原始公钥。
  • buf1 包含属于 prime256v1 (secp256r1) 的字节序列和一个不带原始公钥的 Pkcs8 容器。注意:字节序列与发布代码中使用的字节序列略有不同。这是因为字节序列还包含长度信息,并且根据是否嵌入原始公钥而有所不同。
<小时/>

这同样适用于验证:

var buf1 = Buffer.from('3059301306072a8648ce3d020106082a8648ce3d030107034200', 'hex'); // specific byte-sequence for curve prime256v1
var buf2 = Buffer.from('<Raw public key as hex string>', 'hex'); // raw public key (uncompressed, 65 bytes, startting with 04)
var publicKeyX509Der = Buffer.concat([buf1, buf2], buf1.length + buf2.length);
var verify = crypto.createVerify('SHA384');
verify.write(<data to sign>);
verify.end();
var verified = verify.verify({ key: publicKeyX509Der, format: 'der', type: 'spki' }, signature); // specify format and type

用于验证的 key publicKeyX509Der 是 DER 格式的 X.509-SubjectPublicKeyInfo-key ( SECG SEC1, section C.3 )。

与签名一样:

  • 使用 DER 格式而不是 PEM 格式。
  • buf1 包含属于 prime256v1 的字节序列。
<小时/>

在发布的代码中,ECDH 类的方法用于从原始私钥派生原始公钥。相反,createPublicKey - 和export -方法可用于从 Pkcs8-key 派生 X.509-SubjectPublicKeyInfo-key:

var publicKey = crypto.createPublicKey({ key: privKeyPkcs8DER, type: 'pkcs8', format: 'der' });
var publicKeyX509Der = publicKey.export({type: 'spki', format: 'der'})

这里 privateKeyPkcs8Der 是一个 Pkcs8 key (没有原始公钥),publicKeyX509Der 是一个 X.509-SubjectPublicKeyInfo-key,两者都是 DER 格式。

<小时/>

注意:也可以使用 Sec1 容器代替 Pkcs8 容器。然而, key 和字节序列的结构必须相应地进行调整。 here 描述了 Sec1 容器的使用,但对于不同的曲线 (secp256k1),因此不能简单地复制字节序列。

关于javascript - 为什么nodejs加密签名功能只接受privateKey pem格式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58350484/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com