Crypto.sign() 函数用给定的私钥签署消息
Crypto.sign() function to sign a message with given private key
我需要使用 NodeJS 中的 crypto.sign() 函数对消息进行签名以获得有效的 JWT。
我有一个这样的私钥(base 64):
Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==
然后我试图获得签名:
const getJWT = () => {
const privateKey =
"Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==";
const payload = {
iss: "test",
aud: "test.com",
iat: 1650101178,
exp: 1650101278,
sub: "12345678-1234-1234-1234-123456789123"
};
const token = encode(payload, privateKey);
return token
};
const encode = (payload, key) => {
const header = {
typ: "JWT",
alg: "EdDSA"
};
const headerBase64URL = base64url(JSON.stringify(header));
const payloadBase64URL = base64url(JSON.stringify(payload));
const msg = Buffer.from(`${headerBase64URL}.${payloadBase64URL}`);
const keyDecoded = Buffer.from(key, "base64");
const signature = crypto.sign("Ed25519", msg, keyDecoded); //Here is the problem
const signatureBase64url = base64url(Buffer.from(signature));
return `${msg}.${signatureBase64url}`;
};
我收到此错误:
internal/crypto/sig.js:142
return _signOneShot(keyData, keyFormat, keyType, keyPassphrase, data,
^
Error: error:0909006C:PEM routines:get_name:no start line
library: 'PEM routines',
function: 'get_name',
reason: 'no start line',
code: 'ERR_OSSL_PEM_NO_START_LINE'
如何使我的私钥适应有效格式?
crypto.sign()
方法需要 Ed25519 的 PKCS#8 格式的私钥。您的密钥是原始密钥,由原始私有 32 字节密钥和原始 public 32 字节、base64 编码的串联组成。可以按如下方式导出和导入 DER 编码的 PKCS#8 密钥:
- Base64 解码您的密钥。使用原始 64 字节密钥的前 32 个字节(即原始私钥)。
- 为私有 Ed25519 密钥(十六进制)连接以下前缀:
302e020100300506032b657004220420
- 导入 DER 编码的 PKCS#8 密钥。
因此,getJWT()
中的密钥导入必须更改如下:
const privateKey = toPkcs8der('Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==');
和
const toPkcs8der = (rawB64) => {
var rawPrivate = Buffer.from(rawB64, 'base64').subarray(0, 32);
var prefixPrivateEd25519 = Buffer.from('302e020100300506032b657004220420','hex');
var der = Buffer.concat([prefixPrivateEd25519, rawPrivate]);
return crypto.createPrivateKey({key: der, format: "der", type: "pkcs8"})
}
此外,在encode()
函数中:
删除行const keyDecoded = Buffer.from(key, "base64")
创建签名
const signature = crypto.sign(null, msg, key)
请注意,对于 Ed25519,null
必须作为 sign()
调用中的第一个参数传递。算法来源于key
通过这些更改,NodeJS 代码 returns 以下 JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJ0ZXN0IiwiYXVkIjoidGVzdC5jb20iLCJpYXQiOjE2NTAxMDExNzgsImV4cCI6MTY1MDEwMTI3OCwic3ViIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MTIzIn0.f7WG_02UKljrMeVVOTNNBAGxtLXJUT_8QAnujNhomV18Pn5cU-0lHRgVlmRttOlqI7Iol_fHut3C4AOXxDGnAQ
匹配 .
我需要使用 NodeJS 中的 crypto.sign() 函数对消息进行签名以获得有效的 JWT。 我有一个这样的私钥(base 64):
Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==
然后我试图获得签名:
const getJWT = () => {
const privateKey =
"Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==";
const payload = {
iss: "test",
aud: "test.com",
iat: 1650101178,
exp: 1650101278,
sub: "12345678-1234-1234-1234-123456789123"
};
const token = encode(payload, privateKey);
return token
};
const encode = (payload, key) => {
const header = {
typ: "JWT",
alg: "EdDSA"
};
const headerBase64URL = base64url(JSON.stringify(header));
const payloadBase64URL = base64url(JSON.stringify(payload));
const msg = Buffer.from(`${headerBase64URL}.${payloadBase64URL}`);
const keyDecoded = Buffer.from(key, "base64");
const signature = crypto.sign("Ed25519", msg, keyDecoded); //Here is the problem
const signatureBase64url = base64url(Buffer.from(signature));
return `${msg}.${signatureBase64url}`;
};
我收到此错误:
internal/crypto/sig.js:142
return _signOneShot(keyData, keyFormat, keyType, keyPassphrase, data,
^
Error: error:0909006C:PEM routines:get_name:no start line
library: 'PEM routines',
function: 'get_name',
reason: 'no start line',
code: 'ERR_OSSL_PEM_NO_START_LINE'
如何使我的私钥适应有效格式?
crypto.sign()
方法需要 Ed25519 的 PKCS#8 格式的私钥。您的密钥是原始密钥,由原始私有 32 字节密钥和原始 public 32 字节、base64 编码的串联组成。可以按如下方式导出和导入 DER 编码的 PKCS#8 密钥:
- Base64 解码您的密钥。使用原始 64 字节密钥的前 32 个字节(即原始私钥)。
- 为私有 Ed25519 密钥(十六进制)连接以下前缀:
302e020100300506032b657004220420
- 导入 DER 编码的 PKCS#8 密钥。
因此,getJWT()
中的密钥导入必须更改如下:
const privateKey = toPkcs8der('Dm2xriMD6riJagld4WCA6zWqtuWh40UzT/ZKO0pZgtHATOt0pGw90jG8BQHCE3EOjiCkFR2/gaW6JWi+3nZp8A==');
和
const toPkcs8der = (rawB64) => {
var rawPrivate = Buffer.from(rawB64, 'base64').subarray(0, 32);
var prefixPrivateEd25519 = Buffer.from('302e020100300506032b657004220420','hex');
var der = Buffer.concat([prefixPrivateEd25519, rawPrivate]);
return crypto.createPrivateKey({key: der, format: "der", type: "pkcs8"})
}
此外,在encode()
函数中:
删除行
const keyDecoded = Buffer.from(key, "base64")
创建签名
const signature = crypto.sign(null, msg, key)
请注意,对于 Ed25519,
null
必须作为sign()
调用中的第一个参数传递。算法来源于key
通过这些更改,NodeJS 代码 returns 以下 JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJpc3MiOiJ0ZXN0IiwiYXVkIjoidGVzdC5jb20iLCJpYXQiOjE2NTAxMDExNzgsImV4cCI6MTY1MDEwMTI3OCwic3ViIjoiMTIzNDU2NzgtMTIzNC0xMjM0LTEyMzQtMTIzNDU2Nzg5MTIzIn0.f7WG_02UKljrMeVVOTNNBAGxtLXJUT_8QAnujNhomV18Pn5cU-0lHRgVlmRttOlqI7Iol_fHut3C4AOXxDGnAQ
匹配