UNPKG

@pact-toolbox/crypto

Version:
820 lines (801 loc) 30.8 kB
import nodeCrypto from "node:crypto"; import "@noble/ed25519"; import { blake2b } from "blakejs"; //#region ../../node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.node.mjs const subtle = nodeCrypto.webcrypto?.subtle || {}; const randomUUID = () => { return nodeCrypto.randomUUID(); }; const getRandomValues = (array) => { return nodeCrypto.webcrypto.getRandomValues(array); }; const _crypto = { randomUUID, getRandomValues, subtle }; //#endregion //#region src/assertions.ts function assertIsSecureContext() {} let cachedEd25519Decision; async function isEd25519CurveSupported(subtle$1) { if (cachedEd25519Decision === void 0) cachedEd25519Decision = new Promise((resolve) => { subtle$1.generateKey("Ed25519", false, ["sign", "verify"]).catch(() => { resolve(cachedEd25519Decision = false); }).then(() => { resolve(cachedEd25519Decision = true); }); }); if (typeof cachedEd25519Decision === "boolean") return cachedEd25519Decision; else return await cachedEd25519Decision; } function assertDigestCapabilityIsAvailable() { assertIsSecureContext(); if (typeof _crypto === "undefined" || typeof _crypto.subtle?.digest !== "function") throw new Error("SubtleCrypto.digest is not available"); } async function assertKeyGenerationIsAvailable() { assertIsSecureContext(); if (typeof _crypto === "undefined" || typeof _crypto.subtle?.generateKey !== "function") throw new Error("SubtleCrypto.generateKey is not available"); if (!await isEd25519CurveSupported(_crypto.subtle)) throw new Error("Ed25519 curve is not supported"); } function assertKeyExporterIsAvailable() { assertIsSecureContext(); if (typeof _crypto === "undefined" || typeof _crypto.subtle?.exportKey !== "function") throw new Error("SubtleCrypto.exportKey is not available"); } function assertSigningCapabilityIsAvailable() { assertIsSecureContext(); if (typeof _crypto === "undefined" || typeof _crypto.subtle?.sign !== "function") throw new Error("SubtleCrypto.sign is not available"); } function assertVerificationCapabilityIsAvailable() { assertIsSecureContext(); if (typeof _crypto === "undefined" || typeof _crypto.subtle?.verify !== "function") throw new Error("SubtleCrypto.verify is not available"); } function assertPRNGIsAvailable() { if (typeof _crypto === "undefined" || typeof _crypto.getRandomValues !== "function") throw new Error("Crypto.getRandomValues is not available"); } /** * Asserts that a given byte array is not empty. */ function assertByteArrayIsNotEmptyForCodec(codecDescription, bytes, offset = 0) { if (bytes.length - offset <= 0) throw new Error(`Empty byte array for ${codecDescription}`); } /** * Asserts that a given byte array has enough bytes to decode. */ function assertByteArrayHasEnoughBytesForCodec(codecDescription, expected, bytes, offset = 0) { const bytesLength = bytes.length - offset; if (bytesLength < expected) throw new Error(`Not enough bytes to decode ${codecDescription}. Expected: ${expected}, Actual: ${bytesLength}`); } /** * Asserts that a given offset is within the byte array bounds. * This range is between 0 and the byte array length and is inclusive. * An offset equals to the byte array length is considered a valid offset * as it allows the post-offset of codecs to signal the end of the byte array. */ function assertByteArrayOffsetIsNotOutOfRange(codecDescription, offset, bytesLength) { if (offset < 0 || offset > bytesLength) throw new Error(`Offset is out of range for ${codecDescription}: ${offset}`); } /** * Asserts that a given string matches a given alphabet. */ function assertValidBaseString(alphabet$3, testValue, givenValue = testValue) { if (!testValue.match(new RegExp(`^[${alphabet$3}]*$`))) throw new Error(`Invalid base${alphabet$3.length} string: ${givenValue}`); } //#endregion //#region src/codecs/core.ts /** * Get the encoded size of a given value in bytes. */ function getEncodedSize(value, encoder) { return "fixedSize" in encoder ? encoder.fixedSize : encoder.getSizeFromValue(value); } function createEncoder(encoder) { return Object.freeze({ ...encoder, encode: (value) => { const bytes = new Uint8Array(getEncodedSize(value, encoder)); encoder.write(value, bytes, 0); return bytes; } }); } function createDecoder(decoder) { return Object.freeze({ ...decoder, decode: (bytes, offset = 0) => decoder.read(bytes, offset)[0] }); } function createCodec(codec) { return Object.freeze({ ...codec, decode: (bytes, offset = 0) => codec.read(bytes, offset)[0], encode: (value) => { const bytes = new Uint8Array(getEncodedSize(value, codec)); codec.write(value, bytes, 0); return bytes; } }); } function isFixedSize(codec) { return "fixedSize" in codec && typeof codec.fixedSize === "number"; } function assertIsFixedSize(codec) { if (!isFixedSize(codec)) throw new Error("expected a fixed size codec"); } function isVariableSize(codec) { return !isFixedSize(codec); } function assertIsVariableSize(codec) { if (!isVariableSize(codec)) throw new Error("expected a variable size codec"); } function transformEncoder(encoder, unmap) { return createEncoder({ ...isVariableSize(encoder) ? { ...encoder, getSizeFromValue: (value) => encoder.getSizeFromValue(unmap(value)) } : encoder, write: (value, bytes, offset) => encoder.write(unmap(value), bytes, offset) }); } function transformDecoder(decoder, map) { return createDecoder({ ...decoder, read: (bytes, offset) => { const [value, newOffset] = decoder.read(bytes, offset); return [map(value, bytes, offset), newOffset]; } }); } function combineCodec(encoder, decoder) { if (isFixedSize(encoder) !== isFixedSize(decoder)) throw new Error("encoder and decoder size compatibility mismatch"); if (isFixedSize(encoder) && isFixedSize(decoder) && encoder.fixedSize !== decoder.fixedSize) throw new Error(`encoder and decoder fixed size mismatch ${encoder.fixedSize} !== ${decoder.fixedSize}`); if (!isFixedSize(encoder) && !isFixedSize(decoder) && encoder.maxSize !== decoder.maxSize) throw new Error(`encoder and decoder max size mismatch ${encoder.maxSize} !== ${decoder.maxSize}`); return { ...decoder, ...encoder, decode: decoder.decode, encode: encoder.encode, read: decoder.read, write: encoder.write }; } function transformCodec(codec, unmap, map) { return createCodec({ ...transformEncoder(codec, unmap), read: map ? transformDecoder(codec, map).read : codec.read }); } /** * Concatenates an array of `Uint8Array`s into a single `Uint8Array`. * Reuses the original byte array when applicable. */ const mergeBytes = (byteArrays) => { const nonEmptyByteArrays = byteArrays.filter((arr) => arr.length); if (nonEmptyByteArrays.length === 0) return byteArrays.length ? byteArrays[0] : new Uint8Array(); if (nonEmptyByteArrays.length === 1) return nonEmptyByteArrays[0]; const totalLength = nonEmptyByteArrays.reduce((total, arr) => total + arr.length, 0); const result = new Uint8Array(totalLength); let offset = 0; nonEmptyByteArrays.forEach((arr) => { result.set(arr, offset); offset += arr.length; }); return result; }; /** * Pads a `Uint8Array` with zeroes to the specified length. * If the array is longer than the specified length, it is returned as-is. */ const padBytes = (bytes, length) => { if (bytes.length >= length) return bytes; const paddedBytes = new Uint8Array(length).fill(0); paddedBytes.set(bytes); return paddedBytes; }; /** * Fixes a `Uint8Array` to the specified length. * If the array is longer than the specified length, it is truncated. * If the array is shorter than the specified length, it is padded with zeroes. */ const fixBytes = (bytes, length) => padBytes(bytes.length <= length ? bytes : bytes.slice(0, length), length); /** * Returns true if and only if the provided `data` byte array contains * the provided `bytes` byte array at the specified `offset`. */ function containsBytes(data, bytes, offset) { const slice = offset === 0 && data.length === bytes.length ? data : data.slice(offset, offset + bytes.length); if (slice.length !== bytes.length) return false; return bytes.every((b, i) => b === slice[i]); } /** * Creates a fixed-size encoder from a given encoder. * * @param encoder - The encoder to wrap into a fixed-size encoder. * @param fixedBytes - The fixed number of bytes to write. */ function fixEncoderSize(encoder, fixedBytes) { return createEncoder({ fixedSize: fixedBytes, write: (value, bytes, offset) => { const variableByteArray = encoder.encode(value); const fixedByteArray = variableByteArray.length > fixedBytes ? variableByteArray.slice(0, fixedBytes) : variableByteArray; bytes.set(fixedByteArray, offset); return offset + fixedBytes; } }); } /** * Creates a fixed-size decoder from a given decoder. * * @param decoder - The decoder to wrap into a fixed-size decoder. * @param fixedBytes - The fixed number of bytes to read. */ function fixDecoderSize(decoder, fixedBytes) { return createDecoder({ fixedSize: fixedBytes, read: (bytes, offset) => { assertByteArrayHasEnoughBytesForCodec("fixCodecSize", fixedBytes, bytes, offset); if (offset > 0 || bytes.length > fixedBytes) bytes = bytes.slice(offset, offset + fixedBytes); if (isFixedSize(decoder)) bytes = fixBytes(bytes, decoder.fixedSize); const [value] = decoder.read(bytes, 0); return [value, offset + fixedBytes]; } }); } /** * Creates a fixed-size codec from a given codec. * * @param codec - The codec to wrap into a fixed-size codec. * @param fixedBytes - The fixed number of bytes to read/write. */ function fixCodecSize(codec, fixedBytes) { return combineCodec(fixEncoderSize(codec, fixedBytes), fixDecoderSize(codec, fixedBytes)); } //#endregion //#region src/codecs/strings/base16.ts var HexC = /* @__PURE__ */ function(HexC$1) { HexC$1[HexC$1["ZERO"] = 48] = "ZERO"; HexC$1[HexC$1["NINE"] = 57] = "NINE"; HexC$1[HexC$1["A_UP"] = 65] = "A_UP"; HexC$1[HexC$1["F_UP"] = 70] = "F_UP"; HexC$1[HexC$1["A_LO"] = 97] = "A_LO"; HexC$1[HexC$1["F_LO"] = 102] = "F_LO"; return HexC$1; }(HexC || {}); function charCodeToBase16(char) { if (char >= HexC.ZERO && char <= HexC.NINE) return char - HexC.ZERO; if (char >= HexC.A_UP && char <= HexC.F_UP) return char - (HexC.A_UP - 10); if (char >= HexC.A_LO && char <= HexC.F_LO) return char - (HexC.A_LO - 10); } /** Encodes strings in base16. */ function getBase16Encoder() { return createEncoder({ getSizeFromValue: (value) => Math.ceil(value.length / 2), write(value, bytes, offset) { const len = value.length; const al = len / 2; if (len === 1) { const c = value.charCodeAt(0); const n = charCodeToBase16(c); if (n === void 0) throw new Error(`Invalid string for base16: ${value}`); bytes.set([n], offset); return 1 + offset; } const hexBytes = new Uint8Array(al); for (let i = 0, j = 0; i < al; i++) { const c1 = value.charCodeAt(j++); const c2 = value.charCodeAt(j++); const n1 = charCodeToBase16(c1); const n2 = charCodeToBase16(c2); if (n1 === void 0 || n2 === void 0 && !Number.isNaN(c2)) throw new Error(`Invalid string for base16: ${value}`); hexBytes[i] = !Number.isNaN(c2) ? n1 << 4 | (n2 ?? 0) : n1; } bytes.set(hexBytes, offset); return hexBytes.length + offset; } }); } /** Decodes strings in base16. */ function getBase16Decoder() { return createDecoder({ read(bytes, offset) { const value = bytes.slice(offset).reduce((str, byte) => str + byte.toString(16).padStart(2, "0"), ""); return [value, bytes.length]; } }); } /** Encodes and decodes strings in base16. */ function getBase16Codec() { return combineCodec(getBase16Encoder(), getBase16Decoder()); } const base16 = getBase16Codec(); //#endregion //#region src/keys/signatures.ts let base16Encoder; function assertIsSignature(putativeSignature) { if (!base16Encoder) base16Encoder = getBase16Encoder(); if (putativeSignature.length < 64 || putativeSignature.length > 88) throw new Error(`Invalid signature length: ${putativeSignature.length} out of range`); const bytes = base16Encoder.encode(putativeSignature); const numBytes = bytes.byteLength; if (numBytes !== 64) throw new Error(`Invalid signature length: ${numBytes} bytes`); } function isSignature(putativeSignature) { if (!base16Encoder) base16Encoder = getBase16Encoder(); if (putativeSignature.length < 64 || putativeSignature.length > 88) return false; const bytes = base16Encoder.encode(putativeSignature); const numBytes = bytes.byteLength; if (numBytes !== 64) return false; return true; } async function signBytes(key, data) { assertSigningCapabilityIsAvailable(); const signedData = await crypto.subtle.sign("Ed25519", key, data); return new Uint8Array(signedData); } function signature(putativeSignature) { assertIsSignature(putativeSignature); return putativeSignature; } async function verifySignature(key, signature$1, data) { assertVerificationCapabilityIsAvailable(); return await crypto.subtle.verify("Ed25519", key, signature$1, data); } //#endregion //#region src/keys/keys.ts function addPkcs8Header(bytes) { return new Uint8Array([ 48, 46, 2, 1, 0, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32, ...bytes ]); } async function createPrivateKeyFromBytes(bytes, extractable) { const actualLength = bytes.byteLength; if (actualLength !== 32) throw new Error(`Invalid private key length: ${actualLength}`); const privateKeyBytesPkcs8 = addPkcs8Header(bytes); return _crypto.subtle.importKey("pkcs8", privateKeyBytesPkcs8, "Ed25519", extractable ?? false, ["sign"]); } async function getPublicKeyFromPrivateKey(privateKey, extractable = false) { assertKeyExporterIsAvailable(); if (privateKey.extractable === false) throw new Error(`Private key ${privateKey} is not extractable`); const jwk = await _crypto.subtle.exportKey("jwk", privateKey); return await _crypto.subtle.importKey("jwk", { crv: "Ed25519", ext: extractable, key_ops: ["verify"], kty: "OKP", x: jwk.x }, "Ed25519", extractable, ["verify"]); } async function generateKeyPair() { await assertKeyGenerationIsAvailable(); const keyPair = await _crypto.subtle.generateKey("Ed25519", false, ["sign", "verify"]); return keyPair; } async function generateExtractableKeyPair() { await assertKeyGenerationIsAvailable(); const keyPair = await _crypto.subtle.generateKey("Ed25519", true, ["sign", "verify"]); return keyPair; } async function createKeyPairFromBytes(bytes, extractable) { assertPRNGIsAvailable(); if (bytes.byteLength !== 64) throw new Error(`invalid key pair length: ${bytes.byteLength}`); const [publicKey, privateKey] = await Promise.all([_crypto.subtle.importKey("raw", bytes.slice(32), "Ed25519", true, ["verify"]), createPrivateKeyFromBytes(bytes.slice(0, 32), extractable)]); const randomBytes = new Uint8Array(32); _crypto.getRandomValues(randomBytes); const signedData = await signBytes(privateKey, randomBytes); const isValid = await verifySignature(publicKey, signedData, randomBytes); if (!isValid) throw new Error("public key must match private key"); return { privateKey, publicKey }; } async function createKeyPairFromPrivateKeyBytes(bytes, extractable = false) { const privateKeyPromise = createPrivateKeyFromBytes(bytes, extractable); const [publicKey, privateKey] = await Promise.all([(extractable ? privateKeyPromise : createPrivateKeyFromBytes(bytes, true)).then(async (privateKey$1) => await getPublicKeyFromPrivateKey(privateKey$1, true)), privateKeyPromise]); return { privateKey, publicKey }; } //#endregion //#region src/address.ts function isAddress(putativeAddress) { if (putativeAddress.length < 32 || putativeAddress.length > 44) return false; const bytes = base16.encode(putativeAddress); const numBytes = bytes.byteLength; if (numBytes !== 32) return false; return true; } function assertIsAddress(putativeAddress) { if (putativeAddress.length < 32 || putativeAddress.length > 44) throw new Error(`Invalid address length: ${putativeAddress.length} out of range`); const bytes = base16.encode(putativeAddress); const numBytes = bytes.byteLength; if (numBytes !== 32) throw new Error(`Invalid address length: ${numBytes} bytes`); } function address(putativeAddress) { assertIsAddress(putativeAddress); return putativeAddress; } let addressEncoder; let addressDecoder; let addressCodec; function getAddressEncoder() { return addressEncoder ??= transformEncoder(fixEncoderSize(base16, 32), (putativeAddress) => address(putativeAddress)); } function getAddressDecoder() { return addressDecoder ??= fixDecoderSize(base16, 32); } function getAddressCodec() { return addressCodec ??= combineCodec(getAddressEncoder(), getAddressDecoder()); } function getAddressComparator() { return new Intl.Collator("en", { caseFirst: "lower", ignorePunctuation: false, localeMatcher: "best fit", numeric: false, sensitivity: "variant", usage: "sort" }).compare; } async function exportBase16Key(key) { assertKeyExporterIsAvailable(); if (!key.extractable || key.algorithm.name !== "Ed25519") throw new Error(`Key is not extractable or has an invalid algorithm: ${key.algorithm.name}`); const keyBytes = await crypto.subtle.exportKey("raw", key); return getAddressDecoder().decode(new Uint8Array(keyBytes)); } function isKAccount(putativeAccount) { return putativeAccount.startsWith("k:") && isAddress(putativeAccount.slice(2)); } function assertIsKAccount(putativeAccount) { if (!isKAccount(putativeAccount)) throw new Error(`Invalid account: ${putativeAccount}`); } function kAccount(putativeAccount) { assertIsKAccount(putativeAccount); return putativeAccount; } async function getKAccountFromPublicKey(publicKey) { const address$1 = await exportBase16Key(publicKey); return kAccount(`k:${address$1}`); } async function genKeyPair() { const keyPair = await generateExtractableKeyPair(); return { publicKey: await exportBase16Key(keyPair.publicKey), privateKey: await exportBase16Key(keyPair.privateKey) }; } //#endregion //#region src/codecs/strings/baseX.ts /** * Encodes a string using a custom alphabet by dividing * by the base and handling leading zeroes. * @see {@link getBaseXCodec} for a more detailed description. */ const getBaseXEncoder = (alphabet$3) => { return createEncoder({ getSizeFromValue: (value) => { const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet$3[0]); if (!tailChars) return value.length; const base10Number = getBigIntFromBaseX(tailChars, alphabet$3); return leadingZeroes.length + Math.ceil(base10Number.toString(16).length / 2); }, write(value, bytes, offset) { assertValidBaseString(alphabet$3, value); if (value === "") return offset; const [leadingZeroes, tailChars] = partitionLeadingZeroes(value, alphabet$3[0]); if (!tailChars) { bytes.set(new Uint8Array(leadingZeroes.length).fill(0), offset); return offset + leadingZeroes.length; } let base10Number = getBigIntFromBaseX(tailChars, alphabet$3); const tailBytes = []; while (base10Number > 0n) { tailBytes.unshift(Number(base10Number % 256n)); base10Number /= 256n; } const bytesToAdd = [...Array(leadingZeroes.length).fill(0), ...tailBytes]; bytes.set(bytesToAdd, offset); return offset + bytesToAdd.length; } }); }; /** * Decodes a string using a custom alphabet by dividing * by the base and handling leading zeroes. * @see {@link getBaseXCodec} for a more detailed description. */ const getBaseXDecoder = (alphabet$3) => { return createDecoder({ read(rawBytes, offset) { const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset); if (bytes.length === 0) return ["", 0]; let trailIndex = bytes.findIndex((n) => n !== 0); trailIndex = trailIndex === -1 ? bytes.length : trailIndex; const leadingZeroes = alphabet$3[0].repeat(trailIndex); if (trailIndex === bytes.length) return [leadingZeroes, rawBytes.length]; const base10Number = bytes.slice(trailIndex).reduce((sum, byte) => sum * 256n + BigInt(byte), 0n); const tailChars = getBaseXFromBigInt(base10Number, alphabet$3); return [leadingZeroes + tailChars, rawBytes.length]; } }); }; /** * A string codec that requires a custom alphabet and uses * the length of that alphabet as the base. It then divides * the input by the base as many times as necessary to get * the output. It also supports leading zeroes by using the * first character of the alphabet as the zero character. * * This can be used to create codecs such as base10 or base58. */ const getBaseXCodec = (alphabet$3) => combineCodec(getBaseXEncoder(alphabet$3), getBaseXDecoder(alphabet$3)); function partitionLeadingZeroes(value, zeroCharacter) { const [leadingZeros, tailChars] = value.split(new RegExp(`((?!${zeroCharacter}).*)`)); return [leadingZeros, tailChars]; } function getBigIntFromBaseX(value, alphabet$3) { const base = BigInt(alphabet$3.length); let sum = 0n; for (const char of value) { sum *= base; sum += BigInt(alphabet$3.indexOf(char)); } return sum; } function getBaseXFromBigInt(value, alphabet$3) { const base = BigInt(alphabet$3.length); const tailChars = []; while (value > 0n) { tailChars.unshift(alphabet$3[Number(value % base)]); value /= base; } return tailChars.join(""); } //#endregion //#region src/codecs/strings/base10.ts const alphabet$2 = "0123456789"; /** Encodes strings in base10. */ function getBase10Encoder() { return getBaseXEncoder(alphabet$2); } /** Decodes strings in base10. */ function getBase10Decoder() { return getBaseXDecoder(alphabet$2); } /** Encodes and decodes strings in base10. */ function getBase10Codec() { return getBaseXCodec(alphabet$2); } const base10 = getBase10Codec(); //#endregion //#region src/codecs/strings/base58.ts const alphabet$1 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; /** Encodes strings in base58. */ function getBase58Encoder() { return getBaseXEncoder(alphabet$1); } /** Decodes strings in base58. */ function getBase58Decoder() { return getBaseXDecoder(alphabet$1); } /** Encodes and decodes strings in base58. */ function getBase58Codec() { return getBaseXCodec(alphabet$1); } const base58 = getBase58Codec(); //#endregion //#region src/codecs/strings/baseX-reslice.ts /** * Encodes a string using a custom alphabet by reslicing the bits of the byte array. * @see {@link getBaseXResliceCodec} for a more detailed description. */ function getBaseXResliceEncoder(alphabet$3, bits) { return createEncoder({ getSizeFromValue: (value) => Math.floor(value.length * bits / 8), write(value, bytes, offset) { assertValidBaseString(alphabet$3, value); if (value === "") return offset; const charIndices = [...value].map((c) => alphabet$3.indexOf(c)); const reslicedBytes = reslice(charIndices, bits, 8, false); bytes.set(reslicedBytes, offset); return reslicedBytes.length + offset; } }); } /** * Decodes a string using a custom alphabet by reslicing the bits of the byte array. * @see {@link getBaseXResliceCodec} for a more detailed description. */ function getBaseXResliceDecoder(alphabet$3, bits) { return createDecoder({ read(rawBytes, offset = 0) { const bytes = offset === 0 ? rawBytes : rawBytes.slice(offset); if (bytes.length === 0) return ["", rawBytes.length]; const charIndices = reslice([...bytes], 8, bits, true); return [charIndices.map((i) => alphabet$3[i]).join(""), rawBytes.length]; } }); } /** * A string serializer that reslices bytes into custom chunks * of bits that are then mapped to a custom alphabet. * * This can be used to create serializers whose alphabet * is a power of 2 such as base16 or base64. */ function getBaseXResliceCodec(alphabet$3, bits) { return combineCodec(getBaseXResliceEncoder(alphabet$3, bits), getBaseXResliceDecoder(alphabet$3, bits)); } /** Helper function to reslice the bits inside bytes. */ function reslice(input, inputBits, outputBits, useRemainder) { const output = []; let accumulator = 0; let bitsInAccumulator = 0; const mask = (1 << outputBits) - 1; for (const value of input) { accumulator = accumulator << inputBits | value; bitsInAccumulator += inputBits; while (bitsInAccumulator >= outputBits) { bitsInAccumulator -= outputBits; output.push(accumulator >> bitsInAccumulator & mask); } } if (useRemainder && bitsInAccumulator > 0) output.push(accumulator << outputBits - bitsInAccumulator & mask); return output; } //#endregion //#region src/codecs/strings/base64.ts const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** Encodes strings in base64. */ function getBase64Encoder() { return createEncoder({ getSizeFromValue: (value) => Buffer.from(value, "base64").length, write(value, bytes, offset) { assertValidBaseString(alphabet, value.replace(/=/g, "")); const buffer = Buffer.from(value, "base64"); bytes.set(buffer, offset); return buffer.length + offset; } }); } /** Decodes strings in base64. */ function getBase64Decoder() { return createDecoder({ read: (bytes, offset = 0) => [Buffer.from(bytes.buffer, offset).toString("base64"), bytes.length] }); } /** Encodes and decodes strings in base64. */ function getBase64Codec() { return combineCodec(getBase64Encoder(), getBase64Decoder()); } //#endregion //#region src/codecs/strings/base64-url.ts /** Encodes strings in base64url. */ function getBase64UrlEncoder() { return createEncoder({ getSizeFromValue: (value) => Buffer.from(value, "base64url").length, write(value, bytes, offset) { const buffer = Buffer.from(value, "base64url"); bytes.set(buffer, offset); return buffer.length + offset; } }); } /** Decodes strings in base64url. */ function getBase64UrlDecoder() { return createDecoder({ read: (bytes, offset = 0) => [Buffer.from(bytes.slice(offset)).toString("base64url"), bytes.length] }); } /** Encodes and decodes strings in base64url. */ function getBase64UrlCodec() { return combineCodec(getBase64UrlEncoder(), getBase64UrlDecoder()); } const base64Url = getBase64UrlCodec(); //#endregion //#region src/codecs/strings/null.ts /**Removes null characters from a string. */ function removeNullCharacters(value) { return value.replace(/\u0000/g, ""); } /** Pads a string with null characters at the end. */ function padNullCharacters(value, chars) { return value.padEnd(chars, "\0"); } //#endregion //#region src/codecs/text.ts const TextDecoder = globalThis.TextDecoder; const TextEncoder = globalThis.TextEncoder; //#endregion //#region src/codecs/strings/utf-8.ts /** Encodes UTF-8 strings using the native `TextEncoder` API. */ function getUtf8Encoder() { let textEncoder; return createEncoder({ getSizeFromValue: (value) => (textEncoder ||= new TextEncoder()).encode(value).length, write: (value, bytes, offset) => { const bytesToAdd = (textEncoder ||= new TextEncoder()).encode(value); bytes.set(bytesToAdd, offset); return offset + bytesToAdd.length; } }); } /** Decodes UTF-8 strings using the native `TextDecoder` API. */ function getUtf8Decoder() { let textDecoder; return createDecoder({ read(bytes, offset) { const value = (textDecoder ||= new TextDecoder()).decode(bytes.slice(offset)); return [removeNullCharacters(value), bytes.length]; } }); } /** Encodes and decodes UTF-8 strings using the native `TextEncoder` and `TextDecoder` API. */ function getUtf8Codec() { return combineCodec(getUtf8Encoder(), getUtf8Decoder()); } const utf8 = getUtf8Codec(); //#endregion //#region src/hash/base64-url-blake2b.ts function blake2bBase64Url(input) { return base64Url.decode(blake2b(input, void 0, 32)); } //#endregion //#region src/stringify.ts const objToString = Object.prototype.toString; const objKeys = Object.keys || function(obj) { const keys = []; for (const name in obj) keys.push(name); return keys; }; function stringify(val, isArrayProp) { let i, max, str, keys, key, propVal, toStr; if (val === true) return "true"; if (val === false) return "false"; switch (typeof val) { case "object": if (val === null) return null; else if ("toJSON" in val && typeof val.toJSON === "function") return stringify(val.toJSON(), isArrayProp); else { toStr = objToString.call(val); if (toStr === "[object Array]") { str = "["; max = val.length - 1; for (i = 0; i < max; i++) str += stringify(val[i], true) + ","; if (max > -1) str += stringify(val[i], true); return str + "]"; } else if (toStr === "[object Object]") { keys = objKeys(val).sort(); max = keys.length; str = ""; i = 0; while (i < max) { key = keys[i]; propVal = stringify(val[key], false); if (propVal !== void 0) { if (str) str += ","; str += JSON.stringify(key) + ":" + propVal; } i++; } return "{" + str + "}"; } else return JSON.stringify(val); } case "function": case "undefined": return isArrayProp ? null : void 0; case "bigint": return `${val.toString()}n`; case "string": return JSON.stringify(val); default: return isFinite(val) ? val : null; } } function fastStableStringify(val) { const returnVal = stringify(val, false); if (returnVal !== void 0) return "" + returnVal; } //#endregion export { TextDecoder, TextEncoder, address, assertByteArrayHasEnoughBytesForCodec, assertByteArrayIsNotEmptyForCodec, assertByteArrayOffsetIsNotOutOfRange, assertDigestCapabilityIsAvailable, assertIsAddress, assertIsFixedSize, assertIsKAccount, assertIsSignature, assertIsVariableSize, assertKeyExporterIsAvailable, assertKeyGenerationIsAvailable, assertPRNGIsAvailable, assertSigningCapabilityIsAvailable, assertValidBaseString, assertVerificationCapabilityIsAvailable, base10, base16, base58, base64Url, blake2b, blake2bBase64Url, combineCodec, containsBytes, createCodec, createDecoder, createEncoder, createKeyPairFromBytes, createKeyPairFromPrivateKeyBytes, createPrivateKeyFromBytes, exportBase16Key, fastStableStringify, fixBytes, fixCodecSize, fixDecoderSize, fixEncoderSize, genKeyPair, generateExtractableKeyPair, generateKeyPair, getAddressCodec, getAddressComparator, getAddressDecoder, getAddressEncoder, getBase10Codec, getBase10Decoder, getBase10Encoder, getBase16Codec, getBase16Decoder, getBase16Encoder, getBase58Codec, getBase58Decoder, getBase58Encoder, getBase64Codec, getBase64Decoder, getBase64Encoder, getBase64UrlCodec, getBase64UrlDecoder, getBase64UrlEncoder, getBaseXCodec, getBaseXDecoder, getBaseXEncoder, getBaseXResliceCodec, getBaseXResliceDecoder, getBaseXResliceEncoder, getEncodedSize, getKAccountFromPublicKey, getPublicKeyFromPrivateKey, getUtf8Codec, getUtf8Decoder, getUtf8Encoder, isAddress, isFixedSize, isKAccount, isSignature, isVariableSize, kAccount, mergeBytes, padBytes, padNullCharacters, removeNullCharacters, signBytes, signature, transformCodec, transformDecoder, transformEncoder, utf8, verifySignature }; //# sourceMappingURL=index.node.mjs.map