mirror of https://github.com/waku-org/js-waku.git
Improve error feedback when crypto/subtle is not available
This commit is contained in:
parent
556e060335
commit
1ca7215478
|
@ -1,33 +1,48 @@
|
||||||
import nodeCrypto from "crypto";
|
import nodeCrypto from "crypto";
|
||||||
|
|
||||||
// IE 11
|
import { concat } from "uint8arrays/concat";
|
||||||
declare global {
|
|
||||||
interface Window {
|
|
||||||
msCrypto?: Crypto;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Crypto {
|
declare const self: Record<string, any> | undefined;
|
||||||
webkitSubtle?: SubtleCrypto;
|
const crypto: { node?: any; web?: any } = {
|
||||||
|
node: nodeCrypto,
|
||||||
|
web: typeof self === "object" && "crypto" in self ? self.crypto : undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getSubtle(): SubtleCrypto {
|
||||||
|
if (crypto.web) {
|
||||||
|
return crypto.web.subtle;
|
||||||
|
} else if (crypto.node) {
|
||||||
|
return crypto.node.webcrypto.subtle;
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
"The environment doesn't have Crypto Subtle API (if in the browser, be sure to use to be in a secure context, ie, https)"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const crypto =
|
export function randomBytes(bytesLength = 32): Uint8Array {
|
||||||
(typeof window !== "undefined" &&
|
if (crypto.web) {
|
||||||
(window as Window) &&
|
return crypto.web.getRandomValues(new Uint8Array(bytesLength));
|
||||||
(window.crypto || window.msCrypto)) ||
|
} else if (crypto.node) {
|
||||||
(nodeCrypto.webcrypto as unknown as Crypto);
|
const { randomBytes } = crypto.node;
|
||||||
const subtle: SubtleCrypto = crypto.subtle || crypto.webkitSubtle;
|
return Uint8Array.from(randomBytes(bytesLength));
|
||||||
|
} else {
|
||||||
if (subtle === undefined) {
|
throw new Error(
|
||||||
throw new Error("crypto and/or subtle api unavailable");
|
"The environment doesn't have randomBytes function (if in the browser, be sure to use to be in a secure context, ie, https)"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { crypto, subtle };
|
export async function sha256(...messages: Uint8Array[]): Promise<Uint8Array> {
|
||||||
|
if (crypto.web) {
|
||||||
export function randomBytes(size: number): Uint8Array {
|
const buffer = await crypto.web.subtle.digest("SHA-256", concat(messages));
|
||||||
return crypto.getRandomValues(new Uint8Array(size));
|
return new Uint8Array(buffer);
|
||||||
}
|
} else if (crypto.node) {
|
||||||
|
const { createHash } = crypto.node;
|
||||||
export function sha256(msg: ArrayBufferLike): Promise<ArrayBuffer> {
|
const hash = createHash("sha256");
|
||||||
return subtle.digest({ name: "SHA-256" }, msg);
|
messages.forEach((m) => hash.update(m));
|
||||||
|
return Uint8Array.from(hash.digest());
|
||||||
|
} else {
|
||||||
|
throw new Error("The environment doesn't have sha256 function");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as secp from "@noble/secp256k1";
|
import * as secp from "@noble/secp256k1";
|
||||||
import { concat } from "uint8arrays/concat";
|
import { concat } from "uint8arrays/concat";
|
||||||
|
|
||||||
import { randomBytes, sha256, subtle } from "../crypto";
|
import { getSubtle, randomBytes, sha256 } from "../crypto";
|
||||||
import { hexToBytes } from "../utils";
|
import { hexToBytes } from "../utils";
|
||||||
/**
|
/**
|
||||||
* HKDF as implemented in go-ethereum.
|
* HKDF as implemented in go-ethereum.
|
||||||
|
@ -37,10 +37,10 @@ function aesCtrEncrypt(
|
||||||
key: ArrayBufferLike,
|
key: ArrayBufferLike,
|
||||||
data: ArrayBufferLike
|
data: ArrayBufferLike
|
||||||
): Promise<Uint8Array> {
|
): Promise<Uint8Array> {
|
||||||
return subtle
|
return getSubtle()
|
||||||
.importKey("raw", key, "AES-CTR", false, ["encrypt"])
|
.importKey("raw", key, "AES-CTR", false, ["encrypt"])
|
||||||
.then((cryptoKey) =>
|
.then((cryptoKey) =>
|
||||||
subtle.encrypt(
|
getSubtle().encrypt(
|
||||||
{ name: "AES-CTR", counter: counter, length: 128 },
|
{ name: "AES-CTR", counter: counter, length: 128 },
|
||||||
cryptoKey,
|
cryptoKey,
|
||||||
data
|
data
|
||||||
|
@ -54,10 +54,10 @@ function aesCtrDecrypt(
|
||||||
key: ArrayBufferLike,
|
key: ArrayBufferLike,
|
||||||
data: ArrayBufferLike
|
data: ArrayBufferLike
|
||||||
): Promise<Uint8Array> {
|
): Promise<Uint8Array> {
|
||||||
return subtle
|
return getSubtle()
|
||||||
.importKey("raw", key, "AES-CTR", false, ["decrypt"])
|
.importKey("raw", key, "AES-CTR", false, ["decrypt"])
|
||||||
.then((cryptoKey) =>
|
.then((cryptoKey) =>
|
||||||
subtle.decrypt(
|
getSubtle().decrypt(
|
||||||
{ name: "AES-CTR", counter: counter, length: 128 },
|
{ name: "AES-CTR", counter: counter, length: 128 },
|
||||||
cryptoKey,
|
cryptoKey,
|
||||||
data
|
data
|
||||||
|
@ -71,9 +71,9 @@ function hmacSha256Sign(
|
||||||
msg: ArrayBufferLike
|
msg: ArrayBufferLike
|
||||||
): PromiseLike<Uint8Array> {
|
): PromiseLike<Uint8Array> {
|
||||||
const algorithm = { name: "HMAC", hash: { name: "SHA-256" } };
|
const algorithm = { name: "HMAC", hash: { name: "SHA-256" } };
|
||||||
return subtle
|
return getSubtle()
|
||||||
.importKey("raw", key, algorithm, false, ["sign"])
|
.importKey("raw", key, algorithm, false, ["sign"])
|
||||||
.then((cryptoKey) => subtle.sign(algorithm, cryptoKey, msg))
|
.then((cryptoKey) => getSubtle().sign(algorithm, cryptoKey, msg))
|
||||||
.then((bytes) => new Uint8Array(bytes));
|
.then((bytes) => new Uint8Array(bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,9 +83,9 @@ function hmacSha256Verify(
|
||||||
sig: ArrayBufferLike
|
sig: ArrayBufferLike
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const algorithm = { name: "HMAC", hash: { name: "SHA-256" } };
|
const algorithm = { name: "HMAC", hash: { name: "SHA-256" } };
|
||||||
const _key = subtle.importKey("raw", key, algorithm, false, ["verify"]);
|
const _key = getSubtle().importKey("raw", key, algorithm, false, ["verify"]);
|
||||||
return _key.then((cryptoKey) =>
|
return _key.then((cryptoKey) =>
|
||||||
subtle.verify(algorithm, cryptoKey, sig, msg)
|
getSubtle().verify(algorithm, cryptoKey, sig, msg)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { randomBytes, subtle } from "../crypto";
|
import { getSubtle, randomBytes } from "../crypto";
|
||||||
|
|
||||||
export const KeySize = 32;
|
export const KeySize = 32;
|
||||||
export const IvSize = 12;
|
export const IvSize = 12;
|
||||||
|
@ -11,10 +11,10 @@ export async function encrypt(
|
||||||
key: Buffer,
|
key: Buffer,
|
||||||
clearText: Buffer
|
clearText: Buffer
|
||||||
): Promise<Buffer> {
|
): Promise<Buffer> {
|
||||||
return subtle
|
return getSubtle()
|
||||||
.importKey("raw", key, Algorithm, false, ["encrypt"])
|
.importKey("raw", key, Algorithm, false, ["encrypt"])
|
||||||
.then((cryptoKey) =>
|
.then((cryptoKey) =>
|
||||||
subtle.encrypt({ iv, ...Algorithm }, cryptoKey, clearText)
|
getSubtle().encrypt({ iv, ...Algorithm }, cryptoKey, clearText)
|
||||||
)
|
)
|
||||||
.then(Buffer.from);
|
.then(Buffer.from);
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,10 @@ export async function decrypt(
|
||||||
key: Buffer,
|
key: Buffer,
|
||||||
cipherText: Buffer
|
cipherText: Buffer
|
||||||
): Promise<Buffer> {
|
): Promise<Buffer> {
|
||||||
return subtle
|
return getSubtle()
|
||||||
.importKey("raw", key, Algorithm, false, ["decrypt"])
|
.importKey("raw", key, Algorithm, false, ["decrypt"])
|
||||||
.then((cryptoKey) =>
|
.then((cryptoKey) =>
|
||||||
subtle.decrypt({ iv, ...Algorithm }, cryptoKey, cipherText)
|
getSubtle().decrypt({ iv, ...Algorithm }, cryptoKey, cipherText)
|
||||||
)
|
)
|
||||||
.then(Buffer.from);
|
.then(Buffer.from);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue