@tideorg/js 0.13.19
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/LICENSE +333 -0
- package/README.md +12 -0
- package/dist/Clients/ClientBase.d.ts +24 -0
- package/dist/Clients/ClientBase.d.ts.map +1 -0
- package/dist/Clients/ClientBase.js +160 -0
- package/dist/Clients/NetworkClient.d.ts +11 -0
- package/dist/Clients/NetworkClient.d.ts.map +1 -0
- package/dist/Clients/NetworkClient.js +68 -0
- package/dist/Clients/NodeClient.d.ts +34 -0
- package/dist/Clients/NodeClient.d.ts.map +1 -0
- package/dist/Clients/NodeClient.js +191 -0
- package/dist/Clients/VoucherClient.d.ts +8 -0
- package/dist/Clients/VoucherClient.d.ts.map +1 -0
- package/dist/Clients/VoucherClient.js +36 -0
- package/dist/Clients/index.d.ts +5 -0
- package/dist/Clients/index.d.ts.map +1 -0
- package/dist/Clients/index.js +20 -0
- package/dist/Contracts/BaseContract.d.ts +47 -0
- package/dist/Contracts/BaseContract.d.ts.map +1 -0
- package/dist/Contracts/BaseContract.js +153 -0
- package/dist/Contracts/GenericRealmAccessThresholdRoleContract.d.ts +8 -0
- package/dist/Contracts/GenericRealmAccessThresholdRoleContract.d.ts.map +1 -0
- package/dist/Contracts/GenericRealmAccessThresholdRoleContract.js +21 -0
- package/dist/Contracts/GenericResourceAccessThresholdRoleContract.d.ts +8 -0
- package/dist/Contracts/GenericResourceAccessThresholdRoleContract.d.ts.map +1 -0
- package/dist/Contracts/GenericResourceAccessThresholdRoleContract.js +21 -0
- package/dist/Contracts/index.d.ts +4 -0
- package/dist/Contracts/index.d.ts.map +1 -0
- package/dist/Contracts/index.js +19 -0
- package/dist/Cryptide/Components/BaseComponent.d.ts +56 -0
- package/dist/Cryptide/Components/BaseComponent.d.ts.map +1 -0
- package/dist/Cryptide/Components/BaseComponent.js +176 -0
- package/dist/Cryptide/Components/ComponentRegistry.d.ts +18 -0
- package/dist/Cryptide/Components/ComponentRegistry.d.ts.map +1 -0
- package/dist/Cryptide/Components/ComponentRegistry.js +39 -0
- package/dist/Cryptide/Components/Schemes/AES/AESScheme.d.ts +5 -0
- package/dist/Cryptide/Components/Schemes/AES/AESScheme.d.ts.map +1 -0
- package/dist/Cryptide/Components/Schemes/AES/AESScheme.js +20 -0
- package/dist/Cryptide/Components/Schemes/AES/index.d.ts +2 -0
- package/dist/Cryptide/Components/Schemes/AES/index.d.ts.map +1 -0
- package/dist/Cryptide/Components/Schemes/AES/index.js +17 -0
- package/dist/Cryptide/Components/Schemes/BaseScheme.d.ts +7 -0
- package/dist/Cryptide/Components/Schemes/BaseScheme.d.ts.map +1 -0
- package/dist/Cryptide/Components/Schemes/BaseScheme.js +23 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/Ed25519Components.d.ts +52 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/Ed25519Components.d.ts.map +1 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/Ed25519Components.js +171 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/Ed25519Scheme.d.ts +13 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/Ed25519Scheme.d.ts.map +1 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/Ed25519Scheme.js +71 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/index.d.ts +3 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/index.d.ts.map +1 -0
- package/dist/Cryptide/Components/Schemes/Ed25519/index.js +18 -0
- package/dist/Cryptide/Components/Schemes/SchemeRegistry.d.ts +3 -0
- package/dist/Cryptide/Components/Schemes/SchemeRegistry.d.ts.map +1 -0
- package/dist/Cryptide/Components/Schemes/SchemeRegistry.js +22 -0
- package/dist/Cryptide/Components/Schemes/index.d.ts +5 -0
- package/dist/Cryptide/Components/Schemes/index.d.ts.map +1 -0
- package/dist/Cryptide/Components/Schemes/index.js +20 -0
- package/dist/Cryptide/Components/index.d.ts +4 -0
- package/dist/Cryptide/Components/index.d.ts.map +1 -0
- package/dist/Cryptide/Components/index.js +19 -0
- package/dist/Cryptide/Ed25519.d.ts +106 -0
- package/dist/Cryptide/Ed25519.d.ts.map +1 -0
- package/dist/Cryptide/Ed25519.js +522 -0
- package/dist/Cryptide/Encryption/AES.d.ts +6 -0
- package/dist/Cryptide/Encryption/AES.d.ts.map +1 -0
- package/dist/Cryptide/Encryption/AES.js +76 -0
- package/dist/Cryptide/Encryption/DH.d.ts +4 -0
- package/dist/Cryptide/Encryption/DH.d.ts.map +1 -0
- package/dist/Cryptide/Encryption/DH.js +38 -0
- package/dist/Cryptide/Encryption/ElGamal.d.ts +12 -0
- package/dist/Cryptide/Encryption/ElGamal.d.ts.map +1 -0
- package/dist/Cryptide/Encryption/ElGamal.js +61 -0
- package/dist/Cryptide/Encryption/index.d.ts +4 -0
- package/dist/Cryptide/Encryption/index.d.ts.map +1 -0
- package/dist/Cryptide/Encryption/index.js +19 -0
- package/dist/Cryptide/Hashing/H2P.d.ts +6 -0
- package/dist/Cryptide/Hashing/H2P.d.ts.map +1 -0
- package/dist/Cryptide/Hashing/H2P.js +235 -0
- package/dist/Cryptide/Hashing/Hash.d.ts +8 -0
- package/dist/Cryptide/Hashing/Hash.d.ts.map +1 -0
- package/dist/Cryptide/Hashing/Hash.js +43 -0
- package/dist/Cryptide/Hashing/index.d.ts +3 -0
- package/dist/Cryptide/Hashing/index.d.ts.map +1 -0
- package/dist/Cryptide/Hashing/index.js +18 -0
- package/dist/Cryptide/Interpolation.d.ts +20 -0
- package/dist/Cryptide/Interpolation.d.ts.map +1 -0
- package/dist/Cryptide/Interpolation.js +68 -0
- package/dist/Cryptide/Math.d.ts +11 -0
- package/dist/Cryptide/Math.d.ts.map +1 -0
- package/dist/Cryptide/Math.js +81 -0
- package/dist/Cryptide/Serialization.d.ts +66 -0
- package/dist/Cryptide/Serialization.d.ts.map +1 -0
- package/dist/Cryptide/Serialization.js +517 -0
- package/dist/Cryptide/Signing/BlindSig.d.ts +10 -0
- package/dist/Cryptide/Signing/BlindSig.d.ts.map +1 -0
- package/dist/Cryptide/Signing/BlindSig.js +41 -0
- package/dist/Cryptide/Signing/EdDSA.d.ts +14 -0
- package/dist/Cryptide/Signing/EdDSA.d.ts.map +1 -0
- package/dist/Cryptide/Signing/EdDSA.js +67 -0
- package/dist/Cryptide/Signing/TideSignature.d.ts +54 -0
- package/dist/Cryptide/Signing/TideSignature.d.ts.map +1 -0
- package/dist/Cryptide/Signing/TideSignature.js +110 -0
- package/dist/Cryptide/Signing/index.d.ts +4 -0
- package/dist/Cryptide/Signing/index.d.ts.map +1 -0
- package/dist/Cryptide/Signing/index.js +19 -0
- package/dist/Cryptide/TideKey.d.ts +17 -0
- package/dist/Cryptide/TideKey.d.ts.map +1 -0
- package/dist/Cryptide/TideKey.js +84 -0
- package/dist/Cryptide/TideMemoryObjects.d.ts +4 -0
- package/dist/Cryptide/TideMemoryObjects.d.ts.map +1 -0
- package/dist/Cryptide/TideMemoryObjects.js +32 -0
- package/dist/Cryptide/index.d.ts +11 -0
- package/dist/Cryptide/index.d.ts.map +1 -0
- package/dist/Cryptide/index.js +28 -0
- package/dist/Flow/DecryptionFlows/dVVKDecryptionFlow.d.ts +16 -0
- package/dist/Flow/DecryptionFlows/dVVKDecryptionFlow.d.ts.map +1 -0
- package/dist/Flow/DecryptionFlows/dVVKDecryptionFlow.js +47 -0
- package/dist/Flow/DecryptionFlows/index.d.ts +2 -0
- package/dist/Flow/DecryptionFlows/index.d.ts.map +1 -0
- package/dist/Flow/DecryptionFlows/index.js +17 -0
- package/dist/Flow/EncryptionFlows/AuthorizedEncryptionFlow.d.ts +13 -0
- package/dist/Flow/EncryptionFlows/AuthorizedEncryptionFlow.d.ts.map +1 -0
- package/dist/Flow/EncryptionFlows/AuthorizedEncryptionFlow.js +183 -0
- package/dist/Flow/EncryptionFlows/PolicyAuthorizedEncryptionFlow.d.ts +57 -0
- package/dist/Flow/EncryptionFlows/PolicyAuthorizedEncryptionFlow.d.ts.map +1 -0
- package/dist/Flow/EncryptionFlows/PolicyAuthorizedEncryptionFlow.js +220 -0
- package/dist/Flow/EncryptionFlows/index.d.ts +3 -0
- package/dist/Flow/EncryptionFlows/index.d.ts.map +1 -0
- package/dist/Flow/EncryptionFlows/index.js +18 -0
- package/dist/Flow/SigningFlows/AuthorizedSigningFlow.d.ts +12 -0
- package/dist/Flow/SigningFlows/AuthorizedSigningFlow.d.ts.map +1 -0
- package/dist/Flow/SigningFlows/AuthorizedSigningFlow.js +50 -0
- package/dist/Flow/SigningFlows/dTestVVkSigningFlow.d.ts +15 -0
- package/dist/Flow/SigningFlows/dTestVVkSigningFlow.d.ts.map +1 -0
- package/dist/Flow/SigningFlows/dTestVVkSigningFlow.js +67 -0
- package/dist/Flow/SigningFlows/dVVKSigningFlow.d.ts +17 -0
- package/dist/Flow/SigningFlows/dVVKSigningFlow.d.ts.map +1 -0
- package/dist/Flow/SigningFlows/dVVKSigningFlow.js +61 -0
- package/dist/Flow/SigningFlows/dVVKSigningFlow2Step.d.ts +28 -0
- package/dist/Flow/SigningFlows/dVVKSigningFlow2Step.d.ts.map +1 -0
- package/dist/Flow/SigningFlows/dVVKSigningFlow2Step.js +118 -0
- package/dist/Flow/SigningFlows/index.d.ts +5 -0
- package/dist/Flow/SigningFlows/index.d.ts.map +1 -0
- package/dist/Flow/SigningFlows/index.js +20 -0
- package/dist/Flow/VoucherFlows/VoucherFlow.d.ts +16 -0
- package/dist/Flow/VoucherFlows/VoucherFlow.d.ts.map +1 -0
- package/dist/Flow/VoucherFlows/VoucherFlow.js +34 -0
- package/dist/Flow/VoucherFlows/index.d.ts +2 -0
- package/dist/Flow/VoucherFlows/index.d.ts.map +1 -0
- package/dist/Flow/VoucherFlows/index.js +17 -0
- package/dist/Flow/index.d.ts +5 -0
- package/dist/Flow/index.d.ts.map +1 -0
- package/dist/Flow/index.js +20 -0
- package/dist/Math/KeyDecryption.d.ts +3 -0
- package/dist/Math/KeyDecryption.d.ts.map +1 -0
- package/dist/Math/KeyDecryption.js +24 -0
- package/dist/Math/KeySigning.d.ts +4 -0
- package/dist/Math/KeySigning.d.ts.map +1 -0
- package/dist/Math/KeySigning.js +28 -0
- package/dist/Math/index.d.ts +3 -0
- package/dist/Math/index.d.ts.map +1 -0
- package/dist/Math/index.js +18 -0
- package/dist/Models/AuthRequest.d.ts +13 -0
- package/dist/Models/AuthRequest.d.ts.map +1 -0
- package/dist/Models/AuthRequest.js +46 -0
- package/dist/Models/BaseTideRequest.d.ts +55 -0
- package/dist/Models/BaseTideRequest.d.ts.map +1 -0
- package/dist/Models/BaseTideRequest.js +299 -0
- package/dist/Models/CustomTideRequest.d.ts +19 -0
- package/dist/Models/CustomTideRequest.d.ts.map +1 -0
- package/dist/Models/CustomTideRequest.js +30 -0
- package/dist/Models/Datum.d.ts +11 -0
- package/dist/Models/Datum.d.ts.map +1 -0
- package/dist/Models/Datum.js +33 -0
- package/dist/Models/Doken.d.ts +33 -0
- package/dist/Models/Doken.d.ts.map +1 -0
- package/dist/Models/Doken.js +133 -0
- package/dist/Models/EnclaveEntry.d.ts +14 -0
- package/dist/Models/EnclaveEntry.d.ts.map +1 -0
- package/dist/Models/EnclaveEntry.js +49 -0
- package/dist/Models/Infos/KeyInfo.d.ts +24 -0
- package/dist/Models/Infos/KeyInfo.d.ts.map +1 -0
- package/dist/Models/Infos/KeyInfo.js +51 -0
- package/dist/Models/Infos/OrkInfo.d.ts +18 -0
- package/dist/Models/Infos/OrkInfo.d.ts.map +1 -0
- package/dist/Models/Infos/OrkInfo.js +58 -0
- package/dist/Models/Infos/index.d.ts +3 -0
- package/dist/Models/Infos/index.d.ts.map +1 -0
- package/dist/Models/Infos/index.js +18 -0
- package/dist/Models/ModelRegistry.d.ts +29 -0
- package/dist/Models/ModelRegistry.d.ts.map +1 -0
- package/dist/Models/ModelRegistry.js +321 -0
- package/dist/Models/Policy.d.ts +41 -0
- package/dist/Models/Policy.d.ts.map +1 -0
- package/dist/Models/Policy.js +317 -0
- package/dist/Models/PolicyProtectedSerializedField.d.ts +12 -0
- package/dist/Models/PolicyProtectedSerializedField.d.ts.map +1 -0
- package/dist/Models/PolicyProtectedSerializedField.js +50 -0
- package/dist/Models/Responses/Vendor/VoucherResponse.d.ts +12 -0
- package/dist/Models/Responses/Vendor/VoucherResponse.d.ts.map +1 -0
- package/dist/Models/Responses/Vendor/VoucherResponse.js +39 -0
- package/dist/Models/Responses/Vendor/index.d.ts +2 -0
- package/dist/Models/Responses/Vendor/index.d.ts.map +1 -0
- package/dist/Models/Responses/Vendor/index.js +17 -0
- package/dist/Models/Responses/index.d.ts +2 -0
- package/dist/Models/Responses/index.d.ts.map +1 -0
- package/dist/Models/Responses/index.js +17 -0
- package/dist/Models/SerializedField.d.ts +12 -0
- package/dist/Models/SerializedField.d.ts.map +1 -0
- package/dist/Models/SerializedField.js +50 -0
- package/dist/Models/VendorData.d.ts +12 -0
- package/dist/Models/VendorData.d.ts.map +1 -0
- package/dist/Models/VendorData.js +38 -0
- package/dist/Models/VendorSettings.d.ts +9 -0
- package/dist/Models/VendorSettings.d.ts.map +1 -0
- package/dist/Models/VendorSettings.js +32 -0
- package/dist/Models/index.d.ts +13 -0
- package/dist/Models/index.d.ts.map +1 -0
- package/dist/Models/index.js +30 -0
- package/dist/Tools/TideMemory.d.ts +10 -0
- package/dist/Tools/TideMemory.d.ts.map +1 -0
- package/dist/Tools/TideMemory.js +105 -0
- package/dist/Tools/Utils.d.ts +13 -0
- package/dist/Tools/Utils.d.ts.map +1 -0
- package/dist/Tools/Utils.js +242 -0
- package/dist/Tools/index.d.ts +3 -0
- package/dist/Tools/index.d.ts.map +1 -0
- package/dist/Tools/index.js +18 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/package.json +27 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Tide Protocol - Infrastructure for a TRUE Zero-Trust paradigm
|
|
3
|
+
// Copyright (C) 2022 Tide Foundation Ltd
|
|
4
|
+
//
|
|
5
|
+
// This program is free software and is subject to the terms of
|
|
6
|
+
// the Tide Community Open Code License as published by the
|
|
7
|
+
// Tide Foundation Limited. You may modify it and redistribute
|
|
8
|
+
// it in accordance with and subject to the terms of that License.
|
|
9
|
+
// This program is distributed WITHOUT WARRANTY of any kind,
|
|
10
|
+
// including without any implied warranty of MERCHANTABILITY or
|
|
11
|
+
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
12
|
+
// See the Tide Community Open Code License for more details.
|
|
13
|
+
// You should have received a copy of the Tide Community Open
|
|
14
|
+
// Code License along with this program.
|
|
15
|
+
// If not, see https://tide.org/licenses_tcoc2-0-0-en
|
|
16
|
+
//
|
|
17
|
+
// Some parts of the code were taken from @noble/curves project and are protected under the following license:
|
|
18
|
+
//
|
|
19
|
+
// The MIT License (MIT)
|
|
20
|
+
//
|
|
21
|
+
// Copyright (c) 2022 Paul Miller (https://paulmillr.com)
|
|
22
|
+
//
|
|
23
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
24
|
+
// of this software and associated documentation files (the "Software"), to deal
|
|
25
|
+
// in the Software without restriction, including without limitation the rights
|
|
26
|
+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
27
|
+
// copies of the Software, and to permit persons to whom the Software is
|
|
28
|
+
// furnished to do so, subject to the following conditions:
|
|
29
|
+
//
|
|
30
|
+
// The above copyright notice and this permission notice shall be included in
|
|
31
|
+
// all copies or substantial portions of the Software.
|
|
32
|
+
//
|
|
33
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
34
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
35
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
36
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
37
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
38
|
+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
39
|
+
// THE SOFTWARE.
|
|
40
|
+
//
|
|
41
|
+
import { base64ToBytes, bytesToBase64 } from "./Serialization";
|
|
42
|
+
import { SHA256_Digest } from "./Hashing/Hash";
|
|
43
|
+
const P = 2n ** 255n - 19n; // ed25519 is twisted edwards curve
|
|
44
|
+
const N = 2n ** 252n + 27742317777372353535851937790883648493n; // curve's (group) order
|
|
45
|
+
const Gx = 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an; // base point x
|
|
46
|
+
const Gy = 0x6666666666666666666666666666666666666666666666666666666666666658n; // base point y
|
|
47
|
+
const _d = 37095705934669439343138083508754565189542113879843219016388785533085940283555n;
|
|
48
|
+
const MASK = 2n ** 256n;
|
|
49
|
+
/**
|
|
50
|
+
* ed25519 curve parameters. Equation is −x² + y² = -a + dx²y².
|
|
51
|
+
* Gx and Gy are generator coordinates. p is field order, n is group order.
|
|
52
|
+
* h is cofactor.
|
|
53
|
+
*/
|
|
54
|
+
const CURVE = {
|
|
55
|
+
a: -1n, // -1 mod p
|
|
56
|
+
d: _d, // -(121665/121666) mod p
|
|
57
|
+
p: P, n: N, h: 8, Gx: Gx, Gy: Gy // field prime, curve (group) order, cofactor
|
|
58
|
+
};
|
|
59
|
+
const err = (m = '') => { throw new Error(m); }; // error helper, messes-up stack trace
|
|
60
|
+
const isS = (s) => typeof s === 'string'; // is string
|
|
61
|
+
const isB = (s) => typeof s === 'bigint'; // is bigint
|
|
62
|
+
const isu8 = (a) => (a instanceof Uint8Array || (ArrayBuffer.isView(a) && a.constructor.name === 'Uint8Array'));
|
|
63
|
+
const au8 = (a, l) => // is Uint8Array (of specific length)
|
|
64
|
+
!isu8(a) || (typeof l === 'number' && l > 0 && a.length !== l) ?
|
|
65
|
+
err('Uint8Array of valid length expected') : a;
|
|
66
|
+
const u8n = (len) => new Uint8Array(len); // creates Uint8Array
|
|
67
|
+
const u8fr = (buf) => Uint8Array.from(buf);
|
|
68
|
+
const toU8 = (a, len) => au8(isS(a) ? h2b(a) : u8fr(au8(a, undefined)), len); // norm(hex/u8a) to u8a
|
|
69
|
+
const M = (a, b = P) => { let r = a % b; return r >= 0n ? r : b + r; }; // mod division
|
|
70
|
+
const arange = (n, min, max = MASK, msg = 'bad number: out of range') => isB(n) && min <= n && n < max ? n : err(msg);
|
|
71
|
+
const apoint = (p) => (p instanceof Point ? p : err('Point expected')); // is xyzt point
|
|
72
|
+
/** Point in xyzt extended coordinates. */
|
|
73
|
+
class Point {
|
|
74
|
+
constructor(ex, ey, ez = 1n, et = 0n) {
|
|
75
|
+
this.ex = arange(ex, 0n);
|
|
76
|
+
this.ey = arange(ey, 0n);
|
|
77
|
+
this.ez = arange(ez, 1n);
|
|
78
|
+
this.et = arange(et, 0n);
|
|
79
|
+
Object.freeze(this);
|
|
80
|
+
}
|
|
81
|
+
static fromAffine(p) { return new Point(p.x, p.y, 1n, M(p.x * p.y)); }
|
|
82
|
+
/** RFC8032 5.1.3: hex / Uint8Array to Point. */
|
|
83
|
+
static fromHex(hex, zip215) {
|
|
84
|
+
hex = toU8(hex, 32);
|
|
85
|
+
return this.fromBytes(hex, zip215);
|
|
86
|
+
}
|
|
87
|
+
static fromBase64(b64string) {
|
|
88
|
+
if (isS(b64string))
|
|
89
|
+
return this.fromBytes(base64ToBytes(b64string));
|
|
90
|
+
else
|
|
91
|
+
err("Point.fromBase64 not provided with a string");
|
|
92
|
+
}
|
|
93
|
+
static fromBytes(bytes, zip215 = false) {
|
|
94
|
+
const { d } = CURVE;
|
|
95
|
+
const normed = bytes.slice(); // copy the array to not mess it up
|
|
96
|
+
const lastByte = bytes[31];
|
|
97
|
+
normed[31] = lastByte & ~0x80; // adjust first LE byte = last BE byte
|
|
98
|
+
const y = b2n_LE(normed); // decode as little-endian, convert to num
|
|
99
|
+
const max = zip215 ? MASK : P; // RFC8032 prohibits >= p, ZIP215 doesn't
|
|
100
|
+
arange(y, 0n, max); // zip215=true: 0 <= y < 2^256
|
|
101
|
+
// zip215=false: 0 <= y < 2^255-19
|
|
102
|
+
const y2 = M(y * y); // y²
|
|
103
|
+
const u = M(y2 - 1n); // u=y²-1
|
|
104
|
+
const v = M(d * y2 + 1n); // v=dy²+1
|
|
105
|
+
let { isValid, value: x } = uvRatio(u, v); // (uv³)(uv⁷)^(p-5)/8; square root
|
|
106
|
+
if (!isValid)
|
|
107
|
+
err('bad y coord 3'); // not square root: bad point
|
|
108
|
+
const isXOdd = (x & 1n) === 1n; // adjust sign of x coordinate
|
|
109
|
+
const isLastByteOdd = (lastByte & 0x80) !== 0; // x_0, last bit
|
|
110
|
+
if (!zip215 && x === 0n && isLastByteOdd)
|
|
111
|
+
err('bad y coord 4'); // x=0 and x_0 = 1
|
|
112
|
+
if (isLastByteOdd !== isXOdd)
|
|
113
|
+
x = M(-x);
|
|
114
|
+
return new Point(x, y, 1n, M(x * y)); // Z=1, T=xy
|
|
115
|
+
}
|
|
116
|
+
get x() { return this.toAffine().x; } // .x, .y will call expensive toAffine.
|
|
117
|
+
get y() { return this.toAffine().y; } // Should be used with care.
|
|
118
|
+
assertValidity() {
|
|
119
|
+
const { a, d } = CURVE;
|
|
120
|
+
const p = this;
|
|
121
|
+
if (p.is0())
|
|
122
|
+
throw new Error('bad point: ZERO'); // TODO: optimize, with vars below?
|
|
123
|
+
// Equation in affine coordinates: ax² + y² = 1 + dx²y²
|
|
124
|
+
// Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²
|
|
125
|
+
const { ex: X, ey: Y, ez: Z, et: T } = p;
|
|
126
|
+
const X2 = M(X * X); // X²
|
|
127
|
+
const Y2 = M(Y * Y); // Y²
|
|
128
|
+
const Z2 = M(Z * Z); // Z²
|
|
129
|
+
const Z4 = M(Z2 * Z2); // Z⁴
|
|
130
|
+
const aX2 = M(X2 * a); // aX²
|
|
131
|
+
const left = M(Z2 * M(aX2 + Y2)); // (aX² + Y²)Z²
|
|
132
|
+
const right = M(Z4 + M(d * M(X2 * Y2))); // Z⁴ + dX²Y²
|
|
133
|
+
if (left !== right)
|
|
134
|
+
throw new Error('bad point: equation left != right (1)');
|
|
135
|
+
// In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T
|
|
136
|
+
const XY = M(X * Y);
|
|
137
|
+
const ZT = M(Z * T);
|
|
138
|
+
if (XY !== ZT)
|
|
139
|
+
throw new Error('bad point: equation left != right (2)');
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
equals(other) {
|
|
143
|
+
const { ex: X1, ey: Y1, ez: Z1 } = this;
|
|
144
|
+
const { ex: X2, ey: Y2, ez: Z2 } = apoint(other); // isPoint() checks class equality
|
|
145
|
+
const X1Z2 = M(X1 * Z2), X2Z1 = M(X2 * Z1);
|
|
146
|
+
const Y1Z2 = M(Y1 * Z2), Y2Z1 = M(Y2 * Z1);
|
|
147
|
+
return X1Z2 === X2Z1 && Y1Z2 === Y2Z1;
|
|
148
|
+
}
|
|
149
|
+
is0() { return this.equals(I); }
|
|
150
|
+
negate() {
|
|
151
|
+
return new Point(M(-this.ex), this.ey, this.ez, M(-this.et));
|
|
152
|
+
}
|
|
153
|
+
/** Point doubling. Complete formula. */
|
|
154
|
+
double() {
|
|
155
|
+
const { ex: X1, ey: Y1, ez: Z1 } = this; // Cost: 4M + 4S + 1*a + 6add + 1*2
|
|
156
|
+
const { a } = CURVE; // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd
|
|
157
|
+
const A = M(X1 * X1);
|
|
158
|
+
const B = M(Y1 * Y1);
|
|
159
|
+
const C = M(2n * M(Z1 * Z1));
|
|
160
|
+
const D = M(a * A);
|
|
161
|
+
const x1y1 = X1 + Y1;
|
|
162
|
+
const E = M(M(x1y1 * x1y1) - A - B);
|
|
163
|
+
const G = D + B;
|
|
164
|
+
const F = G - C;
|
|
165
|
+
const H = D - B;
|
|
166
|
+
const X3 = M(E * F);
|
|
167
|
+
const Y3 = M(G * H);
|
|
168
|
+
const T3 = M(E * H);
|
|
169
|
+
const Z3 = M(F * G);
|
|
170
|
+
return new Point(X3, Y3, Z3, T3);
|
|
171
|
+
}
|
|
172
|
+
/** Point addition. Complete formula. */
|
|
173
|
+
add(other) {
|
|
174
|
+
const { ex: X1, ey: Y1, ez: Z1, et: T1 } = this; // Cost: 8M + 1*k + 8add + 1*2.
|
|
175
|
+
const { ex: X2, ey: Y2, ez: Z2, et: T2 } = apoint(other); // doesn't check if other on-curve
|
|
176
|
+
const { a, d } = CURVE; // http://hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#addition-add-2008-hwcd-3
|
|
177
|
+
const A = M(X1 * X2);
|
|
178
|
+
const B = M(Y1 * Y2);
|
|
179
|
+
const C = M(T1 * d * T2);
|
|
180
|
+
const D = M(Z1 * Z2);
|
|
181
|
+
const E = M((X1 + Y1) * (X2 + Y2) - A - B);
|
|
182
|
+
const F = M(D - C);
|
|
183
|
+
const G = M(D + C);
|
|
184
|
+
const H = M(B - a * A);
|
|
185
|
+
const X3 = M(E * F);
|
|
186
|
+
const Y3 = M(G * H);
|
|
187
|
+
const T3 = M(E * H);
|
|
188
|
+
const Z3 = M(F * G);
|
|
189
|
+
return new Point(X3, Y3, Z3, T3);
|
|
190
|
+
}
|
|
191
|
+
mul(n, safe = true) {
|
|
192
|
+
if (n === 0n)
|
|
193
|
+
return safe === true ? err('cannot multiply by 0') : I;
|
|
194
|
+
arange(n, 1n, N);
|
|
195
|
+
if (n === 1n || (!safe && this.is0()))
|
|
196
|
+
return this; // safe=true bans 0. safe=false allows 0.
|
|
197
|
+
if (this.equals(G))
|
|
198
|
+
return wNAF(n).p; // use wNAF precomputes for base points
|
|
199
|
+
let p = I, f = G; // init result point & fake point
|
|
200
|
+
for (let d = this; n > 0n; d = d.double(), n >>= 1n) { // double-and-add ladder
|
|
201
|
+
if (n & 1n)
|
|
202
|
+
p = p.add(d); // if bit is present, add to point
|
|
203
|
+
else if (safe)
|
|
204
|
+
f = f.add(d); // if not, add to fake for timing safety
|
|
205
|
+
}
|
|
206
|
+
return p;
|
|
207
|
+
}
|
|
208
|
+
multiply(scalar) { return this.mul(scalar); } // Aliases for compatibilty
|
|
209
|
+
divide(scalar) { return this.mul(invert(scalar, CURVE.n)); }
|
|
210
|
+
clearCofactor() { return this.mul(BigInt(CURVE.h), false); } // multiply by cofactor
|
|
211
|
+
isSmallOrder() { return this.clearCofactor().is0(); } // check if P is small order
|
|
212
|
+
isTorsionFree() {
|
|
213
|
+
let p = this.mul(N / 2n, false).double(); // ensures the point is not "bad".
|
|
214
|
+
if (N % 2n)
|
|
215
|
+
p = p.add(this); // P^(N+1) // P*N == (P*(N/2))*2+P
|
|
216
|
+
return p.is0();
|
|
217
|
+
}
|
|
218
|
+
/** converts point to 2d xy affine point. (x, y, z, t) ∋ (x=x/z, y=y/z, t=xy). */
|
|
219
|
+
toAffine() {
|
|
220
|
+
const { ex: x, ey: y, ez: z } = this;
|
|
221
|
+
if (this.equals(I))
|
|
222
|
+
return { x: 0n, y: 1n }; // fast-path for zero point
|
|
223
|
+
const iz = invert(z, P); // z^-1: invert z
|
|
224
|
+
if (M(z * iz) !== 1n)
|
|
225
|
+
err('invalid inverse'); // (z * z^-1) must be 1, otherwise bad math
|
|
226
|
+
return { x: M(x * iz), y: M(y * iz) }; // x = x*z^-1; y = y*z^-1
|
|
227
|
+
}
|
|
228
|
+
toRawBytes() {
|
|
229
|
+
const { x, y } = this.toAffine(); // convert to affine 2d point
|
|
230
|
+
this.assertValidity();
|
|
231
|
+
const b = n2b_32LE(y); // encode number to 32 bytes
|
|
232
|
+
b[31] |= x & 1n ? 0x80 : 0; // store sign in first LE byte
|
|
233
|
+
return b;
|
|
234
|
+
}
|
|
235
|
+
toHex() { return b2h(this.toRawBytes()); } // encode to hex string
|
|
236
|
+
toBase64() { return bytesToBase64(this.toRawBytes()); }
|
|
237
|
+
async hash() { return M(b2n_LE(await SHA256_Digest(this.toRawBytes())), CURVE.n); }
|
|
238
|
+
}
|
|
239
|
+
/** Generator / Base point */
|
|
240
|
+
Point.BASE = new Point(Gx, Gy, 1n, M(Gx * Gy));
|
|
241
|
+
/** Identity / Zero point */
|
|
242
|
+
Point.ZERO = new Point(0n, 1n, 1n, 0n);
|
|
243
|
+
const { BASE: G, ZERO: I } = Point; // Generator, identity points
|
|
244
|
+
const padh = (num, pad) => num.toString(16).padStart(pad, '0');
|
|
245
|
+
const b2h = (b) => Array.from(au8(b, undefined)).map(e => padh(e, 2)).join(''); // bytes to hex
|
|
246
|
+
const C = { _0: 48, _9: 57, A: 65, F: 70, a: 97, f: 102 }; // ASCII characters
|
|
247
|
+
const _ch = (ch) => {
|
|
248
|
+
if (ch >= C._0 && ch <= C._9)
|
|
249
|
+
return ch - C._0; // '2' => 50-48
|
|
250
|
+
if (ch >= C.A && ch <= C.F)
|
|
251
|
+
return ch - (C.A - 10); // 'B' => 66-(65-10)
|
|
252
|
+
if (ch >= C.a && ch <= C.f)
|
|
253
|
+
return ch - (C.a - 10); // 'b' => 98-(97-10)
|
|
254
|
+
return;
|
|
255
|
+
};
|
|
256
|
+
const h2b = (hex) => {
|
|
257
|
+
const e = 'hex invalid';
|
|
258
|
+
if (!isS(hex))
|
|
259
|
+
return err(e);
|
|
260
|
+
const hl = hex.length, al = hl / 2;
|
|
261
|
+
if (hl % 2)
|
|
262
|
+
return err(e);
|
|
263
|
+
const array = u8n(al);
|
|
264
|
+
for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { // treat each char as ASCII
|
|
265
|
+
const n1 = _ch(hex.charCodeAt(hi)); // parse first char, multiply it by 16
|
|
266
|
+
const n2 = _ch(hex.charCodeAt(hi + 1)); // parse second char
|
|
267
|
+
if (n1 === undefined || n2 === undefined)
|
|
268
|
+
return err(e);
|
|
269
|
+
array[ai] = n1 * 16 + n2; // example: 'A9' => 10*16 + 9
|
|
270
|
+
}
|
|
271
|
+
return array;
|
|
272
|
+
};
|
|
273
|
+
const n2b_32LE = (num) => h2b(padh(num, 32 * 2)).reverse(); // number to bytes LE
|
|
274
|
+
const b2n_LE = (b) => BigInt('0x' + b2h(u8fr(au8(b, undefined)).reverse())); // bytes LE to num
|
|
275
|
+
const concatB = (...arrs) => {
|
|
276
|
+
const r = u8n(arrs.reduce((sum, a) => sum + au8(a, undefined).length, 0)); // create u8a of summed length
|
|
277
|
+
let pad = 0; // walk through each array,
|
|
278
|
+
arrs.forEach(a => { r.set(a, pad); pad += a.length; }); // ensure they have proper type
|
|
279
|
+
return r;
|
|
280
|
+
};
|
|
281
|
+
const invert = (num, md) => {
|
|
282
|
+
if (!isB(num))
|
|
283
|
+
throw Error("Expecting bigint");
|
|
284
|
+
if (num === 0n || md <= 0n)
|
|
285
|
+
err('no inverse n=' + num + ' mod=' + md); // no neg exponent for now
|
|
286
|
+
let a = M(num, md), b = md, x = 0n, y = 1n, u = 1n, v = 0n;
|
|
287
|
+
while (a !== 0n) { // uses euclidean gcd algorithm
|
|
288
|
+
const q = b / a, r = b % a; // not constant-time
|
|
289
|
+
const m = x - u * q, n = y - v * q;
|
|
290
|
+
b = a, a = r, x = u, y = v, u = m, v = n;
|
|
291
|
+
}
|
|
292
|
+
return b === 1n ? M(x, md) : err('no inverse'); // b is gcd at this point
|
|
293
|
+
};
|
|
294
|
+
const pow2 = (x, power) => {
|
|
295
|
+
let r = x;
|
|
296
|
+
while (power-- > 0n) {
|
|
297
|
+
r *= r;
|
|
298
|
+
r %= P;
|
|
299
|
+
}
|
|
300
|
+
return r;
|
|
301
|
+
};
|
|
302
|
+
const pow_2_252_3 = (x) => {
|
|
303
|
+
const x2 = M(x * x); // x^2, bits 1
|
|
304
|
+
const b2 = M(x2 * x); // x^3, bits 11
|
|
305
|
+
const b4 = M(pow2(b2, 2n) * b2); // x^(2^4-1), bits 1111
|
|
306
|
+
const b5 = M(pow2(b4, 1n) * x); // x^(2^5-1), bits 11111
|
|
307
|
+
const b10 = M(pow2(b5, 5n) * b5); // x^(2^10)
|
|
308
|
+
const b20 = M(pow2(b10, 10n) * b10); // x^(2^20)
|
|
309
|
+
const b40 = M(pow2(b20, 20n) * b20); // x^(2^40)
|
|
310
|
+
const b80 = M(pow2(b40, 40n) * b40); // x^(2^80)
|
|
311
|
+
const b160 = M(pow2(b80, 80n) * b80); // x^(2^160)
|
|
312
|
+
const b240 = M(pow2(b160, 80n) * b80); // x^(2^240)
|
|
313
|
+
const b250 = M(pow2(b240, 10n) * b10); // x^(2^250)
|
|
314
|
+
const pow_p_5_8 = M(pow2(b250, 2n) * x); // < To pow to (p+3)/8, multiply it by x.
|
|
315
|
+
return { pow_p_5_8, b2 };
|
|
316
|
+
};
|
|
317
|
+
const RM1 = 19681161376707505956807079304988542015446066515923890162744021073123829784752n; // √-1
|
|
318
|
+
const uvRatio = (u, v) => {
|
|
319
|
+
const v3 = M(v * v * v); // v³
|
|
320
|
+
const v7 = M(v3 * v3 * v); // v⁷
|
|
321
|
+
const pow = pow_2_252_3(u * v7).pow_p_5_8; // (uv⁷)^(p-5)/8
|
|
322
|
+
let x = M(u * v3 * pow); // (uv³)(uv⁷)^(p-5)/8
|
|
323
|
+
const vx2 = M(v * x * x); // vx²
|
|
324
|
+
const root1 = x; // First root candidate
|
|
325
|
+
const root2 = M(x * RM1); // Second root candidate; RM1 is √-1
|
|
326
|
+
const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root
|
|
327
|
+
const useRoot2 = vx2 === M(-u); // If vx² = -u, set x <-- x * 2^((p-1)/4)
|
|
328
|
+
const noRoot = vx2 === M(BigInt(-1) * u * RM1); // There is no valid root, vx² = -u√-1
|
|
329
|
+
if (useRoot1)
|
|
330
|
+
x = root1;
|
|
331
|
+
if (useRoot2 || noRoot)
|
|
332
|
+
x = root2; // We return root2 anyway, for const-time
|
|
333
|
+
if ((M(x) & 1n) === 1n)
|
|
334
|
+
x = M(-x); // edIsNegative
|
|
335
|
+
return { isValid: useRoot1 || useRoot2, value: x };
|
|
336
|
+
};
|
|
337
|
+
const modL_LE = (hash) => M(b2n_LE(hash), N); // modulo L; but little-endian
|
|
338
|
+
const sha512a = (...m) => etc.sha512Async(...m); // Async SHA512
|
|
339
|
+
const sha512s = (...m) => {
|
|
340
|
+
const fn = etc.sha512Sync;
|
|
341
|
+
if (typeof fn !== 'function')
|
|
342
|
+
err('etc.sha512Sync not set');
|
|
343
|
+
return fn(...m);
|
|
344
|
+
};
|
|
345
|
+
const hash2extK = (hashed) => {
|
|
346
|
+
const head = hashed.slice(0, 32); // slice creates a copy, unlike subarray
|
|
347
|
+
head[0] &= 248; // Clamp bits: 0b1111_1000,
|
|
348
|
+
head[31] &= 127; // 0b0111_1111,
|
|
349
|
+
head[31] |= 64; // 0b0100_0000
|
|
350
|
+
const prefix = hashed.slice(32, 64); // private key "prefix"
|
|
351
|
+
const scalar = modL_LE(head); // modular division over curve order
|
|
352
|
+
const point = G.mul(scalar); // public key point
|
|
353
|
+
const pointBytes = point.toRawBytes(); // point serialized to Uint8Array
|
|
354
|
+
return { head, prefix, scalar, point, pointBytes };
|
|
355
|
+
};
|
|
356
|
+
// RFC8032 5.1.5; getPublicKey async, sync. Hash priv key and extract point.
|
|
357
|
+
const getExtendedPublicKeyAsync = (priv) => sha512a(toU8(priv, 32)).then(hash2extK);
|
|
358
|
+
const getExtendedNonDeterministicPublicKeyAsync = (priv) => {
|
|
359
|
+
const prefix = etc.randomBytes(32); // private key "prefix"
|
|
360
|
+
const point = G.mul(priv); // public key point
|
|
361
|
+
const pointBytes = point.toRawBytes(); // point serialized to Uint8Array
|
|
362
|
+
return { head: undefined, prefix, scalar: priv, point, pointBytes }; // head is undefined as we didn't hash the priv
|
|
363
|
+
};
|
|
364
|
+
const getExtendedPublicKey = (priv) => hash2extK(sha512s(toU8(priv, 32)));
|
|
365
|
+
/** Creates 32-byte ed25519 public key from 32-byte private key. Async. */
|
|
366
|
+
const getPublicKeyAsync = (priv) => getExtendedPublicKeyAsync(priv).then(p => p.pointBytes);
|
|
367
|
+
/** Creates 32-byte ed25519 public key from 32-byte private key. To use, set `etc.sha512Sync` first. */
|
|
368
|
+
const getPublicKey = (priv) => getExtendedPublicKey(priv).pointBytes;
|
|
369
|
+
function hashFinish(asynchronous, res) {
|
|
370
|
+
if (asynchronous)
|
|
371
|
+
return sha512a(res.hashable).then(res.finish);
|
|
372
|
+
return res.finish(sha512s(res.hashable));
|
|
373
|
+
}
|
|
374
|
+
const _sign = (e, rBytes, msg) => {
|
|
375
|
+
const { pointBytes: P, scalar: s } = e;
|
|
376
|
+
const r = modL_LE(rBytes); // r was created outside, reduce it modulo L
|
|
377
|
+
const R = G.mul(r).toRawBytes(); // R = [r]B
|
|
378
|
+
const hashable = concatB(R, P, msg); // dom2(F, C) || R || A || PH(M)
|
|
379
|
+
const finish = (hashed) => {
|
|
380
|
+
const S = M(r + modL_LE(hashed) * s, N); // S = (r + k * s) mod L; 0 <= s < l
|
|
381
|
+
return au8(concatB(R, n2b_32LE(S)), 64); // 64-byte sig: 32b R.x + 32b LE(S)
|
|
382
|
+
};
|
|
383
|
+
return { hashable, finish };
|
|
384
|
+
};
|
|
385
|
+
/** Signs message (NOT message hash) using private key. Async. */
|
|
386
|
+
const signAsync = async (msg, privKey) => {
|
|
387
|
+
const m = toU8(msg); // RFC8032 5.1.6: sign msg with key async
|
|
388
|
+
const e = await getExtendedPublicKeyAsync(privKey); // pub,prfx
|
|
389
|
+
const rBytes = await sha512a(e.prefix, m); // r = SHA512(dom2(F, C) || prefix || PH(M))
|
|
390
|
+
return hashFinish(true, _sign(e, rBytes, m)); // gen R, k, S, then 64-byte signature
|
|
391
|
+
};
|
|
392
|
+
/** Signs message (NOT message hash) using private key without determinism. Async. */
|
|
393
|
+
const signNonDeterministicAsync = async (msg, privKey) => {
|
|
394
|
+
const m = toU8(msg); // RFC8032 5.1.6: sign msg with key async
|
|
395
|
+
const e = await getExtendedNonDeterministicPublicKeyAsync(privKey); // pub,prfx
|
|
396
|
+
const rBytes = await sha512a(e.prefix, m); // r = SHA512(dom2(F, C) || prefix || PH(M))
|
|
397
|
+
return hashFinish(true, _sign(e, rBytes, m)); // gen R, k, S, then 64-byte signature
|
|
398
|
+
};
|
|
399
|
+
/** Signs message (NOT message hash) using private key. To use, set `etc.sha512Sync` first. */
|
|
400
|
+
const sign = (msg, privKey) => {
|
|
401
|
+
const m = toU8(msg); // RFC8032 5.1.6: sign msg with key sync
|
|
402
|
+
const e = getExtendedPublicKey(privKey); // pub,prfx
|
|
403
|
+
const rBytes = sha512s(e.prefix, m); // r = SHA512(dom2(F, C) || prefix || PH(M))
|
|
404
|
+
return hashFinish(false, _sign(e, rBytes, m)); // gen R, k, S, then 64-byte signature
|
|
405
|
+
};
|
|
406
|
+
const dvo = { zip215: false }; // Julio set this to false
|
|
407
|
+
const _verify = (sig, msg, pub, opts = dvo) => {
|
|
408
|
+
sig = toU8(sig, 64); // Signature hex str/Bytes, must be 64 bytes
|
|
409
|
+
msg = toU8(msg); // Message hex str/Bytes
|
|
410
|
+
pub = toU8(pub, 32);
|
|
411
|
+
const { zip215 } = opts; // switch between zip215 and rfc8032 verif
|
|
412
|
+
let A, R, s, SB, hashable = new Uint8Array();
|
|
413
|
+
try {
|
|
414
|
+
A = Point.fromHex(pub, zip215); // public key A decoded
|
|
415
|
+
R = Point.fromHex(sig.slice(0, 32), zip215); // 0 <= R < 2^256: ZIP215 R can be >= P
|
|
416
|
+
s = b2n_LE(sig.slice(32, 64)); // Decode second half as an integer S
|
|
417
|
+
SB = G.mul(s, false); // in the range 0 <= s < L
|
|
418
|
+
hashable = concatB(R.toRawBytes(), A.toRawBytes(), msg); // dom2(F, C) || R || A || PH(M)
|
|
419
|
+
}
|
|
420
|
+
catch (error) { }
|
|
421
|
+
const finish = (hashed) => {
|
|
422
|
+
if (SB == null)
|
|
423
|
+
return false; // false if try-catch catched an error
|
|
424
|
+
if (!zip215 && A.isSmallOrder())
|
|
425
|
+
return false; // false for SBS: Strongly Binding Signature
|
|
426
|
+
const k = modL_LE(hashed); // decode in little-endian, modulo L
|
|
427
|
+
const RkA = R.add(A.mul(k, false)); // [8]R + [8][k]A'
|
|
428
|
+
return RkA.add(SB.negate()).clearCofactor().is0(); // [8][S]B = [8]R + [8][k]A'
|
|
429
|
+
};
|
|
430
|
+
return { hashable, finish };
|
|
431
|
+
};
|
|
432
|
+
// RFC8032 5.1.7: verification async, sync
|
|
433
|
+
/** Verifies signature on message and public key. Async. */
|
|
434
|
+
const verifyAsync = async (s, m, p, opts = dvo) => hashFinish(true, _verify(s, m, p, opts));
|
|
435
|
+
/** Verifies signature on message and public key. To use, set `etc.sha512Sync` first. */
|
|
436
|
+
const verify = (s, m, p, opts = dvo) => hashFinish(false, _verify(s, m, p, opts));
|
|
437
|
+
const cr = () => // We support: 1) browsers 2) node.js 19+
|
|
438
|
+
typeof globalThis === 'object' && 'crypto' in globalThis ? globalThis.crypto : undefined;
|
|
439
|
+
const subtle = () => {
|
|
440
|
+
const c = cr();
|
|
441
|
+
return c && c.subtle || err('crypto.subtle must be defined');
|
|
442
|
+
};
|
|
443
|
+
/** Math, hex, byte helpers. Not in `utils` because utils share API with noble-curves. */
|
|
444
|
+
const etc = {
|
|
445
|
+
bytesToHex: b2h,
|
|
446
|
+
hexToBytes: h2b,
|
|
447
|
+
concatBytes: concatB,
|
|
448
|
+
mod: M,
|
|
449
|
+
invert: invert,
|
|
450
|
+
randomBytes: (len = 32) => {
|
|
451
|
+
const c = cr(); // Can be shimmed in node.js <= 18 to prevent error:
|
|
452
|
+
// import { webcrypto } from 'node:crypto';
|
|
453
|
+
// if (!globalThis.crypto) globalThis.crypto = webcrypto;
|
|
454
|
+
if (!c || !c.getRandomValues)
|
|
455
|
+
err('crypto.getRandomValues must be defined');
|
|
456
|
+
return c.getRandomValues(u8n(len));
|
|
457
|
+
},
|
|
458
|
+
sha512Async: async (...messages) => {
|
|
459
|
+
const s = subtle();
|
|
460
|
+
const m = concatB(...messages);
|
|
461
|
+
return u8n(await s.digest('SHA-512', m.buffer));
|
|
462
|
+
},
|
|
463
|
+
sha512Sync: undefined, // Actual logic below
|
|
464
|
+
bigIntToBytes: n2b_32LE,
|
|
465
|
+
bytesToBigInt: b2n_LE
|
|
466
|
+
};
|
|
467
|
+
/** ed25519-specific key utilities. */
|
|
468
|
+
const utils = {
|
|
469
|
+
getExtendedPublicKeyAsync: getExtendedPublicKeyAsync,
|
|
470
|
+
getExtendedPublicKey: getExtendedPublicKey,
|
|
471
|
+
randomPrivateKey: () => etc.randomBytes(32),
|
|
472
|
+
precompute: (w = 8, p = G) => { p.multiply(3n); w; return p; }, // no-op
|
|
473
|
+
};
|
|
474
|
+
const W = 8; // Precomputes-related code. W = window size
|
|
475
|
+
const scalarBits = 256;
|
|
476
|
+
const pwindows = Math.ceil(scalarBits / W) + 1;
|
|
477
|
+
const pwindowSize = 2 ** (W - 1);
|
|
478
|
+
const precompute = () => {
|
|
479
|
+
const points = []; // 10x sign(), 2x verify(). To achieve this,
|
|
480
|
+
let p = G, b = p; // a lot of points related to base point G.
|
|
481
|
+
for (let w = 0; w < pwindows; w++) { // Points are stored in array and used
|
|
482
|
+
b = p; // any time Gx multiplication is done.
|
|
483
|
+
points.push(b); // They consume 16-32 MiB of RAM.
|
|
484
|
+
for (let i = 1; i < pwindowSize; i++) {
|
|
485
|
+
b = b.add(p);
|
|
486
|
+
points.push(b);
|
|
487
|
+
}
|
|
488
|
+
p = b.double(); // Precomputes don't speed-up getSharedKey,
|
|
489
|
+
} // which multiplies user point by scalar,
|
|
490
|
+
return points; // when precomputes are using base point
|
|
491
|
+
};
|
|
492
|
+
let Gpows = undefined; // precomputes for base point G
|
|
493
|
+
const wNAF = (n) => {
|
|
494
|
+
// Compared to other point mult methods,
|
|
495
|
+
const comp = Gpows || (Gpows = precompute()); // stores 2x less points using subtraction
|
|
496
|
+
const ctneg = (cnd, p) => { let n = p.negate(); return cnd ? n : p; }; // negate
|
|
497
|
+
let p = I, f = G; // f must be G, or could become I in the end
|
|
498
|
+
const pow_2_w = 2 ** W; // W=8 256
|
|
499
|
+
const maxNum = pow_2_w; // W=8 256
|
|
500
|
+
const mask = BigInt(pow_2_w - 1); // W=8 255 == mask 0b11111111
|
|
501
|
+
const shiftBy = BigInt(W); // W=8 8
|
|
502
|
+
for (let w = 0; w < pwindows; w++) {
|
|
503
|
+
let wbits = Number(n & mask); // extract W bits.
|
|
504
|
+
n >>= shiftBy; // shift number by W bits.
|
|
505
|
+
if (wbits > pwindowSize) {
|
|
506
|
+
wbits -= maxNum;
|
|
507
|
+
n += 1n;
|
|
508
|
+
} // split if bits > max: +224 => 256-32
|
|
509
|
+
const off = w * pwindowSize;
|
|
510
|
+
const offF = off, offP = off + Math.abs(wbits) - 1; // offsets, evaluate both
|
|
511
|
+
const isEven = w % 2 !== 0, isNeg = wbits < 0; // conditions, evaluate both
|
|
512
|
+
if (wbits === 0) {
|
|
513
|
+
f = f.add(ctneg(isEven, comp[offF])); // bits are 0: add garbage to fake point
|
|
514
|
+
}
|
|
515
|
+
else { // ^ can't add off2, off2 = I
|
|
516
|
+
p = p.add(ctneg(isNeg, comp[offP])); // bits are 1: add to result point
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return { p, f }; // return both real and fake points for JIT
|
|
520
|
+
}; // !! you can disable precomputes by commenting-out call of the wNAF() inside Point#mul()
|
|
521
|
+
// !! Remove the export to easily use in REPL / browser console
|
|
522
|
+
export { CURVE, etc, Point, getPublicKey, getPublicKeyAsync, sign, signAsync, signNonDeterministicAsync, utils, verify, verifyAsync };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function createAESKey(rawKey: Uint8Array, keyUsage: KeyUsage[]): Promise<CryptoKey>;
|
|
2
|
+
export declare function encryptData(secretData: string | Uint8Array, key: Uint8Array | bigint | string): Promise<string>;
|
|
3
|
+
export declare function encryptDataRawOutput(encodedData: Uint8Array, aesKey: Uint8Array): Promise<Uint8Array<ArrayBuffer>>;
|
|
4
|
+
export declare function decryptData(encryptedData: string, key: Uint8Array | bigint | string): Promise<string>;
|
|
5
|
+
export declare function decryptDataRawOutput(encryptedData: Uint8Array, key: Uint8Array): Promise<Uint8Array<ArrayBuffer>>;
|
|
6
|
+
//# sourceMappingURL=AES.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AES.d.ts","sourceRoot":"","sources":["../../../Cryptide/Encryption/AES.ts"],"names":[],"mappings":"AAsBA,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,sBAQpE;AAED,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,mBAcnG;AACD,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,oCAWrF;AAGD,wBAAsB,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,mBAezF;AAED,wBAAsB,oBAAoB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,oCAapF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Tide Protocol - Infrastructure for a TRUE Zero-Trust paradigm
|
|
3
|
+
// Copyright (C) 2022 Tide Foundation Ltd
|
|
4
|
+
//
|
|
5
|
+
// This program is free software and is subject to the terms of
|
|
6
|
+
// the Tide Community Open Code License as published by the
|
|
7
|
+
// Tide Foundation Limited. You may modify it and redistribute
|
|
8
|
+
// it in accordance with and subject to the terms of that License.
|
|
9
|
+
// This program is distributed WITHOUT WARRANTY of any kind,
|
|
10
|
+
// including without any implied warranty of MERCHANTABILITY or
|
|
11
|
+
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
12
|
+
// See the Tide Community Open Code License for more details.
|
|
13
|
+
// You should have received a copy of the Tide Community Open
|
|
14
|
+
// Code License along with this program.
|
|
15
|
+
// If not, see https://tide.org/licenses_tcoc2-0-0-en
|
|
16
|
+
//
|
|
17
|
+
import { base64ToBytes, BigIntToByteArray, bytesToBase64, ConcatUint8Arrays } from "../Serialization";
|
|
18
|
+
const enc = new TextEncoder();
|
|
19
|
+
const dec = new TextDecoder();
|
|
20
|
+
export function createAESKey(rawKey, keyUsage) {
|
|
21
|
+
return window.crypto.subtle.importKey("raw", rawKey, "AES-GCM", true, keyUsage);
|
|
22
|
+
}
|
|
23
|
+
export async function encryptData(secretData, key) {
|
|
24
|
+
var aesKey;
|
|
25
|
+
if (key instanceof Uint8Array) {
|
|
26
|
+
aesKey = key;
|
|
27
|
+
}
|
|
28
|
+
else if (typeof (key) === 'string') {
|
|
29
|
+
aesKey = enc.encode(key);
|
|
30
|
+
}
|
|
31
|
+
else if (typeof (key) === 'bigint') {
|
|
32
|
+
aesKey = BigIntToByteArray(key);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw Error("Unsupported key type");
|
|
36
|
+
}
|
|
37
|
+
const encoded = typeof (secretData) === 'string' ? enc.encode(secretData) : secretData;
|
|
38
|
+
const encrypted = await encryptDataRawOutput(encoded, aesKey);
|
|
39
|
+
return bytesToBase64(encrypted);
|
|
40
|
+
}
|
|
41
|
+
export async function encryptDataRawOutput(encodedData, aesKey) {
|
|
42
|
+
const cryptoKey = await createAESKey(aesKey, ["encrypt"]);
|
|
43
|
+
// iv will be needed for decryption
|
|
44
|
+
const iv = window.crypto.getRandomValues(new Uint8Array(12));
|
|
45
|
+
const encryptedBuffer = await window.crypto.subtle.encrypt({ name: "AES-GCM", iv: iv }, cryptoKey, encodedData);
|
|
46
|
+
const buff = ConcatUint8Arrays([iv, new Uint8Array(encryptedBuffer)]);
|
|
47
|
+
return buff;
|
|
48
|
+
}
|
|
49
|
+
export async function decryptData(encryptedData, key) {
|
|
50
|
+
var aesKey;
|
|
51
|
+
if (key instanceof Uint8Array) {
|
|
52
|
+
aesKey = key;
|
|
53
|
+
}
|
|
54
|
+
else if (typeof (key) === 'string') {
|
|
55
|
+
aesKey = enc.encode(key);
|
|
56
|
+
}
|
|
57
|
+
else if (typeof (key) === 'bigint') {
|
|
58
|
+
aesKey = BigIntToByteArray(key);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
throw Error("Unsupported key type");
|
|
62
|
+
}
|
|
63
|
+
const encryptedDataBuff = base64ToBytes(encryptedData);
|
|
64
|
+
const decryptedContent = await decryptDataRawOutput(encryptedDataBuff, aesKey);
|
|
65
|
+
return dec.decode(decryptedContent);
|
|
66
|
+
}
|
|
67
|
+
export async function decryptDataRawOutput(encryptedData, key) {
|
|
68
|
+
const aesKey = await createAESKey(key, ["decrypt"]);
|
|
69
|
+
const iv = encryptedData.slice(0, 12);
|
|
70
|
+
const data = encryptedData.slice(12);
|
|
71
|
+
const decryptedContent = await window.crypto.subtle.decrypt({
|
|
72
|
+
name: "AES-GCM",
|
|
73
|
+
iv: iv,
|
|
74
|
+
}, aesKey, data);
|
|
75
|
+
return new Uint8Array(decryptedContent);
|
|
76
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Point } from "../Ed25519";
|
|
2
|
+
export declare function computeSharedKey(pub: Point, priv: bigint | string | Uint8Array): Promise<Uint8Array<ArrayBuffer>>;
|
|
3
|
+
export declare function generateECDHi(pubs: Point[], priv: bigint | string | Uint8Array): Promise<Uint8Array<ArrayBuffer>[]>;
|
|
4
|
+
//# sourceMappingURL=DH.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DH.d.ts","sourceRoot":"","sources":["../../../Cryptide/Encryption/DH.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAInC,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,oCAUpF;AAED,wBAAsB,aAAa,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,sCAIpF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Tide Protocol - Infrastructure for a TRUE Zero-Trust paradigm
|
|
3
|
+
// Copyright (C) 2022 Tide Foundation Ltd
|
|
4
|
+
//
|
|
5
|
+
// This program is free software and is subject to the terms of
|
|
6
|
+
// the Tide Community Open Code License as published by the
|
|
7
|
+
// Tide Foundation Limited. You may modify it and redistribute
|
|
8
|
+
// it in accordance with and subject to the terms of that License.
|
|
9
|
+
// This program is distributed WITHOUT WARRANTY of any kind,
|
|
10
|
+
// including without any implied warranty of MERCHANTABILITY or
|
|
11
|
+
// FITNESS FOR A PARTICULAR PURPOSE.
|
|
12
|
+
// See the Tide Community Open Code License for more details.
|
|
13
|
+
// You should have received a copy of the Tide Community Open
|
|
14
|
+
// Code License along with this program.
|
|
15
|
+
// If not, see https://tide.org/licenses_tcoc2-0-0-en
|
|
16
|
+
//
|
|
17
|
+
import { SHA256_Digest } from "../Hashing/Hash";
|
|
18
|
+
import { BigIntFromByteArray, base64ToBytes } from "../Serialization";
|
|
19
|
+
export async function computeSharedKey(pub, priv) {
|
|
20
|
+
let privNum;
|
|
21
|
+
if (typeof (priv) == "string") {
|
|
22
|
+
privNum = BigIntFromByteArray(base64ToBytes(priv));
|
|
23
|
+
}
|
|
24
|
+
else if (priv instanceof Uint8Array) {
|
|
25
|
+
privNum = BigIntFromByteArray(priv);
|
|
26
|
+
}
|
|
27
|
+
else if (typeof (priv) == "bigint") {
|
|
28
|
+
privNum = priv;
|
|
29
|
+
}
|
|
30
|
+
else
|
|
31
|
+
throw Error("Unknown Type");
|
|
32
|
+
return await SHA256_Digest(pub.mul(privNum).toRawBytes());
|
|
33
|
+
}
|
|
34
|
+
export async function generateECDHi(pubs, priv) {
|
|
35
|
+
const pre_ecdhi = pubs.map(async (pub) => computeSharedKey(pub, priv));
|
|
36
|
+
const ecdhi = await Promise.all(pre_ecdhi);
|
|
37
|
+
return ecdhi;
|
|
38
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Point } from "../Ed25519";
|
|
2
|
+
export default class ElGamal {
|
|
3
|
+
static encryptData(secretData: Uint8Array, publicKey: Point): Promise<string>;
|
|
4
|
+
static encryptDataRaw(secretData: Uint8Array, publicKey: Point): Promise<Uint8Array<ArrayBuffer>>;
|
|
5
|
+
static encryptDataRaw_withAuthentication(secretData: Uint8Array, publicKey: Point, authMsg: Uint8Array): Promise<{
|
|
6
|
+
cipher: Uint8Array<ArrayBuffer>;
|
|
7
|
+
auth: any;
|
|
8
|
+
}>;
|
|
9
|
+
static decryptData(base64_c1_c2: string, k: bigint | Uint8Array): Promise<Uint8Array<ArrayBuffer>>;
|
|
10
|
+
static decryptDataRaw(base64_c1_c2: Uint8Array, k: bigint | Uint8Array): Promise<Uint8Array<ArrayBuffer>>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=ElGamal.d.ts.map
|