@taquito/sapling 24.3.0-beta.1 → 24.3.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/SAPLING_PARAMS_PROVENANCE.md +24 -0
- package/dist/lib/sapling-keys/helpers.js +3 -2
- package/dist/lib/sapling-keys/in-memory-proving-key.js +1 -1
- package/dist/lib/sapling-keys/in-memory-spending-key.js +2 -2
- package/dist/lib/sapling-keys/in-memory-viewing-key.js +1 -1
- package/dist/lib/sapling-module-wrapper.js +12 -4
- package/dist/lib/sapling-state/sapling-state.js +3 -2
- package/dist/lib/sapling-tx-builder/sapling-transactions-builder.js +6 -5
- package/dist/lib/sapling-tx-viewer/sapling-transaction-viewer.js +3 -2
- package/dist/lib/taquito-sapling.js +6 -5
- package/dist/lib/types.js +2 -0
- package/dist/lib/version.js +2 -2
- package/dist/taquito-sapling.es6.js +702 -19
- package/dist/taquito-sapling.es6.js.map +1 -1
- package/dist/taquito-sapling.umd.js +703 -18
- package/dist/taquito-sapling.umd.js.map +1 -1
- package/dist/types/node_modules/@scure/base/index.d.ts +293 -0
- package/dist/types/sapling-module-wrapper.d.ts +1 -1
- package/dist/types/sapling-state/sapling-state.d.ts +4 -1
- package/dist/types/sapling-tx-builder/sapling-transactions-builder.d.ts +6 -3
- package/dist/types/sapling-tx-viewer/sapling-transaction-viewer.d.ts +4 -1
- package/dist/types/src/version.d.ts +4 -0
- package/dist/types/types.d.ts +4 -1
- package/package.json +21 -46
- package/saplingOutputParams.js +13 -0
- package/fetch-sapling-params.js +0 -39
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('bignumber.js'), require('@taquito/taquito'), require('@taquito/utils'), require('@taquito/core'), require('@
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports', 'bignumber.js', '@taquito/taquito', '@taquito/utils', '@taquito/core', '@
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.taquitoSapling = {}, global.BigNumber, global.taquito, global.utils, global.core, global.sapling, global.blake, global.nacl, global.
|
|
5
|
-
})(this, (function (exports,
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('bignumber.js'), require('@taquito/taquito'), require('@taquito/utils'), require('@taquito/core'), require('@taquito/sapling-wasm'), require('blakejs'), require('@stablelib/nacl'), require('typedarray-to-buffer')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'bignumber.js', '@taquito/taquito', '@taquito/utils', '@taquito/core', '@taquito/sapling-wasm', 'blakejs', '@stablelib/nacl', 'typedarray-to-buffer'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.taquitoSapling = {}, global.BigNumber, global.taquito, global.utils, global.core, global.sapling, global.blake, global.nacl, global.toBuffer));
|
|
5
|
+
})(this, (function (exports, BigNumberJs, taquito, utils, core, sapling, blake, nacl, toBuffer) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopNamespaceDefault(e) {
|
|
8
8
|
var n = Object.create(null);
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
var sapling__namespace = /*#__PURE__*/_interopNamespaceDefault(sapling);
|
|
25
|
-
var bip39__namespace = /*#__PURE__*/_interopNamespaceDefault(bip39);
|
|
26
25
|
|
|
27
26
|
/******************************************************************************
|
|
28
27
|
Copyright (c) Microsoft Corporation.
|
|
@@ -149,7 +148,7 @@
|
|
|
149
148
|
};
|
|
150
149
|
}
|
|
151
150
|
function convertValueToBigNumber(value) {
|
|
152
|
-
return new
|
|
151
|
+
return new BigNumberJs(Buffer.from(value).toString('hex'), 16);
|
|
153
152
|
}
|
|
154
153
|
function bufToUint8Array(buffer) {
|
|
155
154
|
return new Uint8Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Uint8Array.BYTES_PER_ELEMENT);
|
|
@@ -242,7 +241,7 @@
|
|
|
242
241
|
const encodedMemo = Buffer.from(utils.stringToBytes(txPlainText.memo).padEnd(txPlainText.memoSize, '0'), 'hex');
|
|
243
242
|
return Buffer.concat([
|
|
244
243
|
txPlainText.diversifier,
|
|
245
|
-
utils.toHexBuf(new
|
|
244
|
+
utils.toHexBuf(new BigNumberJs(txPlainText.amount), 64),
|
|
246
245
|
txPlainText.randomCommitmentTrapdoor,
|
|
247
246
|
utils.toHexBuf(txPlainText.memoSize, 32),
|
|
248
247
|
encodedMemo,
|
|
@@ -256,6 +255,7 @@
|
|
|
256
255
|
const DEFAULT_BOUND_DATA = Buffer.from('', 'hex');
|
|
257
256
|
|
|
258
257
|
var _SaplingTransactionViewer_viewingKeyProvider, _SaplingTransactionViewer_readProvider, _SaplingTransactionViewer_saplingContractId;
|
|
258
|
+
const BigNumber$3 = BigNumberJs;
|
|
259
259
|
/**
|
|
260
260
|
* Allows to retrieve and decrypt sapling transactions using on a viewing key
|
|
261
261
|
*
|
|
@@ -279,7 +279,7 @@
|
|
|
279
279
|
*
|
|
280
280
|
*/
|
|
281
281
|
async getBalance() {
|
|
282
|
-
let balance = new BigNumber(0);
|
|
282
|
+
let balance = new BigNumber$3(0);
|
|
283
283
|
const { commitments_and_ciphertexts, nullifiers } = await this.getSaplingDiff();
|
|
284
284
|
for (let i = 0; i < commitments_and_ciphertexts.length; i++) {
|
|
285
285
|
const decrypted = await this.decryptCiphertextAsReceiver(commitments_and_ciphertexts[i]);
|
|
@@ -471,6 +471,7 @@
|
|
|
471
471
|
* https://github.com/airgap-it/airgap-coin-lib/blob/master/LICENSE.md
|
|
472
472
|
*
|
|
473
473
|
*/
|
|
474
|
+
const BigNumber$2 = BigNumberJs;
|
|
474
475
|
/**
|
|
475
476
|
* The SaplingState class's main purpose is to provide a Merkle path for the forger and the transaction builder, so that it may verify that the Sapling transaction is valid
|
|
476
477
|
*
|
|
@@ -590,7 +591,7 @@
|
|
|
590
591
|
}
|
|
591
592
|
else {
|
|
592
593
|
let nextPos, nextTree, otherTree;
|
|
593
|
-
const fullTree = new BigNumber(2).pow(height - 1);
|
|
594
|
+
const fullTree = new BigNumber$2(2).pow(height - 1);
|
|
594
595
|
if (position.lt(fullTree)) {
|
|
595
596
|
nextPos = position;
|
|
596
597
|
nextTree = tree[1];
|
|
@@ -609,15 +610,24 @@
|
|
|
609
610
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
610
611
|
const saplingOutputParams = require('../saplingOutputParams');
|
|
611
612
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
612
|
-
const saplingSpendParams = require('
|
|
613
|
+
const saplingSpendParams = require('@taquito/sapling-spend-params');
|
|
613
614
|
let cachedParams;
|
|
615
|
+
const getRandomValueSource = () => {
|
|
616
|
+
const crypto = globalThis.crypto;
|
|
617
|
+
if (!crypto?.getRandomValues) {
|
|
618
|
+
throw new Error('Sapling randomness requires globalThis.crypto.getRandomValues');
|
|
619
|
+
}
|
|
620
|
+
return crypto;
|
|
621
|
+
};
|
|
614
622
|
class SaplingWrapper {
|
|
615
623
|
async withProvingContext(action) {
|
|
616
624
|
await this.initSaplingParameters();
|
|
617
625
|
return sapling__namespace.withProvingContext(action);
|
|
618
626
|
}
|
|
619
627
|
getRandomBytes(length) {
|
|
620
|
-
|
|
628
|
+
const bytes = new Uint8Array(length);
|
|
629
|
+
getRandomValueSource().getRandomValues(bytes);
|
|
630
|
+
return bytes;
|
|
621
631
|
}
|
|
622
632
|
async randR() {
|
|
623
633
|
return sapling__namespace.randR();
|
|
@@ -660,6 +670,7 @@
|
|
|
660
670
|
}
|
|
661
671
|
|
|
662
672
|
var _SaplingTransactionBuilder_inMemorySpendingKey, _SaplingTransactionBuilder_inMemoryProvingKey, _SaplingTransactionBuilder_saplingForger, _SaplingTransactionBuilder_contractAddress, _SaplingTransactionBuilder_saplingId, _SaplingTransactionBuilder_memoSize, _SaplingTransactionBuilder_readProvider, _SaplingTransactionBuilder_saplingWrapper, _SaplingTransactionBuilder_chainId, _SaplingTransactionBuilder_saplingState;
|
|
673
|
+
const BigNumber$1 = BigNumberJs;
|
|
663
674
|
class SaplingTransactionBuilder {
|
|
664
675
|
constructor(keys, saplingForger, saplingContractDetails, readProvider, saplingWrapper = new SaplingWrapper()) {
|
|
665
676
|
_SaplingTransactionBuilder_inMemorySpendingKey.set(this, void 0);
|
|
@@ -724,9 +735,9 @@
|
|
|
724
735
|
const outputs = [];
|
|
725
736
|
const inputs = [];
|
|
726
737
|
inputs.push(...(await this.prepareSaplingSpendDescription(saplingContext, chosenInputs.inputsToSpend)));
|
|
727
|
-
let sumAmountOutput = new BigNumber(0);
|
|
738
|
+
let sumAmountOutput = new BigNumber$1(0);
|
|
728
739
|
for (const i in saplingTransactionParams) {
|
|
729
|
-
sumAmountOutput = sumAmountOutput.plus(new BigNumber(saplingTransactionParams[i].amount));
|
|
740
|
+
sumAmountOutput = sumAmountOutput.plus(new BigNumber$1(saplingTransactionParams[i].amount));
|
|
730
741
|
const [address] = utils.b58DecodeAndCheckPrefix(saplingTransactionParams[i].to, [
|
|
731
742
|
utils.PrefixV2.SaplingAddress,
|
|
732
743
|
]);
|
|
@@ -750,7 +761,7 @@
|
|
|
750
761
|
randomCommitmentTrapdoor: randomCommitmentTrapdoor,
|
|
751
762
|
outgoingViewingKey: outgoingViewingKey,
|
|
752
763
|
}, chosenInputs.sumSelectedInputs);
|
|
753
|
-
sumAmountOutput = sumAmountOutput.plus(new BigNumber(payBackAmount));
|
|
764
|
+
sumAmountOutput = sumAmountOutput.plus(new BigNumber$1(payBackAmount));
|
|
754
765
|
outputs.push(payBackOutput);
|
|
755
766
|
}
|
|
756
767
|
const balance = this.calculateTransactionBalance(chosenInputs.sumSelectedInputs.toString(), sumAmountOutput.toString());
|
|
@@ -772,7 +783,7 @@
|
|
|
772
783
|
}
|
|
773
784
|
// sum of values of inputs minus sums of values of output equals balance
|
|
774
785
|
calculateTransactionBalance(inputTotal, outputTotal) {
|
|
775
|
-
return new BigNumber(inputTotal).minus(new BigNumber(outputTotal));
|
|
786
|
+
return new BigNumber$1(inputTotal).minus(new BigNumber$1(outputTotal));
|
|
776
787
|
}
|
|
777
788
|
async prepareSaplingOutputDescription(parametersOutputDescription) {
|
|
778
789
|
const ephemeralPrivateKey = await __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingWrapper, "f").randR();
|
|
@@ -825,7 +836,7 @@
|
|
|
825
836
|
const saplingSpendDescriptions = [];
|
|
826
837
|
for (let i = 0; i < inputsToSpend.length; i++) {
|
|
827
838
|
const amount = convertValueToBigNumber(inputsToSpend[i].value).toString();
|
|
828
|
-
const witness = await __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingState, "f").getWitness(stateTree, new BigNumber(inputsToSpend[i].position));
|
|
839
|
+
const witness = await __classPrivateFieldGet(this, _SaplingTransactionBuilder_saplingState, "f").getWitness(stateTree, new BigNumber$1(inputsToSpend[i].position));
|
|
829
840
|
const unsignedSpendDescription = __classPrivateFieldGet(this, _SaplingTransactionBuilder_inMemoryProvingKey, "f")
|
|
830
841
|
? await __classPrivateFieldGet(this, _SaplingTransactionBuilder_inMemoryProvingKey, "f").prepareSpendDescription({
|
|
831
842
|
saplingContext,
|
|
@@ -908,6 +919,647 @@
|
|
|
908
919
|
}
|
|
909
920
|
_SaplingTransactionBuilder_inMemorySpendingKey = new WeakMap(), _SaplingTransactionBuilder_inMemoryProvingKey = new WeakMap(), _SaplingTransactionBuilder_saplingForger = new WeakMap(), _SaplingTransactionBuilder_contractAddress = new WeakMap(), _SaplingTransactionBuilder_saplingId = new WeakMap(), _SaplingTransactionBuilder_memoSize = new WeakMap(), _SaplingTransactionBuilder_readProvider = new WeakMap(), _SaplingTransactionBuilder_saplingWrapper = new WeakMap(), _SaplingTransactionBuilder_chainId = new WeakMap(), _SaplingTransactionBuilder_saplingState = new WeakMap();
|
|
910
921
|
|
|
922
|
+
/**
|
|
923
|
+
* Utilities for hex, bytes, CSPRNG.
|
|
924
|
+
* @module
|
|
925
|
+
*/
|
|
926
|
+
/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
927
|
+
/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */
|
|
928
|
+
function isBytes(a) {
|
|
929
|
+
return a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array');
|
|
930
|
+
}
|
|
931
|
+
/** Asserts something is positive integer. */
|
|
932
|
+
function anumber(n, title = '') {
|
|
933
|
+
if (!Number.isSafeInteger(n) || n < 0) {
|
|
934
|
+
const prefix = title && `"${title}" `;
|
|
935
|
+
throw new Error(`${prefix}expected integer >= 0, got ${n}`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
/** Asserts something is Uint8Array. */
|
|
939
|
+
function abytes(value, length, title = '') {
|
|
940
|
+
const bytes = isBytes(value);
|
|
941
|
+
const len = value?.length;
|
|
942
|
+
const needsLen = length !== undefined;
|
|
943
|
+
if (!bytes || (needsLen && len !== length)) {
|
|
944
|
+
const prefix = title && `"${title}" `;
|
|
945
|
+
const ofLen = needsLen ? ` of length ${length}` : '';
|
|
946
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
947
|
+
throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);
|
|
948
|
+
}
|
|
949
|
+
return value;
|
|
950
|
+
}
|
|
951
|
+
/** Asserts something is hash */
|
|
952
|
+
function ahash(h) {
|
|
953
|
+
if (typeof h !== 'function' || typeof h.create !== 'function')
|
|
954
|
+
throw new Error('Hash must wrapped by utils.createHasher');
|
|
955
|
+
anumber(h.outputLen);
|
|
956
|
+
anumber(h.blockLen);
|
|
957
|
+
}
|
|
958
|
+
/** Asserts a hash instance has not been destroyed / finished */
|
|
959
|
+
function aexists(instance, checkFinished = true) {
|
|
960
|
+
if (instance.destroyed)
|
|
961
|
+
throw new Error('Hash instance has been destroyed');
|
|
962
|
+
if (checkFinished && instance.finished)
|
|
963
|
+
throw new Error('Hash#digest() has already been called');
|
|
964
|
+
}
|
|
965
|
+
/** Asserts output is properly-sized byte array */
|
|
966
|
+
function aoutput(out, instance) {
|
|
967
|
+
abytes(out, undefined, 'digestInto() output');
|
|
968
|
+
const min = instance.outputLen;
|
|
969
|
+
if (out.length < min) {
|
|
970
|
+
throw new Error('"digestInto() output" expected to be of length >=' + min);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
/** Zeroize a byte array. Warning: JS provides no guarantees. */
|
|
974
|
+
function clean(...arrays) {
|
|
975
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
976
|
+
arrays[i].fill(0);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
/** Create DataView of an array for easy byte-level manipulation. */
|
|
980
|
+
function createView(arr) {
|
|
981
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* There is no setImmediate in browser and setTimeout is slow.
|
|
985
|
+
* Call of async fn will return Promise, which will be fullfiled only on
|
|
986
|
+
* next scheduler queue processing step and this is exactly what we need.
|
|
987
|
+
*/
|
|
988
|
+
const nextTick = async () => { };
|
|
989
|
+
/** Returns control to thread each 'tick' ms to avoid blocking. */
|
|
990
|
+
async function asyncLoop(iters, tick, cb) {
|
|
991
|
+
let ts = Date.now();
|
|
992
|
+
for (let i = 0; i < iters; i++) {
|
|
993
|
+
cb(i);
|
|
994
|
+
// Date.now() is not monotonic, so in case if clock goes backwards we return return control too
|
|
995
|
+
const diff = Date.now() - ts;
|
|
996
|
+
if (diff >= 0 && diff < tick)
|
|
997
|
+
continue;
|
|
998
|
+
await nextTick();
|
|
999
|
+
ts += diff;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
/**
|
|
1003
|
+
* Converts string to bytes using UTF8 encoding.
|
|
1004
|
+
* Built-in doesn't validate input to be string: we do the check.
|
|
1005
|
+
* @example utf8ToBytes('abc') // Uint8Array.from([97, 98, 99])
|
|
1006
|
+
*/
|
|
1007
|
+
function utf8ToBytes(str) {
|
|
1008
|
+
if (typeof str !== 'string')
|
|
1009
|
+
throw new Error('string expected');
|
|
1010
|
+
return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Helper for KDFs: consumes uint8array or string.
|
|
1014
|
+
* When string is passed, does utf8 decoding, using TextDecoder.
|
|
1015
|
+
*/
|
|
1016
|
+
function kdfInputToBytes(data, errorTitle = '') {
|
|
1017
|
+
if (typeof data === 'string')
|
|
1018
|
+
return utf8ToBytes(data);
|
|
1019
|
+
return abytes(data, undefined, errorTitle);
|
|
1020
|
+
}
|
|
1021
|
+
/** Merges default options and passed options. */
|
|
1022
|
+
function checkOpts(defaults, opts) {
|
|
1023
|
+
if (opts !== undefined && {}.toString.call(opts) !== '[object Object]')
|
|
1024
|
+
throw new Error('options must be object or undefined');
|
|
1025
|
+
const merged = Object.assign(defaults, opts);
|
|
1026
|
+
return merged;
|
|
1027
|
+
}
|
|
1028
|
+
/** Creates function with outputLen, blockLen, create properties from a class constructor. */
|
|
1029
|
+
function createHasher(hashCons, info = {}) {
|
|
1030
|
+
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
1031
|
+
const tmp = hashCons(undefined);
|
|
1032
|
+
hashC.outputLen = tmp.outputLen;
|
|
1033
|
+
hashC.blockLen = tmp.blockLen;
|
|
1034
|
+
hashC.create = (opts) => hashCons(opts);
|
|
1035
|
+
Object.assign(hashC, info);
|
|
1036
|
+
return Object.freeze(hashC);
|
|
1037
|
+
}
|
|
1038
|
+
/** Creates OID opts for NIST hashes, with prefix 06 09 60 86 48 01 65 03 04 02. */
|
|
1039
|
+
const oidNist = (suffix) => ({
|
|
1040
|
+
oid: Uint8Array.from([0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, suffix]),
|
|
1041
|
+
});
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* HMAC: RFC2104 message authentication code.
|
|
1045
|
+
* @module
|
|
1046
|
+
*/
|
|
1047
|
+
/** Internal class for HMAC. */
|
|
1048
|
+
class _HMAC {
|
|
1049
|
+
oHash;
|
|
1050
|
+
iHash;
|
|
1051
|
+
blockLen;
|
|
1052
|
+
outputLen;
|
|
1053
|
+
finished = false;
|
|
1054
|
+
destroyed = false;
|
|
1055
|
+
constructor(hash, key) {
|
|
1056
|
+
ahash(hash);
|
|
1057
|
+
abytes(key, undefined, 'key');
|
|
1058
|
+
this.iHash = hash.create();
|
|
1059
|
+
if (typeof this.iHash.update !== 'function')
|
|
1060
|
+
throw new Error('Expected instance of class which extends utils.Hash');
|
|
1061
|
+
this.blockLen = this.iHash.blockLen;
|
|
1062
|
+
this.outputLen = this.iHash.outputLen;
|
|
1063
|
+
const blockLen = this.blockLen;
|
|
1064
|
+
const pad = new Uint8Array(blockLen);
|
|
1065
|
+
// blockLen can be bigger than outputLen
|
|
1066
|
+
pad.set(key.length > blockLen ? hash.create().update(key).digest() : key);
|
|
1067
|
+
for (let i = 0; i < pad.length; i++)
|
|
1068
|
+
pad[i] ^= 0x36;
|
|
1069
|
+
this.iHash.update(pad);
|
|
1070
|
+
// By doing update (processing of first block) of outer hash here we can re-use it between multiple calls via clone
|
|
1071
|
+
this.oHash = hash.create();
|
|
1072
|
+
// Undo internal XOR && apply outer XOR
|
|
1073
|
+
for (let i = 0; i < pad.length; i++)
|
|
1074
|
+
pad[i] ^= 0x36 ^ 0x5c;
|
|
1075
|
+
this.oHash.update(pad);
|
|
1076
|
+
clean(pad);
|
|
1077
|
+
}
|
|
1078
|
+
update(buf) {
|
|
1079
|
+
aexists(this);
|
|
1080
|
+
this.iHash.update(buf);
|
|
1081
|
+
return this;
|
|
1082
|
+
}
|
|
1083
|
+
digestInto(out) {
|
|
1084
|
+
aexists(this);
|
|
1085
|
+
abytes(out, this.outputLen, 'output');
|
|
1086
|
+
this.finished = true;
|
|
1087
|
+
this.iHash.digestInto(out);
|
|
1088
|
+
this.oHash.update(out);
|
|
1089
|
+
this.oHash.digestInto(out);
|
|
1090
|
+
this.destroy();
|
|
1091
|
+
}
|
|
1092
|
+
digest() {
|
|
1093
|
+
const out = new Uint8Array(this.oHash.outputLen);
|
|
1094
|
+
this.digestInto(out);
|
|
1095
|
+
return out;
|
|
1096
|
+
}
|
|
1097
|
+
_cloneInto(to) {
|
|
1098
|
+
// Create new instance without calling constructor since key already in state and we don't know it.
|
|
1099
|
+
to ||= Object.create(Object.getPrototypeOf(this), {});
|
|
1100
|
+
const { oHash, iHash, finished, destroyed, blockLen, outputLen } = this;
|
|
1101
|
+
to = to;
|
|
1102
|
+
to.finished = finished;
|
|
1103
|
+
to.destroyed = destroyed;
|
|
1104
|
+
to.blockLen = blockLen;
|
|
1105
|
+
to.outputLen = outputLen;
|
|
1106
|
+
to.oHash = oHash._cloneInto(to.oHash);
|
|
1107
|
+
to.iHash = iHash._cloneInto(to.iHash);
|
|
1108
|
+
return to;
|
|
1109
|
+
}
|
|
1110
|
+
clone() {
|
|
1111
|
+
return this._cloneInto();
|
|
1112
|
+
}
|
|
1113
|
+
destroy() {
|
|
1114
|
+
this.destroyed = true;
|
|
1115
|
+
this.oHash.destroy();
|
|
1116
|
+
this.iHash.destroy();
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
/**
|
|
1120
|
+
* HMAC: RFC2104 message authentication code.
|
|
1121
|
+
* @param hash - function that would be used e.g. sha256
|
|
1122
|
+
* @param key - message key
|
|
1123
|
+
* @param message - message data
|
|
1124
|
+
* @example
|
|
1125
|
+
* import { hmac } from '@noble/hashes/hmac';
|
|
1126
|
+
* import { sha256 } from '@noble/hashes/sha2';
|
|
1127
|
+
* const mac1 = hmac(sha256, 'key', 'message');
|
|
1128
|
+
*/
|
|
1129
|
+
const hmac = (hash, key, message) => new _HMAC(hash, key).update(message).digest();
|
|
1130
|
+
hmac.create = (hash, key) => new _HMAC(hash, key);
|
|
1131
|
+
|
|
1132
|
+
/**
|
|
1133
|
+
* PBKDF (RFC 2898). Can be used to create a key from password and salt.
|
|
1134
|
+
* @module
|
|
1135
|
+
*/
|
|
1136
|
+
// Common start and end for sync/async functions
|
|
1137
|
+
function pbkdf2Init(hash, _password, _salt, _opts) {
|
|
1138
|
+
ahash(hash);
|
|
1139
|
+
const opts = checkOpts({ dkLen: 32, asyncTick: 10 }, _opts);
|
|
1140
|
+
const { c, dkLen, asyncTick } = opts;
|
|
1141
|
+
anumber(c, 'c');
|
|
1142
|
+
anumber(dkLen, 'dkLen');
|
|
1143
|
+
anumber(asyncTick, 'asyncTick');
|
|
1144
|
+
if (c < 1)
|
|
1145
|
+
throw new Error('iterations (c) must be >= 1');
|
|
1146
|
+
const password = kdfInputToBytes(_password, 'password');
|
|
1147
|
+
const salt = kdfInputToBytes(_salt, 'salt');
|
|
1148
|
+
// DK = PBKDF2(PRF, Password, Salt, c, dkLen);
|
|
1149
|
+
const DK = new Uint8Array(dkLen);
|
|
1150
|
+
// U1 = PRF(Password, Salt + INT_32_BE(i))
|
|
1151
|
+
const PRF = hmac.create(hash, password);
|
|
1152
|
+
const PRFSalt = PRF._cloneInto().update(salt);
|
|
1153
|
+
return { c, dkLen, asyncTick, DK, PRF, PRFSalt };
|
|
1154
|
+
}
|
|
1155
|
+
function pbkdf2Output(PRF, PRFSalt, DK, prfW, u) {
|
|
1156
|
+
PRF.destroy();
|
|
1157
|
+
PRFSalt.destroy();
|
|
1158
|
+
if (prfW)
|
|
1159
|
+
prfW.destroy();
|
|
1160
|
+
clean(u);
|
|
1161
|
+
return DK;
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* PBKDF2-HMAC: RFC 2898 key derivation function
|
|
1165
|
+
* @param hash - hash function that would be used e.g. sha256
|
|
1166
|
+
* @param password - password from which a derived key is generated
|
|
1167
|
+
* @param salt - cryptographic salt
|
|
1168
|
+
* @param opts - {c, dkLen} where c is work factor and dkLen is output message size
|
|
1169
|
+
* @example
|
|
1170
|
+
* const key = pbkdf2(sha256, 'password', 'salt', { dkLen: 32, c: Math.pow(2, 18) });
|
|
1171
|
+
*/
|
|
1172
|
+
function pbkdf2(hash, password, salt, opts) {
|
|
1173
|
+
const { c, dkLen, DK, PRF, PRFSalt } = pbkdf2Init(hash, password, salt, opts);
|
|
1174
|
+
let prfW; // Working copy
|
|
1175
|
+
const arr = new Uint8Array(4);
|
|
1176
|
+
const view = createView(arr);
|
|
1177
|
+
const u = new Uint8Array(PRF.outputLen);
|
|
1178
|
+
// DK = T1 + T2 + ⋯ + Tdklen/hlen
|
|
1179
|
+
for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {
|
|
1180
|
+
// Ti = F(Password, Salt, c, i)
|
|
1181
|
+
const Ti = DK.subarray(pos, pos + PRF.outputLen);
|
|
1182
|
+
view.setInt32(0, ti, false);
|
|
1183
|
+
// F(Password, Salt, c, i) = U1 ^ U2 ^ ⋯ ^ Uc
|
|
1184
|
+
// U1 = PRF(Password, Salt + INT_32_BE(i))
|
|
1185
|
+
(prfW = PRFSalt._cloneInto(prfW)).update(arr).digestInto(u);
|
|
1186
|
+
Ti.set(u.subarray(0, Ti.length));
|
|
1187
|
+
for (let ui = 1; ui < c; ui++) {
|
|
1188
|
+
// Uc = PRF(Password, Uc−1)
|
|
1189
|
+
PRF._cloneInto(prfW).update(u).digestInto(u);
|
|
1190
|
+
for (let i = 0; i < Ti.length; i++)
|
|
1191
|
+
Ti[i] ^= u[i];
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
return pbkdf2Output(PRF, PRFSalt, DK, prfW, u);
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* PBKDF2-HMAC: RFC 2898 key derivation function. Async version.
|
|
1198
|
+
* @example
|
|
1199
|
+
* await pbkdf2Async(sha256, 'password', 'salt', { dkLen: 32, c: 500_000 });
|
|
1200
|
+
*/
|
|
1201
|
+
async function pbkdf2Async(hash, password, salt, opts) {
|
|
1202
|
+
const { c, dkLen, asyncTick, DK, PRF, PRFSalt } = pbkdf2Init(hash, password, salt, opts);
|
|
1203
|
+
let prfW; // Working copy
|
|
1204
|
+
const arr = new Uint8Array(4);
|
|
1205
|
+
const view = createView(arr);
|
|
1206
|
+
const u = new Uint8Array(PRF.outputLen);
|
|
1207
|
+
// DK = T1 + T2 + ⋯ + Tdklen/hlen
|
|
1208
|
+
for (let ti = 1, pos = 0; pos < dkLen; ti++, pos += PRF.outputLen) {
|
|
1209
|
+
// Ti = F(Password, Salt, c, i)
|
|
1210
|
+
const Ti = DK.subarray(pos, pos + PRF.outputLen);
|
|
1211
|
+
view.setInt32(0, ti, false);
|
|
1212
|
+
// F(Password, Salt, c, i) = U1 ^ U2 ^ ⋯ ^ Uc
|
|
1213
|
+
// U1 = PRF(Password, Salt + INT_32_BE(i))
|
|
1214
|
+
(prfW = PRFSalt._cloneInto(prfW)).update(arr).digestInto(u);
|
|
1215
|
+
Ti.set(u.subarray(0, Ti.length));
|
|
1216
|
+
await asyncLoop(c - 1, asyncTick, () => {
|
|
1217
|
+
// Uc = PRF(Password, Uc−1)
|
|
1218
|
+
PRF._cloneInto(prfW).update(u).digestInto(u);
|
|
1219
|
+
for (let i = 0; i < Ti.length; i++)
|
|
1220
|
+
Ti[i] ^= u[i];
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
return pbkdf2Output(PRF, PRFSalt, DK, prfW, u);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
/**
|
|
1227
|
+
* Internal Merkle-Damgard hash utils.
|
|
1228
|
+
* @module
|
|
1229
|
+
*/
|
|
1230
|
+
/**
|
|
1231
|
+
* Merkle-Damgard hash construction base class.
|
|
1232
|
+
* Could be used to create MD5, RIPEMD, SHA1, SHA2.
|
|
1233
|
+
*/
|
|
1234
|
+
class HashMD {
|
|
1235
|
+
blockLen;
|
|
1236
|
+
outputLen;
|
|
1237
|
+
padOffset;
|
|
1238
|
+
isLE;
|
|
1239
|
+
// For partial updates less than block size
|
|
1240
|
+
buffer;
|
|
1241
|
+
view;
|
|
1242
|
+
finished = false;
|
|
1243
|
+
length = 0;
|
|
1244
|
+
pos = 0;
|
|
1245
|
+
destroyed = false;
|
|
1246
|
+
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
1247
|
+
this.blockLen = blockLen;
|
|
1248
|
+
this.outputLen = outputLen;
|
|
1249
|
+
this.padOffset = padOffset;
|
|
1250
|
+
this.isLE = isLE;
|
|
1251
|
+
this.buffer = new Uint8Array(blockLen);
|
|
1252
|
+
this.view = createView(this.buffer);
|
|
1253
|
+
}
|
|
1254
|
+
update(data) {
|
|
1255
|
+
aexists(this);
|
|
1256
|
+
abytes(data);
|
|
1257
|
+
const { view, buffer, blockLen } = this;
|
|
1258
|
+
const len = data.length;
|
|
1259
|
+
for (let pos = 0; pos < len;) {
|
|
1260
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
1261
|
+
// Fast path: we have at least one block in input, cast it to view and process
|
|
1262
|
+
if (take === blockLen) {
|
|
1263
|
+
const dataView = createView(data);
|
|
1264
|
+
for (; blockLen <= len - pos; pos += blockLen)
|
|
1265
|
+
this.process(dataView, pos);
|
|
1266
|
+
continue;
|
|
1267
|
+
}
|
|
1268
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
1269
|
+
this.pos += take;
|
|
1270
|
+
pos += take;
|
|
1271
|
+
if (this.pos === blockLen) {
|
|
1272
|
+
this.process(view, 0);
|
|
1273
|
+
this.pos = 0;
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
this.length += data.length;
|
|
1277
|
+
this.roundClean();
|
|
1278
|
+
return this;
|
|
1279
|
+
}
|
|
1280
|
+
digestInto(out) {
|
|
1281
|
+
aexists(this);
|
|
1282
|
+
aoutput(out, this);
|
|
1283
|
+
this.finished = true;
|
|
1284
|
+
// Padding
|
|
1285
|
+
// We can avoid allocation of buffer for padding completely if it
|
|
1286
|
+
// was previously not allocated here. But it won't change performance.
|
|
1287
|
+
const { buffer, view, blockLen, isLE } = this;
|
|
1288
|
+
let { pos } = this;
|
|
1289
|
+
// append the bit '1' to the message
|
|
1290
|
+
buffer[pos++] = 0b10000000;
|
|
1291
|
+
clean(this.buffer.subarray(pos));
|
|
1292
|
+
// we have less than padOffset left in buffer, so we cannot put length in
|
|
1293
|
+
// current block, need process it and pad again
|
|
1294
|
+
if (this.padOffset > blockLen - pos) {
|
|
1295
|
+
this.process(view, 0);
|
|
1296
|
+
pos = 0;
|
|
1297
|
+
}
|
|
1298
|
+
// Pad until full block byte with zeros
|
|
1299
|
+
for (let i = pos; i < blockLen; i++)
|
|
1300
|
+
buffer[i] = 0;
|
|
1301
|
+
// Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
|
|
1302
|
+
// You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
|
|
1303
|
+
// So we just write lowest 64 bits of that value.
|
|
1304
|
+
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
|
|
1305
|
+
this.process(view, 0);
|
|
1306
|
+
const oview = createView(out);
|
|
1307
|
+
const len = this.outputLen;
|
|
1308
|
+
// NOTE: we do division by 4 later, which must be fused in single op with modulo by JIT
|
|
1309
|
+
if (len % 4)
|
|
1310
|
+
throw new Error('_sha2: outputLen must be aligned to 32bit');
|
|
1311
|
+
const outLen = len / 4;
|
|
1312
|
+
const state = this.get();
|
|
1313
|
+
if (outLen > state.length)
|
|
1314
|
+
throw new Error('_sha2: outputLen bigger than state');
|
|
1315
|
+
for (let i = 0; i < outLen; i++)
|
|
1316
|
+
oview.setUint32(4 * i, state[i], isLE);
|
|
1317
|
+
}
|
|
1318
|
+
digest() {
|
|
1319
|
+
const { buffer, outputLen } = this;
|
|
1320
|
+
this.digestInto(buffer);
|
|
1321
|
+
const res = buffer.slice(0, outputLen);
|
|
1322
|
+
this.destroy();
|
|
1323
|
+
return res;
|
|
1324
|
+
}
|
|
1325
|
+
_cloneInto(to) {
|
|
1326
|
+
to ||= new this.constructor();
|
|
1327
|
+
to.set(...this.get());
|
|
1328
|
+
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
1329
|
+
to.destroyed = destroyed;
|
|
1330
|
+
to.finished = finished;
|
|
1331
|
+
to.length = length;
|
|
1332
|
+
to.pos = pos;
|
|
1333
|
+
if (length % blockLen)
|
|
1334
|
+
to.buffer.set(buffer);
|
|
1335
|
+
return to;
|
|
1336
|
+
}
|
|
1337
|
+
clone() {
|
|
1338
|
+
return this._cloneInto();
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
/** Initial SHA512 state. Bits 0..64 of frac part of sqrt of primes 2..19 */
|
|
1342
|
+
const SHA512_IV = /* @__PURE__ */ Uint32Array.from([
|
|
1343
|
+
0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,
|
|
1344
|
+
0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,
|
|
1345
|
+
]);
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.
|
|
1349
|
+
* @todo re-check https://issues.chromium.org/issues/42212588
|
|
1350
|
+
* @module
|
|
1351
|
+
*/
|
|
1352
|
+
const U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);
|
|
1353
|
+
const _32n = /* @__PURE__ */ BigInt(32);
|
|
1354
|
+
function fromBig(n, le = false) {
|
|
1355
|
+
if (le)
|
|
1356
|
+
return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };
|
|
1357
|
+
return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };
|
|
1358
|
+
}
|
|
1359
|
+
function split(lst, le = false) {
|
|
1360
|
+
const len = lst.length;
|
|
1361
|
+
let Ah = new Uint32Array(len);
|
|
1362
|
+
let Al = new Uint32Array(len);
|
|
1363
|
+
for (let i = 0; i < len; i++) {
|
|
1364
|
+
const { h, l } = fromBig(lst[i], le);
|
|
1365
|
+
[Ah[i], Al[i]] = [h, l];
|
|
1366
|
+
}
|
|
1367
|
+
return [Ah, Al];
|
|
1368
|
+
}
|
|
1369
|
+
// for Shift in [0, 32)
|
|
1370
|
+
const shrSH = (h, _l, s) => h >>> s;
|
|
1371
|
+
const shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
|
|
1372
|
+
// Right rotate for Shift in [1, 32)
|
|
1373
|
+
const rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));
|
|
1374
|
+
const rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);
|
|
1375
|
+
// Right rotate for Shift in (32, 64), NOTE: 32 is special case.
|
|
1376
|
+
const rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));
|
|
1377
|
+
const rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));
|
|
1378
|
+
// JS uses 32-bit signed integers for bitwise operations which means we cannot
|
|
1379
|
+
// simple take carry out of low bit sum by shift, we need to use division.
|
|
1380
|
+
function add(Ah, Al, Bh, Bl) {
|
|
1381
|
+
const l = (Al >>> 0) + (Bl >>> 0);
|
|
1382
|
+
return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };
|
|
1383
|
+
}
|
|
1384
|
+
// Addition with more than 2 elements
|
|
1385
|
+
const add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);
|
|
1386
|
+
const add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;
|
|
1387
|
+
const add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);
|
|
1388
|
+
const add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;
|
|
1389
|
+
const add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);
|
|
1390
|
+
const add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;
|
|
1391
|
+
|
|
1392
|
+
/**
|
|
1393
|
+
* SHA2 hash function. A.k.a. sha256, sha384, sha512, sha512_224, sha512_256.
|
|
1394
|
+
* SHA256 is the fastest hash implementable in JS, even faster than Blake3.
|
|
1395
|
+
* Check out [RFC 4634](https://www.rfc-editor.org/rfc/rfc4634) and
|
|
1396
|
+
* [FIPS 180-4](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf).
|
|
1397
|
+
* @module
|
|
1398
|
+
*/
|
|
1399
|
+
// SHA2-512 is slower than sha256 in js because u64 operations are slow.
|
|
1400
|
+
// Round contants
|
|
1401
|
+
// First 32 bits of the fractional parts of the cube roots of the first 80 primes 2..409
|
|
1402
|
+
// prettier-ignore
|
|
1403
|
+
const K512 = /* @__PURE__ */ (() => split([
|
|
1404
|
+
'0x428a2f98d728ae22', '0x7137449123ef65cd', '0xb5c0fbcfec4d3b2f', '0xe9b5dba58189dbbc',
|
|
1405
|
+
'0x3956c25bf348b538', '0x59f111f1b605d019', '0x923f82a4af194f9b', '0xab1c5ed5da6d8118',
|
|
1406
|
+
'0xd807aa98a3030242', '0x12835b0145706fbe', '0x243185be4ee4b28c', '0x550c7dc3d5ffb4e2',
|
|
1407
|
+
'0x72be5d74f27b896f', '0x80deb1fe3b1696b1', '0x9bdc06a725c71235', '0xc19bf174cf692694',
|
|
1408
|
+
'0xe49b69c19ef14ad2', '0xefbe4786384f25e3', '0x0fc19dc68b8cd5b5', '0x240ca1cc77ac9c65',
|
|
1409
|
+
'0x2de92c6f592b0275', '0x4a7484aa6ea6e483', '0x5cb0a9dcbd41fbd4', '0x76f988da831153b5',
|
|
1410
|
+
'0x983e5152ee66dfab', '0xa831c66d2db43210', '0xb00327c898fb213f', '0xbf597fc7beef0ee4',
|
|
1411
|
+
'0xc6e00bf33da88fc2', '0xd5a79147930aa725', '0x06ca6351e003826f', '0x142929670a0e6e70',
|
|
1412
|
+
'0x27b70a8546d22ffc', '0x2e1b21385c26c926', '0x4d2c6dfc5ac42aed', '0x53380d139d95b3df',
|
|
1413
|
+
'0x650a73548baf63de', '0x766a0abb3c77b2a8', '0x81c2c92e47edaee6', '0x92722c851482353b',
|
|
1414
|
+
'0xa2bfe8a14cf10364', '0xa81a664bbc423001', '0xc24b8b70d0f89791', '0xc76c51a30654be30',
|
|
1415
|
+
'0xd192e819d6ef5218', '0xd69906245565a910', '0xf40e35855771202a', '0x106aa07032bbd1b8',
|
|
1416
|
+
'0x19a4c116b8d2d0c8', '0x1e376c085141ab53', '0x2748774cdf8eeb99', '0x34b0bcb5e19b48a8',
|
|
1417
|
+
'0x391c0cb3c5c95a63', '0x4ed8aa4ae3418acb', '0x5b9cca4f7763e373', '0x682e6ff3d6b2b8a3',
|
|
1418
|
+
'0x748f82ee5defb2fc', '0x78a5636f43172f60', '0x84c87814a1f0ab72', '0x8cc702081a6439ec',
|
|
1419
|
+
'0x90befffa23631e28', '0xa4506cebde82bde9', '0xbef9a3f7b2c67915', '0xc67178f2e372532b',
|
|
1420
|
+
'0xca273eceea26619c', '0xd186b8c721c0c207', '0xeada7dd6cde0eb1e', '0xf57d4f7fee6ed178',
|
|
1421
|
+
'0x06f067aa72176fba', '0x0a637dc5a2c898a6', '0x113f9804bef90dae', '0x1b710b35131c471b',
|
|
1422
|
+
'0x28db77f523047d84', '0x32caab7b40c72493', '0x3c9ebe0a15c9bebc', '0x431d67c49c100d4c',
|
|
1423
|
+
'0x4cc5d4becb3e42b6', '0x597f299cfc657e2a', '0x5fcb6fab3ad6faec', '0x6c44198c4a475817'
|
|
1424
|
+
].map(n => BigInt(n))))();
|
|
1425
|
+
const SHA512_Kh = /* @__PURE__ */ (() => K512[0])();
|
|
1426
|
+
const SHA512_Kl = /* @__PURE__ */ (() => K512[1])();
|
|
1427
|
+
// Reusable temporary buffers
|
|
1428
|
+
const SHA512_W_H = /* @__PURE__ */ new Uint32Array(80);
|
|
1429
|
+
const SHA512_W_L = /* @__PURE__ */ new Uint32Array(80);
|
|
1430
|
+
/** Internal 64-byte base SHA2 hash class. */
|
|
1431
|
+
class SHA2_64B extends HashMD {
|
|
1432
|
+
constructor(outputLen) {
|
|
1433
|
+
super(128, outputLen, 16, false);
|
|
1434
|
+
}
|
|
1435
|
+
// prettier-ignore
|
|
1436
|
+
get() {
|
|
1437
|
+
const { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
|
|
1438
|
+
return [Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl];
|
|
1439
|
+
}
|
|
1440
|
+
// prettier-ignore
|
|
1441
|
+
set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl) {
|
|
1442
|
+
this.Ah = Ah | 0;
|
|
1443
|
+
this.Al = Al | 0;
|
|
1444
|
+
this.Bh = Bh | 0;
|
|
1445
|
+
this.Bl = Bl | 0;
|
|
1446
|
+
this.Ch = Ch | 0;
|
|
1447
|
+
this.Cl = Cl | 0;
|
|
1448
|
+
this.Dh = Dh | 0;
|
|
1449
|
+
this.Dl = Dl | 0;
|
|
1450
|
+
this.Eh = Eh | 0;
|
|
1451
|
+
this.El = El | 0;
|
|
1452
|
+
this.Fh = Fh | 0;
|
|
1453
|
+
this.Fl = Fl | 0;
|
|
1454
|
+
this.Gh = Gh | 0;
|
|
1455
|
+
this.Gl = Gl | 0;
|
|
1456
|
+
this.Hh = Hh | 0;
|
|
1457
|
+
this.Hl = Hl | 0;
|
|
1458
|
+
}
|
|
1459
|
+
process(view, offset) {
|
|
1460
|
+
// Extend the first 16 words into the remaining 64 words w[16..79] of the message schedule array
|
|
1461
|
+
for (let i = 0; i < 16; i++, offset += 4) {
|
|
1462
|
+
SHA512_W_H[i] = view.getUint32(offset);
|
|
1463
|
+
SHA512_W_L[i] = view.getUint32((offset += 4));
|
|
1464
|
+
}
|
|
1465
|
+
for (let i = 16; i < 80; i++) {
|
|
1466
|
+
// s0 := (w[i-15] rightrotate 1) xor (w[i-15] rightrotate 8) xor (w[i-15] rightshift 7)
|
|
1467
|
+
const W15h = SHA512_W_H[i - 15] | 0;
|
|
1468
|
+
const W15l = SHA512_W_L[i - 15] | 0;
|
|
1469
|
+
const s0h = rotrSH(W15h, W15l, 1) ^ rotrSH(W15h, W15l, 8) ^ shrSH(W15h, W15l, 7);
|
|
1470
|
+
const s0l = rotrSL(W15h, W15l, 1) ^ rotrSL(W15h, W15l, 8) ^ shrSL(W15h, W15l, 7);
|
|
1471
|
+
// s1 := (w[i-2] rightrotate 19) xor (w[i-2] rightrotate 61) xor (w[i-2] rightshift 6)
|
|
1472
|
+
const W2h = SHA512_W_H[i - 2] | 0;
|
|
1473
|
+
const W2l = SHA512_W_L[i - 2] | 0;
|
|
1474
|
+
const s1h = rotrSH(W2h, W2l, 19) ^ rotrBH(W2h, W2l, 61) ^ shrSH(W2h, W2l, 6);
|
|
1475
|
+
const s1l = rotrSL(W2h, W2l, 19) ^ rotrBL(W2h, W2l, 61) ^ shrSL(W2h, W2l, 6);
|
|
1476
|
+
// SHA256_W[i] = s0 + s1 + SHA256_W[i - 7] + SHA256_W[i - 16];
|
|
1477
|
+
const SUMl = add4L(s0l, s1l, SHA512_W_L[i - 7], SHA512_W_L[i - 16]);
|
|
1478
|
+
const SUMh = add4H(SUMl, s0h, s1h, SHA512_W_H[i - 7], SHA512_W_H[i - 16]);
|
|
1479
|
+
SHA512_W_H[i] = SUMh | 0;
|
|
1480
|
+
SHA512_W_L[i] = SUMl | 0;
|
|
1481
|
+
}
|
|
1482
|
+
let { Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl } = this;
|
|
1483
|
+
// Compression function main loop, 80 rounds
|
|
1484
|
+
for (let i = 0; i < 80; i++) {
|
|
1485
|
+
// S1 := (e rightrotate 14) xor (e rightrotate 18) xor (e rightrotate 41)
|
|
1486
|
+
const sigma1h = rotrSH(Eh, El, 14) ^ rotrSH(Eh, El, 18) ^ rotrBH(Eh, El, 41);
|
|
1487
|
+
const sigma1l = rotrSL(Eh, El, 14) ^ rotrSL(Eh, El, 18) ^ rotrBL(Eh, El, 41);
|
|
1488
|
+
//const T1 = (H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i]) | 0;
|
|
1489
|
+
const CHIh = (Eh & Fh) ^ (~Eh & Gh);
|
|
1490
|
+
const CHIl = (El & Fl) ^ (~El & Gl);
|
|
1491
|
+
// T1 = H + sigma1 + Chi(E, F, G) + SHA512_K[i] + SHA512_W[i]
|
|
1492
|
+
// prettier-ignore
|
|
1493
|
+
const T1ll = add5L(Hl, sigma1l, CHIl, SHA512_Kl[i], SHA512_W_L[i]);
|
|
1494
|
+
const T1h = add5H(T1ll, Hh, sigma1h, CHIh, SHA512_Kh[i], SHA512_W_H[i]);
|
|
1495
|
+
const T1l = T1ll | 0;
|
|
1496
|
+
// S0 := (a rightrotate 28) xor (a rightrotate 34) xor (a rightrotate 39)
|
|
1497
|
+
const sigma0h = rotrSH(Ah, Al, 28) ^ rotrBH(Ah, Al, 34) ^ rotrBH(Ah, Al, 39);
|
|
1498
|
+
const sigma0l = rotrSL(Ah, Al, 28) ^ rotrBL(Ah, Al, 34) ^ rotrBL(Ah, Al, 39);
|
|
1499
|
+
const MAJh = (Ah & Bh) ^ (Ah & Ch) ^ (Bh & Ch);
|
|
1500
|
+
const MAJl = (Al & Bl) ^ (Al & Cl) ^ (Bl & Cl);
|
|
1501
|
+
Hh = Gh | 0;
|
|
1502
|
+
Hl = Gl | 0;
|
|
1503
|
+
Gh = Fh | 0;
|
|
1504
|
+
Gl = Fl | 0;
|
|
1505
|
+
Fh = Eh | 0;
|
|
1506
|
+
Fl = El | 0;
|
|
1507
|
+
({ h: Eh, l: El } = add(Dh | 0, Dl | 0, T1h | 0, T1l | 0));
|
|
1508
|
+
Dh = Ch | 0;
|
|
1509
|
+
Dl = Cl | 0;
|
|
1510
|
+
Ch = Bh | 0;
|
|
1511
|
+
Cl = Bl | 0;
|
|
1512
|
+
Bh = Ah | 0;
|
|
1513
|
+
Bl = Al | 0;
|
|
1514
|
+
const All = add3L(T1l, sigma0l, MAJl);
|
|
1515
|
+
Ah = add3H(All, T1h, sigma0h, MAJh);
|
|
1516
|
+
Al = All | 0;
|
|
1517
|
+
}
|
|
1518
|
+
// Add the compressed chunk to the current hash value
|
|
1519
|
+
({ h: Ah, l: Al } = add(this.Ah | 0, this.Al | 0, Ah | 0, Al | 0));
|
|
1520
|
+
({ h: Bh, l: Bl } = add(this.Bh | 0, this.Bl | 0, Bh | 0, Bl | 0));
|
|
1521
|
+
({ h: Ch, l: Cl } = add(this.Ch | 0, this.Cl | 0, Ch | 0, Cl | 0));
|
|
1522
|
+
({ h: Dh, l: Dl } = add(this.Dh | 0, this.Dl | 0, Dh | 0, Dl | 0));
|
|
1523
|
+
({ h: Eh, l: El } = add(this.Eh | 0, this.El | 0, Eh | 0, El | 0));
|
|
1524
|
+
({ h: Fh, l: Fl } = add(this.Fh | 0, this.Fl | 0, Fh | 0, Fl | 0));
|
|
1525
|
+
({ h: Gh, l: Gl } = add(this.Gh | 0, this.Gl | 0, Gh | 0, Gl | 0));
|
|
1526
|
+
({ h: Hh, l: Hl } = add(this.Hh | 0, this.Hl | 0, Hh | 0, Hl | 0));
|
|
1527
|
+
this.set(Ah, Al, Bh, Bl, Ch, Cl, Dh, Dl, Eh, El, Fh, Fl, Gh, Gl, Hh, Hl);
|
|
1528
|
+
}
|
|
1529
|
+
roundClean() {
|
|
1530
|
+
clean(SHA512_W_H, SHA512_W_L);
|
|
1531
|
+
}
|
|
1532
|
+
destroy() {
|
|
1533
|
+
clean(this.buffer);
|
|
1534
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
/** Internal SHA2-512 hash class. */
|
|
1538
|
+
class _SHA512 extends SHA2_64B {
|
|
1539
|
+
Ah = SHA512_IV[0] | 0;
|
|
1540
|
+
Al = SHA512_IV[1] | 0;
|
|
1541
|
+
Bh = SHA512_IV[2] | 0;
|
|
1542
|
+
Bl = SHA512_IV[3] | 0;
|
|
1543
|
+
Ch = SHA512_IV[4] | 0;
|
|
1544
|
+
Cl = SHA512_IV[5] | 0;
|
|
1545
|
+
Dh = SHA512_IV[6] | 0;
|
|
1546
|
+
Dl = SHA512_IV[7] | 0;
|
|
1547
|
+
Eh = SHA512_IV[8] | 0;
|
|
1548
|
+
El = SHA512_IV[9] | 0;
|
|
1549
|
+
Fh = SHA512_IV[10] | 0;
|
|
1550
|
+
Fl = SHA512_IV[11] | 0;
|
|
1551
|
+
Gh = SHA512_IV[12] | 0;
|
|
1552
|
+
Gl = SHA512_IV[13] | 0;
|
|
1553
|
+
Hh = SHA512_IV[14] | 0;
|
|
1554
|
+
Hl = SHA512_IV[15] | 0;
|
|
1555
|
+
constructor() {
|
|
1556
|
+
super(64);
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
/** SHA2-512 hash function from RFC 4634. */
|
|
1560
|
+
const sha512 = /* @__PURE__ */ createHasher(() => new _SHA512(),
|
|
1561
|
+
/* @__PURE__ */ oidNist(0x03));
|
|
1562
|
+
|
|
911
1563
|
function decryptKey(spendingKey, password) {
|
|
912
1564
|
const [keyArr, pre] = (() => {
|
|
913
1565
|
try {
|
|
@@ -931,7 +1583,7 @@
|
|
|
931
1583
|
}
|
|
932
1584
|
const salt = toBuffer(keyArr.slice(0, 8));
|
|
933
1585
|
const encryptedSk = toBuffer(keyArr.slice(8));
|
|
934
|
-
const encryptionKey = pbkdf2
|
|
1586
|
+
const encryptionKey = pbkdf2(sha512, password, salt, { c: 32768, dkLen: 32 });
|
|
935
1587
|
// Zero nonce is safe: fresh random salt per encryption produces unique PBKDF2-derived key.
|
|
936
1588
|
// See: https://gitlab.com/tezos/tezos/-/blob/master/src/lib_signer_backends/encrypted.ml
|
|
937
1589
|
const decrypted = nacl.openSecretBox(new Uint8Array(encryptionKey), new Uint8Array(24), // zero nonce - uniqueness provided by per-encryption derived key
|
|
@@ -1011,6 +1663,38 @@
|
|
|
1011
1663
|
}
|
|
1012
1664
|
_InMemoryViewingKey_fullViewingKey = new WeakMap();
|
|
1013
1665
|
|
|
1666
|
+
/*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) */
|
|
1667
|
+
// Normalization replaces equivalent sequences of characters
|
|
1668
|
+
// so that any two texts that are equivalent will be reduced
|
|
1669
|
+
// to the same sequence of code points, called the normal form of the original text.
|
|
1670
|
+
// https://tonsky.me/blog/unicode/#why-is-a----
|
|
1671
|
+
function nfkd(str) {
|
|
1672
|
+
if (typeof str !== 'string')
|
|
1673
|
+
throw new TypeError('invalid mnemonic type: ' + typeof str);
|
|
1674
|
+
return str.normalize('NFKD');
|
|
1675
|
+
}
|
|
1676
|
+
function normalize(str) {
|
|
1677
|
+
const norm = nfkd(str);
|
|
1678
|
+
const words = norm.split(' ');
|
|
1679
|
+
if (![12, 15, 18, 21, 24].includes(words.length))
|
|
1680
|
+
throw new Error('Invalid mnemonic');
|
|
1681
|
+
return { nfkd: norm, words };
|
|
1682
|
+
}
|
|
1683
|
+
const psalt = (passphrase) => nfkd('mnemonic' + passphrase);
|
|
1684
|
+
/**
|
|
1685
|
+
* Irreversible: Uses KDF to derive 64 bytes of key data from mnemonic + optional password.
|
|
1686
|
+
* @param mnemonic 12-24 words
|
|
1687
|
+
* @param passphrase string that will additionally protect the key
|
|
1688
|
+
* @returns 64 bytes of key data
|
|
1689
|
+
* @example
|
|
1690
|
+
* const mnem = 'legal winner thank year wave sausage worth useful legal winner thank yellow';
|
|
1691
|
+
* await mnemonicToSeed(mnem, 'password');
|
|
1692
|
+
* // new Uint8Array([...64 bytes])
|
|
1693
|
+
*/
|
|
1694
|
+
function mnemonicToSeed(mnemonic, passphrase = '') {
|
|
1695
|
+
return pbkdf2Async(sha512, normalize(mnemonic).nfkd, psalt(passphrase), { c: 2048, dkLen: 64 });
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1014
1698
|
var _InMemorySpendingKey_spendingKeyBuf, _InMemorySpendingKey_saplingViewingKey;
|
|
1015
1699
|
/**
|
|
1016
1700
|
* holds the spending key, create proof and signature for spend descriptions
|
|
@@ -1036,7 +1720,7 @@
|
|
|
1036
1720
|
*/
|
|
1037
1721
|
static async fromMnemonic(mnemonic, derivationPath = 'm/') {
|
|
1038
1722
|
// no password passed here. password provided only changes from sask -> MMXj
|
|
1039
|
-
const fullSeed = await
|
|
1723
|
+
const fullSeed = await mnemonicToSeed(mnemonic);
|
|
1040
1724
|
const first32 = fullSeed.slice(0, 32);
|
|
1041
1725
|
const second32 = fullSeed.slice(32);
|
|
1042
1726
|
// reduce seed bytes must be 32 bytes reflecting both halves
|
|
@@ -1167,6 +1851,7 @@
|
|
|
1167
1851
|
* @module @taquito/sapling
|
|
1168
1852
|
*/
|
|
1169
1853
|
var _SaplingToolkit_inMemorySpendingKey, _SaplingToolkit_saplingId, _SaplingToolkit_contractAddress, _SaplingToolkit_memoSize, _SaplingToolkit_readProvider, _SaplingToolkit_packer, _SaplingToolkit_saplingForger, _SaplingToolkit_saplingTxBuilder, _SaplingToolkit_saplingTransactionViewer;
|
|
1854
|
+
const BigNumber = BigNumberJs;
|
|
1170
1855
|
/**
|
|
1171
1856
|
* Class that surfaces all of the sapling capability allowing to read from a sapling state and prepare transactions
|
|
1172
1857
|
*
|