TypeError: ключ не относится к типу CryptoKey
Я использую Node с библиотекой @ specific /webcrypto для шифрования вводимой строки; однако он вызывает эту ошибку TypeError, но тот же код отлично работает в браузере Chrome. Я новичок в Node и Async.
Вот код:
const { Crypto } = require("@peculiar/webcrypto");
const crypto = new Crypto();
const btoa = require('btoa');
const CC = "Hello World";
const b_size = CC.length;
P = new ArrayBuffer(b_size);
C = new Uint8Array(P);
function iKey() {
return crypto.subtle.importKey(
"jwk",{
kty:"RSA",
e:"AQAB",
n:"gfJ-DTivOto0B1qvI9jGQgLvPvEkfVzbhf4-GM_XGrSyJRa1ASOZV89qpBIYDq8lwSwxibybvRqROhNavH6X_xQux9TAhDVBYZv8bH7pR4cfCLQrNvbpFRan3XBv7zeifGThyJGJ8R0BJTh4R4K9cu7kE48Ig1GO6iIx6emnYaQBhRUHsLfxfhQCwlHLraOXcP_RPM9TfZRO4dVHdRrdX1B60B6OqwU1ojRmo1oLiJCN6KjwMsYbSbYnflt_uyFUGxxBQE-1qnhBkarm10pgIgVDiSIn8XKQBxLg-Ao6cc7pXytp7Bd--g45OKHinRKaSP-Ub8g3S9g4LV2Qt8UZbQ",
alg:"RSA-OAEP-256",
ext:true
},
{
name:"RSA-OAEP",
hash: {name: "SHA-256"}
},
true,
["encrypt"]
);
}
e_key = iKey();
for(i=0; i < b_size; ++i) {
C[i] = CC.charCodeAt(i);
}
function crypt() {
return crypto.subtle.encrypt(
{
name: "RSA-OAEP",
hash: {name: "SHA-256"}
},
e_key, P
).then(function(encrypted){
console.log(new Uint8Array(encrypted));
}).catch(function(err){
console.error(err);
});
}
crypt();
1 ответ
Причина этого в том, что к тому времени crypt()
бегал, iKey()
не закончил..
Исправление заключалось в перемещении e_key = iKey()
в crypt()
функция, и сделатьcrypt()
функцию async, чтобы мы моглиawait
за iKey()
чтобы закончить, прежде чем пытаться использовать возвращаемые данные.
крипта теперь выглядит так:
async function crypt() {
let e_key = await iKey();
return crypto.subtle.encrypt(
{
name: "RSA-OAEP",
hash: {name: "SHA-256"}
},
e_key, P
).then(function(encrypted){
console.log(new Uint8Array(encrypted));
}).catch(function(err){
console.error(err);
});
}
Это полный файл:
const { Crypto } = require("@peculiar/webcrypto");
const crypto = new Crypto();
const btoa = require('btoa');
const CC = "Hello World";
const b_size = CC.length;
P = new ArrayBuffer(b_size);
C = new Uint8Array(P);
function iKey() {
return crypto.subtle.importKey(
"jwk",{
kty:"RSA",
e:"AQAB",
n:"gfJ-DTivOto0B1qvI9jGQgLvPvEkfVzbhf4-GM_XGrSyJRa1ASOZV89qpBIYDq8lwSwxibybvRqROhNavH6X_xQux9TAhDVBYZv8bH7pR4cfCLQrNvbpFRan3XBv7zeifGThyJGJ8R0BJTh4R4K9cu7kE48Ig1GO6iIx6emnYaQBhRUHsLfxfhQCwlHLraOXcP_RPM9TfZRO4dVHdRrdX1B60B6OqwU1ojRmo1oLiJCN6KjwMsYbSbYnflt_uyFUGxxBQE-1qnhBkarm10pgIgVDiSIn8XKQBxLg-Ao6cc7pXytp7Bd--g45OKHinRKaSP-Ub8g3S9g4LV2Qt8UZbQ",
alg:"RSA-OAEP-256",
ext:true
},
{
name:"RSA-OAEP",
hash: {name: "SHA-256"}
},
true,
["encrypt"]
);
}
/** COMMENTED THIS LINE OUT */
// e_key = iKey();
for(i=0; i < b_size; ++i) {
C[i] = CC.charCodeAt(i);
}
async function crypt() {
/** MOVED iKey INTO HERE */
let e_key = await iKey();
return crypto.subtle.encrypt(
{
name: "RSA-OAEP",
hash: {name: "SHA-256"}
},
e_key, P
).then(function(encrypted){
console.log(new Uint8Array(encrypted));
}).catch(function(err){
console.error(err);
});
}
crypt();
Что возвращает:
// return
Uint8Array(256) [
17, 88, 41, 189, 185, 200, 225, 96, 186, 155, 153, 212,
207, 91, 203, 5, 38, 152, 19, 107, 182, 180, 210, 54,
236, 153, 204, 112, 148, 65, 246, 208, 34, 90, 251, 40,
64, 33, 175, 123, 84, 59, 249, 24, 125, 219, 65, 220,
7, 186, 175, 204, 123, 41, 121, 143, 163, 100, 223, 180,
167, 99, 19, 52, 117, 145, 215, 188, 226, 173, 237, 244,
165, 101, 203, 104, 60, 26, 255, 181, 80, 185, 240, 162,
156, 215, 212, 39, 13, 215, 51, 192, 167, 183, 4, 160,
206, 92, 97, 84,
... 156 more items
]
Обновить:
Причина, по которой вы не можете использовать его в глобальной области видимости, заключается в том, как Node обрабатывает асинхронные операции. При этом у вас есть несколько вариантов:
Опция 1
Вместо того, чтобы использовать await
за iKey()
(который является просто синтаксическим сахаром для обещаний) вы можете использовать .then
с ним, а также повернуть crypto
в Promise
основанная функция:
// code above removed for brevity
function crypt(key) {
return new Promise((resolve, reject) => {
crypto.subtle.encrypt(
{
name: "RSA-OAEP",
hash: {name: "SHA-256"}
},
key, P
).then(encrypted => {
resolve(new Uint8Array(encrypted));
}).catch(err => {
reject(err);
});
})
}
// Use it like:
iKey().then(e_key => {
crypt(e_key) // <- we are now passing the key in as a param
.then(enc => console.log(enc))
.catch(err => console.error(err))
}).catch(error => {
console.error(error);
})
Вариант 2:
Оберните все в выражение асинхронной функции, вызываемой немедленно.
(async () => {
const e_key = await iKey();
// also async now
async function crypt() {
return crypto.subtle.encrypt(
{
name: "RSA-OAEP",
hash: {name: "SHA-256"}
},
e_key, P
).then(encrypted => {
return new Uint8Array(encrypted);
}).catch(err => {
throw err;
});
}
try {
const enc = await crypt();
console.log(enc);
} catch (err) {
console.error(err);
}
})();
Существуют также библиотеки Promise, такие как BlueBird, которые вы можете использовать, чтобы упростить эту задачу, но в этом вся суть..
Обновление 2:
Вот как вы можете использовать "глобальную функцию" с обещанием.
const {
Crypto
} = require("@peculiar/webcrypto");
const crypto = new Crypto();
const btoa = require('btoa');
const CC = "Hello World";
const b_size = CC.length;
P = new ArrayBuffer(b_size);
C = new Uint8Array(P);
function iKey() {
return crypto.subtle.importKey(
"jwk", {
kty: "RSA",
e: "AQAB",
n: "gfJ-DTivOto0B1qvI9jGQgLvPvEkfVzbhf4-GM_XGrSyJRa1ASOZV89qpBIYDq8lwSwxibybvRqROhNavH6X_xQux9TAhDVBYZv8bH7pR4cfCLQrNvbpFRan3XBv7zeifGThyJGJ8R0BJTh4R4K9cu7kE48Ig1GO6iIx6emnYaQBhRUHsLfxfhQCwlHLraOXcP_RPM9TfZRO4dVHdRrdX1B60B6OqwU1ojRmo1oLiJCN6KjwMsYbSbYnflt_uyFUGxxBQE-1qnhBkarm10pgIgVDiSIn8XKQBxLg-Ao6cc7pXytp7Bd--g45OKHinRKaSP-Ub8g3S9g4LV2Qt8UZbQ",
alg: "RSA-OAEP-256",
ext: true
}, {
name: "RSA-OAEP",
hash: {
name: "SHA-256"
}
},
true,
["encrypt"]
);
}
/** COMMENTED THIS LINE OUT */
// e_key = iKey();
for (i = 0; i < b_size; ++i) {
C[i] = CC.charCodeAt(i);
}
function crypt(key) { // <-- Notice we now pass in the key via a param
return new Promise((resolve, reject) => {
crypto.subtle.encrypt({
name: "RSA-OAEP",
hash: {
name: "SHA-256"
}
},
key, P
).then(function (encrypted) {
resolve(new Uint8Array(encrypted));
}).catch(function (err) {
reject(err);
});
})
}
function someGlobalFunction(encryptedValue) {
console.log("\r\n\r\nFROM GLOBAL FUNCTION:\r\n\r\n");
console.log(encryptedValue);
console.log("This is some global function");
console.log("I am taking the encryped value as a param and doing something with it");
console.log("For now, I just logged it to console..(see above)");
}
iKey().then(e_key => {
crypt(e_key).then(encryped => { // <-- Notice we now pass in the key via a param
someGlobalFunction(encryped);
}).catch(error => {
console.error(error);
})
}).catch(err => {
console.error(err);
});