@pact-toolbox/crypto
Version:
935 lines (915 loc) • 34.3 kB
JavaScript
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
const node_crypto = __toESM(require("node:crypto"));
const blakejs = __toESM(require("blakejs"));
//#region ../../node_modules/.pnpm/uncrypto@0.1.3/node_modules/uncrypto/dist/crypto.node.mjs
const subtle = node_crypto.default.webcrypto?.subtle || {};
const randomUUID = () => {
return node_crypto.default.randomUUID();
};
const getRandomValues = (array) => {
return node_crypto.default.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((0, blakejs.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
exports.TextDecoder = TextDecoder;
exports.TextEncoder = TextEncoder;
exports.address = address;
exports.assertByteArrayHasEnoughBytesForCodec = assertByteArrayHasEnoughBytesForCodec;
exports.assertByteArrayIsNotEmptyForCodec = assertByteArrayIsNotEmptyForCodec;
exports.assertByteArrayOffsetIsNotOutOfRange = assertByteArrayOffsetIsNotOutOfRange;
exports.assertDigestCapabilityIsAvailable = assertDigestCapabilityIsAvailable;
exports.assertIsAddress = assertIsAddress;
exports.assertIsFixedSize = assertIsFixedSize;
exports.assertIsKAccount = assertIsKAccount;
exports.assertIsSignature = assertIsSignature;
exports.assertIsVariableSize = assertIsVariableSize;
exports.assertKeyExporterIsAvailable = assertKeyExporterIsAvailable;
exports.assertKeyGenerationIsAvailable = assertKeyGenerationIsAvailable;
exports.assertPRNGIsAvailable = assertPRNGIsAvailable;
exports.assertSigningCapabilityIsAvailable = assertSigningCapabilityIsAvailable;
exports.assertValidBaseString = assertValidBaseString;
exports.assertVerificationCapabilityIsAvailable = assertVerificationCapabilityIsAvailable;
exports.base10 = base10;
exports.base16 = base16;
exports.base58 = base58;
exports.base64Url = base64Url;
Object.defineProperty(exports, 'blake2b', {
enumerable: true,
get: function () {
return blakejs.blake2b;
}
});
exports.blake2bBase64Url = blake2bBase64Url;
exports.combineCodec = combineCodec;
exports.containsBytes = containsBytes;
exports.createCodec = createCodec;
exports.createDecoder = createDecoder;
exports.createEncoder = createEncoder;
exports.createKeyPairFromBytes = createKeyPairFromBytes;
exports.createKeyPairFromPrivateKeyBytes = createKeyPairFromPrivateKeyBytes;
exports.createPrivateKeyFromBytes = createPrivateKeyFromBytes;
exports.exportBase16Key = exportBase16Key;
exports.fastStableStringify = fastStableStringify;
exports.fixBytes = fixBytes;
exports.fixCodecSize = fixCodecSize;
exports.fixDecoderSize = fixDecoderSize;
exports.fixEncoderSize = fixEncoderSize;
exports.genKeyPair = genKeyPair;
exports.generateExtractableKeyPair = generateExtractableKeyPair;
exports.generateKeyPair = generateKeyPair;
exports.getAddressCodec = getAddressCodec;
exports.getAddressComparator = getAddressComparator;
exports.getAddressDecoder = getAddressDecoder;
exports.getAddressEncoder = getAddressEncoder;
exports.getBase10Codec = getBase10Codec;
exports.getBase10Decoder = getBase10Decoder;
exports.getBase10Encoder = getBase10Encoder;
exports.getBase16Codec = getBase16Codec;
exports.getBase16Decoder = getBase16Decoder;
exports.getBase16Encoder = getBase16Encoder;
exports.getBase58Codec = getBase58Codec;
exports.getBase58Decoder = getBase58Decoder;
exports.getBase58Encoder = getBase58Encoder;
exports.getBase64Codec = getBase64Codec;
exports.getBase64Decoder = getBase64Decoder;
exports.getBase64Encoder = getBase64Encoder;
exports.getBase64UrlCodec = getBase64UrlCodec;
exports.getBase64UrlDecoder = getBase64UrlDecoder;
exports.getBase64UrlEncoder = getBase64UrlEncoder;
exports.getBaseXCodec = getBaseXCodec;
exports.getBaseXDecoder = getBaseXDecoder;
exports.getBaseXEncoder = getBaseXEncoder;
exports.getBaseXResliceCodec = getBaseXResliceCodec;
exports.getBaseXResliceDecoder = getBaseXResliceDecoder;
exports.getBaseXResliceEncoder = getBaseXResliceEncoder;
exports.getEncodedSize = getEncodedSize;
exports.getKAccountFromPublicKey = getKAccountFromPublicKey;
exports.getPublicKeyFromPrivateKey = getPublicKeyFromPrivateKey;
exports.getUtf8Codec = getUtf8Codec;
exports.getUtf8Decoder = getUtf8Decoder;
exports.getUtf8Encoder = getUtf8Encoder;
exports.isAddress = isAddress;
exports.isFixedSize = isFixedSize;
exports.isKAccount = isKAccount;
exports.isSignature = isSignature;
exports.isVariableSize = isVariableSize;
exports.kAccount = kAccount;
exports.mergeBytes = mergeBytes;
exports.padBytes = padBytes;
exports.padNullCharacters = padNullCharacters;
exports.removeNullCharacters = removeNullCharacters;
exports.signBytes = signBytes;
exports.signature = signature;
exports.transformCodec = transformCodec;
exports.transformDecoder = transformDecoder;
exports.transformEncoder = transformEncoder;
exports.utf8 = utf8;
exports.verifySignature = verifySignature;
//# sourceMappingURL=index.node.cjs.map