如何导入 PEM 格式的 RSA 私钥以用于 WebCrypto?
How can I import an RSA private key in PEM format for use with WebCrypto?
我正在尝试使用 WebCrypto 通过 RSA-PSS 对令牌进行签名,但我一直收到错误消息:
DataError: Data provided to an operation does not meet requirements
在 crypto.subtle.importKey
。
这是我的 JavaScript 代码:
function signToken(token, key) {
crypto.subtle.importKey(
'pkcs8',
PEM2Binary(key),
{
name: 'RSA-PSS',
hash: { name: 'SHA-256' },
},
false,
['sign']
).then(function(privKey){
crypto.subtle.sign(
'RSA-PSS',
privKey,
new TextEncoder().encode(token)
).then(function(signedToken){
msg = JSON.stringify({ intent: 'authenticate-token', signedToken: signedToken });
socket.send(msg);
})
}).catch(function(error){
console.error(error);
})
}
function PEM2Binary(pem) {
var encoded = '';
var lines = pem.split('\n');
for (var i = 0; i < lines.length; i++) {
if (lines[i].indexOf('-----') < 0) {
encoded += lines[i];
}
}
var byteStr = atob(encoded);
var bytes = new Uint8Array(byteStr.length);
for (var i = 0; i < byteStr.length; i++) {
bytes[i] = byteStr.charCodeAt(i);
}
return bytes.buffer;
}
我使用的示例私钥:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA3d+Y/kWq4nNrJd0dgktQ7lfDUtEIxcs10I8+xPEUhpvacotB
o787dDP4ZFYhRQf0WMjQYJwEna/NsrPuY2fgFWIBlUdpkj1SR00FBxHvnRlzP1Sg
cYnJlqh7/A26tM51nVkMtf/4NtYr+jFvRmB5759U1GRBFwZYsoWQRQlQKh5MAk89
KRc/TvrXNzam39GcLvSYz9uN0p2p2Mrofjgv42m53AqC9LOrQbwDX7Dxl0n4z3EI
Z2Ycx33QZVYiLPH1GHTJ8+JuKjqY0ovu6lghGN0y2xR+sqWNvgyW7xlDWZ6Vwyxs
K5SCIc48VwiiAyGZGhcCZloMlO5S/dutycgHhQIDAQABAoIBAQDXfef2bmu+bSNQ
LyYN+mCsXQkUUnoWwXuPCNGKLiwlYRIV1jL2ezGfdyp1KUI+7a7g3Immi2HgVXOP
cTrDyYvWuM2Y0zcyFeTn42JSr5TuHF3W0LbUD2N/tDxXXm5MVYnePTMfQXEusW0d
Hw5YaDOGDFYzwvuFBWD4YsjwhE8b12np/BZxniTzIl/blW+moocxAampj2SOc9dV
Z06Nw1gQYScclKqdASxnIsOOALhu7h0qOLAhhVgYWH6c+AC1q/72QQy9QYOW87e/
U5mkmxfjFtifYgnBGCRN5Uv5S6lnJD10z8+yR4SomVlxDTw0UkJMOT96KEhI5ICf
s1kKU2AxAoGBAPeWvNX63C+XbgDscttSNBrx6TOEwfeZiaGSxE+P+vKa3/YuVASf
rkL0xLnUTj+OhoaLzTetQ99RlUQsYkP8IQbIhiqXMHjpDTJStlHEbdJeT1fRUVF5
55S61bpYL8xLGYNvCFEmV66YuyZBAWq/DgkBG6gX2f71lHo2UJL/B/WjAoGBAOVp
Nw5/42wuwtSoynl5f0Tlbb5nruLbNMuaSAZ7ZjDVL6DXmwTyBQgg478LWB29xP2I
Or0TTPped3DeLTJrAG9Gxz6SEHfyh0lN7wc2RfS15NNfHKJwQJjuEaTR498yHWKq
UQkryU5xe3Qfr51RkFvmWzw91aUU0YwvqWDYodC3AoGBAPEBCBv6ry6cZvX7M+qN
4C6CYJBHoFAWYsSmivUvoAVcALowapR9ozGF9aE2Klzvrb92gnK59CGD1pqf4Z9v
4+4ob4Ex3nsz0Ca2IMcDQCvQpcdD97YpxeUe4UEc6pogWFt6T0w+2IcaIMKh8HEq
PM1DCNrdLNRj1P4JtPEB04ulAoGAXXIBGifftCZL+CGU7+wceizWCfPj2cYeeDys
z+8dzhBYaTTJkTcf85KqEhyF1P+CqR7/hhrBhU5Laq8lS98n+yuiZwtKKAGjN6nG
DnL+BdK9lZeta0E8Hs8CYteX8UdRjun/PjQWuJwjBEcP2o3ptnVbfmtVhfu361lS
rf8v0nsCgYAoshpslw7/qxUw7ac4xy0puMwuBBFAiQLFm5siOjZohOWYgQ3gZpl0
TJD9jBnEiH/Jpc883YzSh2bnEGZZ9wBffnhv1rjfNh6PbrcSdSKOznPEMpvw/pOB
wBnu6RWZ9mtWWIdDmYEJDqzrV7qp2w2x2foLc4oyCUKbUbQ/DvTYFQ==
-----END RSA PRIVATE KEY-----
在此先感谢您的帮助。
PEM文件中的header -----BEGIN RSA PRIVATE KEY-----
是为PKCS#1 keys保留的,但是WebCryptoApi不支持pkcs1,所以你需要使用类似的工具将key从PKCS#1转换为PKCS#8 openssl.
# openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in pkcs1.key -out pkcs8.key
我正在尝试使用 WebCrypto 通过 RSA-PSS 对令牌进行签名,但我一直收到错误消息:
DataError: Data provided to an operation does not meet requirements
在 crypto.subtle.importKey
。
这是我的 JavaScript 代码:
function signToken(token, key) {
crypto.subtle.importKey(
'pkcs8',
PEM2Binary(key),
{
name: 'RSA-PSS',
hash: { name: 'SHA-256' },
},
false,
['sign']
).then(function(privKey){
crypto.subtle.sign(
'RSA-PSS',
privKey,
new TextEncoder().encode(token)
).then(function(signedToken){
msg = JSON.stringify({ intent: 'authenticate-token', signedToken: signedToken });
socket.send(msg);
})
}).catch(function(error){
console.error(error);
})
}
function PEM2Binary(pem) {
var encoded = '';
var lines = pem.split('\n');
for (var i = 0; i < lines.length; i++) {
if (lines[i].indexOf('-----') < 0) {
encoded += lines[i];
}
}
var byteStr = atob(encoded);
var bytes = new Uint8Array(byteStr.length);
for (var i = 0; i < byteStr.length; i++) {
bytes[i] = byteStr.charCodeAt(i);
}
return bytes.buffer;
}
我使用的示例私钥:
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA3d+Y/kWq4nNrJd0dgktQ7lfDUtEIxcs10I8+xPEUhpvacotB
o787dDP4ZFYhRQf0WMjQYJwEna/NsrPuY2fgFWIBlUdpkj1SR00FBxHvnRlzP1Sg
cYnJlqh7/A26tM51nVkMtf/4NtYr+jFvRmB5759U1GRBFwZYsoWQRQlQKh5MAk89
KRc/TvrXNzam39GcLvSYz9uN0p2p2Mrofjgv42m53AqC9LOrQbwDX7Dxl0n4z3EI
Z2Ycx33QZVYiLPH1GHTJ8+JuKjqY0ovu6lghGN0y2xR+sqWNvgyW7xlDWZ6Vwyxs
K5SCIc48VwiiAyGZGhcCZloMlO5S/dutycgHhQIDAQABAoIBAQDXfef2bmu+bSNQ
LyYN+mCsXQkUUnoWwXuPCNGKLiwlYRIV1jL2ezGfdyp1KUI+7a7g3Immi2HgVXOP
cTrDyYvWuM2Y0zcyFeTn42JSr5TuHF3W0LbUD2N/tDxXXm5MVYnePTMfQXEusW0d
Hw5YaDOGDFYzwvuFBWD4YsjwhE8b12np/BZxniTzIl/blW+moocxAampj2SOc9dV
Z06Nw1gQYScclKqdASxnIsOOALhu7h0qOLAhhVgYWH6c+AC1q/72QQy9QYOW87e/
U5mkmxfjFtifYgnBGCRN5Uv5S6lnJD10z8+yR4SomVlxDTw0UkJMOT96KEhI5ICf
s1kKU2AxAoGBAPeWvNX63C+XbgDscttSNBrx6TOEwfeZiaGSxE+P+vKa3/YuVASf
rkL0xLnUTj+OhoaLzTetQ99RlUQsYkP8IQbIhiqXMHjpDTJStlHEbdJeT1fRUVF5
55S61bpYL8xLGYNvCFEmV66YuyZBAWq/DgkBG6gX2f71lHo2UJL/B/WjAoGBAOVp
Nw5/42wuwtSoynl5f0Tlbb5nruLbNMuaSAZ7ZjDVL6DXmwTyBQgg478LWB29xP2I
Or0TTPped3DeLTJrAG9Gxz6SEHfyh0lN7wc2RfS15NNfHKJwQJjuEaTR498yHWKq
UQkryU5xe3Qfr51RkFvmWzw91aUU0YwvqWDYodC3AoGBAPEBCBv6ry6cZvX7M+qN
4C6CYJBHoFAWYsSmivUvoAVcALowapR9ozGF9aE2Klzvrb92gnK59CGD1pqf4Z9v
4+4ob4Ex3nsz0Ca2IMcDQCvQpcdD97YpxeUe4UEc6pogWFt6T0w+2IcaIMKh8HEq
PM1DCNrdLNRj1P4JtPEB04ulAoGAXXIBGifftCZL+CGU7+wceizWCfPj2cYeeDys
z+8dzhBYaTTJkTcf85KqEhyF1P+CqR7/hhrBhU5Laq8lS98n+yuiZwtKKAGjN6nG
DnL+BdK9lZeta0E8Hs8CYteX8UdRjun/PjQWuJwjBEcP2o3ptnVbfmtVhfu361lS
rf8v0nsCgYAoshpslw7/qxUw7ac4xy0puMwuBBFAiQLFm5siOjZohOWYgQ3gZpl0
TJD9jBnEiH/Jpc883YzSh2bnEGZZ9wBffnhv1rjfNh6PbrcSdSKOznPEMpvw/pOB
wBnu6RWZ9mtWWIdDmYEJDqzrV7qp2w2x2foLc4oyCUKbUbQ/DvTYFQ==
-----END RSA PRIVATE KEY-----
在此先感谢您的帮助。
PEM文件中的header -----BEGIN RSA PRIVATE KEY-----
是为PKCS#1 keys保留的,但是WebCryptoApi不支持pkcs1,所以你需要使用类似的工具将key从PKCS#1转换为PKCS#8 openssl.
# openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in pkcs1.key -out pkcs8.key