cloudworker-proxy
Version:
An api gateway for cloudflare workers
224 lines (223 loc) • 8.77 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const webcrypto_core_1 = require("webcrypto-core");
const key_1 = require("../key");
const native = require("../native");
function b64_decode(b64url) {
return Buffer.from(webcrypto_core_1.Base64Url.decode(b64url));
}
class AesCrypto extends webcrypto_core_1.BaseCrypto {
static generateKey(algorithm, extractable, keyUsages) {
return new Promise((resolve, reject) => {
native.AesKey.generate(algorithm.length / 8, (err, key) => {
if (err) {
reject(err);
}
else {
const aes = new key_1.CryptoKey(key, algorithm, "secret", extractable, keyUsages);
resolve(aes);
}
});
});
}
static importKey(format, keyData, algorithm, extractable, keyUsages) {
return new Promise((resolve, reject) => {
const formatLC = format.toLocaleLowerCase();
let raw;
switch (formatLC) {
case "jwk":
raw = b64_decode(keyData.k);
break;
case "raw":
raw = keyData;
break;
default:
throw new webcrypto_core_1.WebCryptoError(`ImportKey: Wrong format value '${format}'`);
}
algorithm.length = raw.byteLength * 8;
native.AesKey.import(raw, (err, key) => {
if (err) {
reject(err);
}
else {
resolve(new key_1.CryptoKey(key, algorithm, "secret", extractable, keyUsages));
}
});
});
}
static exportKey(format, key) {
return new Promise((resolve, reject) => {
const nativeKey = key.native;
switch (format.toLocaleLowerCase()) {
case "jwk":
const jwk = {
kty: "oct",
alg: "",
key_ops: key.usages,
k: "",
ext: true,
};
jwk.alg = "A" + key.algorithm.length + /-(\w+)$/.exec(key.algorithm.name)[1].toUpperCase();
nativeKey.export((err, data) => {
if (err) {
reject(err);
}
else {
jwk.k = webcrypto_core_1.Base64Url.encode(data);
resolve(jwk);
}
});
break;
case "raw":
nativeKey.export((err, data) => {
if (err) {
reject(err);
}
else {
resolve(data.buffer);
}
});
break;
default: throw new webcrypto_core_1.WebCryptoError(`ExportKey: Unknown export format '${format}'`);
}
});
}
static encrypt(algorithm, key, data) {
if (algorithm.name.toUpperCase() === webcrypto_core_1.AlgorithmNames.AesKW) {
return this.WrapUnwrap(key.native, data, true);
}
else {
return this.EncryptDecrypt(algorithm, key, data, true);
}
}
static decrypt(algorithm, key, data) {
if (algorithm.name.toUpperCase() === webcrypto_core_1.AlgorithmNames.AesKW) {
return this.WrapUnwrap(key.native, data, false);
}
else {
return this.EncryptDecrypt(algorithm, key, data, false);
}
}
static EncryptDecrypt(algorithm, key, data, type) {
return new Promise((resolve, reject) => {
const nativeKey = key.native;
switch (algorithm.name.toLowerCase()) {
case webcrypto_core_1.AlgorithmNames.AesGCM.toLowerCase(): {
const algGCM = algorithm;
const iv = Buffer.from(algorithm.iv);
const aad = algGCM.additionalData ? Buffer.from(algGCM.additionalData) : Buffer.alloc(0);
const tagLength = algGCM.tagLength || 128;
if (type) {
nativeKey.encryptGcm(iv, data, aad || Buffer.alloc(0), tagLength / 8, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(data2.buffer);
}
});
}
else {
nativeKey.decryptGcm(iv, data, aad || Buffer.alloc(0), tagLength / 8, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(data2.buffer);
}
});
}
break;
}
case webcrypto_core_1.AlgorithmNames.AesCBC.toLowerCase(): {
const algCBC = "CBC";
const iv = Buffer.from(algorithm.iv);
if (type) {
nativeKey.encrypt(algCBC, iv, data, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(data2.buffer);
}
});
}
else {
nativeKey.decrypt(algCBC, iv, data, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(data2.buffer);
}
});
}
break;
}
case webcrypto_core_1.AlgorithmNames.AesCTR.toLowerCase(): {
const alg = algorithm;
const counter = Buffer.from(alg.counter);
if (type) {
nativeKey.encryptCtr(data, counter, alg.length, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(data2.buffer);
}
});
}
else {
nativeKey.decryptCtr(data, counter, alg.length, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(data2.buffer);
}
});
}
break;
}
case webcrypto_core_1.AlgorithmNames.AesECB.toLowerCase(): {
if (type) {
nativeKey.encryptEcb(data, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(data2.buffer);
}
});
}
else {
nativeKey.decryptEcb(data, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(data2.buffer);
}
});
}
break;
}
default: throw new webcrypto_core_1.AlgorithmError(webcrypto_core_1.AlgorithmError.NOT_SUPPORTED, algorithm.name);
}
});
}
static WrapUnwrap(key, data, enc) {
return new Promise((resolve, reject) => {
const fn = enc ? key.wrapKey : key.unwrapKey;
fn.call(key, data, (err, data2) => {
if (err) {
reject(err);
}
else {
resolve(new Uint8Array(data2).buffer);
}
});
});
}
}
exports.AesCrypto = AesCrypto;