@oxy.so/core 7.13.1 → 7.14.0
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/dist/cjs/crypto/aead.js +3 -3
- package/dist/cjs/crypto/contentHash.js +4 -4
- package/dist/cjs/crypto/identityDerivations.js +5 -5
- package/dist/cjs/crypto/identityLink.js +3 -3
- package/dist/cjs/crypto/identityProof.js +3 -3
- package/dist/cjs/crypto/index.js +2 -2
- package/dist/cjs/crypto/kdf.js +3 -3
- package/dist/cjs/crypto/polyfill.js +13 -13
- package/dist/cjs/crypto/recoveryPhrase.js +12 -12
- package/dist/cjs/crypto/registrationPow.js +4 -4
- package/dist/cjs/index.js +2 -2
- package/dist/esm/crypto/aead.js +1 -1
- package/dist/esm/crypto/contentHash.js +2 -2
- package/dist/esm/crypto/identityDerivations.js +2 -2
- package/dist/esm/crypto/identityLink.js +2 -2
- package/dist/esm/crypto/identityProof.js +2 -2
- package/dist/esm/crypto/index.js +2 -2
- package/dist/esm/crypto/kdf.js +2 -2
- package/dist/esm/crypto/polyfill.js +13 -13
- package/dist/esm/crypto/recoveryPhrase.js +1 -1
- package/dist/esm/crypto/registrationPow.js +3 -3
- package/dist/esm/index.js +2 -2
- package/dist/types/crypto/polyfill.d.ts +13 -13
- package/dist/types/crypto/registrationPow.d.ts +1 -1
- package/package.json +8 -8
- package/src/crypto/aead.ts +1 -1
- package/src/crypto/contentHash.ts +2 -2
- package/src/crypto/identityDerivations.ts +2 -2
- package/src/crypto/identityLink.ts +2 -2
- package/src/crypto/identityProof.ts +2 -2
- package/src/crypto/index.ts +2 -2
- package/src/crypto/kdf.ts +2 -2
- package/src/crypto/polyfill.ts +13 -13
- package/src/crypto/recoveryPhrase.ts +1 -1
- package/src/crypto/registrationPow.ts +3 -3
- package/src/index.ts +2 -2
package/dist/cjs/crypto/aead.js
CHANGED
|
@@ -27,7 +27,7 @@ exports.decryptAead = decryptAead;
|
|
|
27
27
|
// Loading the polyfill guarantees `globalThis.crypto.getRandomValues` exists on
|
|
28
28
|
// every platform (native crypto on web/Node; expo-crypto-backed shim on RN).
|
|
29
29
|
require("./polyfill");
|
|
30
|
-
const
|
|
30
|
+
const chacha_js_1 = require("@noble/ciphers/chacha.js");
|
|
31
31
|
/** Key length for XChaCha20-Poly1305, in bytes (256-bit). */
|
|
32
32
|
exports.AEAD_KEY_LENGTH = 32;
|
|
33
33
|
/** Nonce length for XChaCha20-Poly1305, in bytes (192-bit). */
|
|
@@ -55,7 +55,7 @@ function randomNonce() {
|
|
|
55
55
|
function encryptAead(key, plaintext, aad) {
|
|
56
56
|
assertKey(key);
|
|
57
57
|
const nonce = randomNonce();
|
|
58
|
-
const ciphertext = (0,
|
|
58
|
+
const ciphertext = (0, chacha_js_1.xchacha20poly1305)(key, nonce, aad).encrypt(plaintext);
|
|
59
59
|
return { nonce, ciphertext };
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
@@ -75,5 +75,5 @@ function decryptAead(key, nonce, ciphertext, aad) {
|
|
|
75
75
|
if (nonce.length !== exports.AEAD_NONCE_LENGTH) {
|
|
76
76
|
throw new Error(`AEAD nonce must be ${exports.AEAD_NONCE_LENGTH} bytes, got ${nonce.length}`);
|
|
77
77
|
}
|
|
78
|
-
return (0,
|
|
78
|
+
return (0, chacha_js_1.xchacha20poly1305)(key, nonce, aad).decrypt(ciphertext);
|
|
79
79
|
}
|
|
@@ -9,14 +9,14 @@ exports.createContentHasher = createContentHasher;
|
|
|
9
9
|
* directly: `@noble/hashes` must load after this entry's polyfill, and through
|
|
10
10
|
* the ONE lazy root, so it never lands in an app's startup JavaScript.
|
|
11
11
|
*/
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
13
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
14
14
|
function createContentHasher() {
|
|
15
|
-
const hash =
|
|
15
|
+
const hash = sha2_js_1.sha256.create();
|
|
16
16
|
return {
|
|
17
17
|
update: (chunk) => {
|
|
18
18
|
hash.update(chunk);
|
|
19
19
|
},
|
|
20
|
-
digestHex: () => (0,
|
|
20
|
+
digestHex: () => (0, utils_js_1.bytesToHex)(hash.digest()),
|
|
21
21
|
};
|
|
22
22
|
}
|
|
@@ -17,8 +17,8 @@ exports.deriveScopedSeedFromKey = deriveScopedSeedFromKey;
|
|
|
17
17
|
exports.deriveSocialReceiveKey = deriveSocialReceiveKey;
|
|
18
18
|
exports.signSocialReceiveDigest = signSocialReceiveDigest;
|
|
19
19
|
exports.authChallengeDigest = authChallengeDigest;
|
|
20
|
-
const
|
|
21
|
-
const
|
|
20
|
+
const hmac_js_1 = require("@noble/hashes/hmac.js");
|
|
21
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
22
22
|
const secp256k1_1 = require("@oxy.so/protocol/secp256k1");
|
|
23
23
|
const kdf_1 = require("./kdf");
|
|
24
24
|
/**
|
|
@@ -73,11 +73,11 @@ function deriveSocialReceiveKey(privateKeyHex, index) {
|
|
|
73
73
|
}
|
|
74
74
|
const privateKey = (0, secp256k1_1.normalizeSecp256k1PrivateKey)(privateKeyHex);
|
|
75
75
|
const parentPublic = hexToBytes((0, secp256k1_1.deriveSecp256k1PublicKey)(privateKey, true));
|
|
76
|
-
const chainCode = (0,
|
|
76
|
+
const chainCode = (0, hmac_js_1.hmac)(sha2_js_1.sha256, utf8(exports.SOCIAL_RECEIVE_CHAIN_CODE_KEY), parentPublic);
|
|
77
77
|
const data = new Uint8Array(37);
|
|
78
78
|
data.set(parentPublic, 0);
|
|
79
79
|
new DataView(data.buffer).setUint32(33, index, false);
|
|
80
|
-
const i = (0,
|
|
80
|
+
const i = (0, hmac_js_1.hmac)(sha2_js_1.sha512, chainCode, data);
|
|
81
81
|
const childPrivate = (0, secp256k1_1.tweakAddSecp256k1PrivateKey)(privateKey, bytesToHex(i.slice(0, 32)));
|
|
82
82
|
return { privateKey: childPrivate, publicKey: (0, secp256k1_1.deriveSecp256k1PublicKey)(childPrivate, true) };
|
|
83
83
|
}
|
|
@@ -101,5 +101,5 @@ function signSocialReceiveDigest(privateKeyHex, index, digestHex) {
|
|
|
101
101
|
* format is the one `POST /auth/verify` checks, unchanged.
|
|
102
102
|
*/
|
|
103
103
|
function authChallengeDigest(publicKey, challenge, timestamp) {
|
|
104
|
-
return bytesToHex((0,
|
|
104
|
+
return bytesToHex((0, sha2_js_1.sha256)(utf8(`auth:${publicKey}:${challenge}:${timestamp}`)));
|
|
105
105
|
}
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.deriveIdentityLinkCode = deriveIdentityLinkCode;
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
12
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
13
13
|
const DOMAIN = 'oxy-identity-link-code/v1';
|
|
14
14
|
function deriveIdentityLinkCode(linkId, publicKey) {
|
|
15
|
-
const digest = (0,
|
|
15
|
+
const digest = (0, sha2_js_1.sha256)((0, utils_js_1.utf8ToBytes)(`${DOMAIN}|${linkId}|${publicKey.trim().toLowerCase()}`));
|
|
16
16
|
const value = ((digest[0] << 24) | (digest[1] << 16) | (digest[2] << 8) | digest[3]) >>> 0;
|
|
17
17
|
return String(value % 1000000).padStart(6, '0');
|
|
18
18
|
}
|
|
@@ -10,13 +10,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.digestIdentityPayload = digestIdentityPayload;
|
|
11
11
|
exports.signIdentityProof = signIdentityProof;
|
|
12
12
|
require("./polyfill");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
14
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
15
15
|
const sign_1 = require("@oxy.so/protocol/sign");
|
|
16
16
|
const client_1 = require("@oxy.so/contracts/client");
|
|
17
17
|
/** SHA-256 hex of the canonical JSON of `payload` — the `payloadDigest` claim. */
|
|
18
18
|
function digestIdentityPayload(payload) {
|
|
19
|
-
return (0,
|
|
19
|
+
return (0, utils_js_1.bytesToHex)((0, sha2_js_1.sha256)((0, utils_js_1.utf8ToBytes)((0, client_1.canonicalJson)(payload))));
|
|
20
20
|
}
|
|
21
21
|
/** Sign `claims` with the root, producing the proof as it travels. */
|
|
22
22
|
async function signIdentityProof(identity, claims) {
|
package/dist/cjs/crypto/index.js
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.verifySignature = exports.signMessage = exports.loadCommonsIdentityBridge = exports.canonicalize = exports.createContentHasher = exports.solveRegistrationPow = exports.deriveIdentityLinkCode = exports.signIdentityProof = exports.digestIdentityPayload = exports.authChallengeDigest = exports.signSocialReceiveDigest = exports.deriveSocialReceiveKey = exports.deriveScopedSeedFromKey = exports.MAX_SOCIAL_RECEIVE_INDEX = exports.SOCIAL_RECEIVE_CHAIN_CODE_KEY = exports.SCOPED_SEED_KDF_SALT = exports.deriveSharedSecret = exports.AEAD_NONCE_LENGTH = exports.AEAD_KEY_LENGTH = exports.decryptAead = exports.encryptAead = exports.hkdfSha256 = exports.BACKUP_KDF_ENCRYPTION_INFO = exports.RecoveryPhraseService = exports.SignatureService = exports.updateIdentityMarker = exports.readIdentityMarker = exports.IdentityUnavailableError = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = void 0;
|
|
16
|
-
// MUST stay the first import:
|
|
17
|
-
//
|
|
16
|
+
// MUST stay the first import: the shim has to exist before any module below
|
|
17
|
+
// evaluates or draws randomness (see `./polyfill`).
|
|
18
18
|
require("./polyfill");
|
|
19
19
|
var keyManager_1 = require("./keyManager");
|
|
20
20
|
Object.defineProperty(exports, "KeyManager", { enumerable: true, get: function () { return keyManager_1.KeyManager; } });
|
package/dist/cjs/crypto/kdf.js
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.hkdfSha256 = hkdfSha256;
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const hkdf_js_1 = require("@noble/hashes/hkdf.js");
|
|
16
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
17
17
|
/**
|
|
18
18
|
* Derive `length` bytes of keying material from `ikm` using HKDF-SHA256
|
|
19
19
|
* (RFC 5869 — extract-then-expand).
|
|
@@ -35,5 +35,5 @@ function hkdfSha256(ikm, salt, info, length) {
|
|
|
35
35
|
if (length > 255 * 32) {
|
|
36
36
|
throw new Error('hkdfSha256: length must not exceed 8160 bytes (255 * 32)');
|
|
37
37
|
}
|
|
38
|
-
return (0,
|
|
38
|
+
return (0, hkdf_js_1.hkdf)(sha2_js_1.sha256, ikm, salt, info, length);
|
|
39
39
|
}
|
|
@@ -18,20 +18,20 @@
|
|
|
18
18
|
* global WebCrypto, and a `require('node:crypto')` here made web bundlers ship
|
|
19
19
|
* Node's crypto, stream and buffer polyfills (~600 KB) to every browser.
|
|
20
20
|
*
|
|
21
|
-
* # Evaluation order — this module must import NOTHING that
|
|
21
|
+
* # Evaluation order — this module must import NOTHING that reaches a crypto library
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* on
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* to `buffer` and `@oxy.so/protocol/random`,
|
|
33
|
-
* and `index.ts` imports this file first.
|
|
34
|
-
* guards both halves.
|
|
23
|
+
* ES imports are evaluated before the importing module's body, so every module
|
|
24
|
+
* this file imports runs BEFORE the shim below is installed. This file used to
|
|
25
|
+
* import `@oxy.so/protocol`'s root entry, which reaches `@noble/curves` →
|
|
26
|
+
* `@noble/hashes` through the envelope signer, and `@noble/hashes` 1.x read
|
|
27
|
+
* `globalThis.crypto` once, at evaluation: on Hermes (no `globalThis.crypto` at
|
|
28
|
+
* startup) it captured `undefined` before the shim existed, and every identity
|
|
29
|
+
* creation on Android failed with `crypto.getRandomValues must be defined`.
|
|
30
|
+
* Noble 2.x reads the global on every call, so that capture is gone, but the
|
|
31
|
+
* shim still has to exist before any module body that reads it runs. Its
|
|
32
|
+
* imports are therefore limited to `buffer` and `@oxy.so/protocol/random`,
|
|
33
|
+
* both free of crypto libraries, and `index.ts` imports this file first.
|
|
34
|
+
* `__tests__/polyfillOrder.test.ts` guards both halves.
|
|
35
35
|
*
|
|
36
36
|
*/
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.RecoveryPhraseService = exports.BACKUP_MATERIAL_LENGTH = exports.BACKUP_KDF_LOOKUP_INFO = exports.BACKUP_KDF_ENCRYPTION_INFO = exports.BACKUP_KDF_SALT = void 0;
|
|
18
18
|
const bip39_1 = require("@scure/bip39");
|
|
19
|
-
const
|
|
19
|
+
const english_js_1 = require("@scure/bip39/wordlists/english.js");
|
|
20
20
|
const keyManager_1 = require("./keyManager");
|
|
21
21
|
const kdf_1 = require("./kdf");
|
|
22
22
|
/**
|
|
@@ -59,7 +59,7 @@ class RecoveryPhraseService {
|
|
|
59
59
|
*/
|
|
60
60
|
static async generateIdentityWithRecovery(options) {
|
|
61
61
|
// Generate 128-bit entropy for 12-word mnemonic
|
|
62
|
-
const mnemonic = (0, bip39_1.generateMnemonic)(
|
|
62
|
+
const mnemonic = (0, bip39_1.generateMnemonic)(english_js_1.wordlist, 128);
|
|
63
63
|
// Derive private key from mnemonic
|
|
64
64
|
// Using the seed directly as the private key (simplified approach)
|
|
65
65
|
const seed = await (0, bip39_1.mnemonicToSeed)(mnemonic);
|
|
@@ -83,7 +83,7 @@ class RecoveryPhraseService {
|
|
|
83
83
|
*/
|
|
84
84
|
static async generateIdentityWithRecovery24(options) {
|
|
85
85
|
// Generate 256-bit entropy for 24-word mnemonic
|
|
86
|
-
const mnemonic = (0, bip39_1.generateMnemonic)(
|
|
86
|
+
const mnemonic = (0, bip39_1.generateMnemonic)(english_js_1.wordlist, 256);
|
|
87
87
|
const seed = await (0, bip39_1.mnemonicToSeed)(mnemonic);
|
|
88
88
|
const privateKeyHex = toHex(seed.subarray(0, 32));
|
|
89
89
|
const publicKey = await keyManager_1.KeyManager.importKeyPair(privateKeyHex, {
|
|
@@ -109,7 +109,7 @@ class RecoveryPhraseService {
|
|
|
109
109
|
* committed anywhere — if it is lost the account becomes unrecoverable.
|
|
110
110
|
*/
|
|
111
111
|
static async derivePendingIdentity() {
|
|
112
|
-
const mnemonic = (0, bip39_1.generateMnemonic)(
|
|
112
|
+
const mnemonic = (0, bip39_1.generateMnemonic)(english_js_1.wordlist, 128);
|
|
113
113
|
const seed = await (0, bip39_1.mnemonicToSeed)(mnemonic);
|
|
114
114
|
const privateKey = toHex(seed.subarray(0, 32));
|
|
115
115
|
const publicKey = keyManager_1.KeyManager.derivePublicKey(privateKey);
|
|
@@ -130,7 +130,7 @@ class RecoveryPhraseService {
|
|
|
130
130
|
*/
|
|
131
131
|
static async derivePrivateKeyFromPhrase(phrase) {
|
|
132
132
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
133
|
-
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
133
|
+
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist)) {
|
|
134
134
|
throw new Error('Invalid recovery phrase');
|
|
135
135
|
}
|
|
136
136
|
const seed = await (0, bip39_1.mnemonicToSeed)(normalizedPhrase);
|
|
@@ -155,7 +155,7 @@ class RecoveryPhraseService {
|
|
|
155
155
|
*/
|
|
156
156
|
static async deriveBackupMaterial(phrase) {
|
|
157
157
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
158
|
-
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
158
|
+
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist)) {
|
|
159
159
|
throw new Error('Invalid recovery phrase. Please check the words and try again.');
|
|
160
160
|
}
|
|
161
161
|
const seed = await (0, bip39_1.mnemonicToSeed)(normalizedPhrase);
|
|
@@ -175,7 +175,7 @@ class RecoveryPhraseService {
|
|
|
175
175
|
static async restoreFromPhrase(phrase, options) {
|
|
176
176
|
// Normalize and validate the phrase
|
|
177
177
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
178
|
-
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
178
|
+
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist)) {
|
|
179
179
|
throw new Error('Invalid recovery phrase. Please check the words and try again.');
|
|
180
180
|
}
|
|
181
181
|
// Derive the same private key from the mnemonic
|
|
@@ -192,26 +192,26 @@ class RecoveryPhraseService {
|
|
|
192
192
|
*/
|
|
193
193
|
static validatePhrase(phrase) {
|
|
194
194
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
195
|
-
return (0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
195
|
+
return (0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist);
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
198
198
|
* Get the word list for autocomplete/validation
|
|
199
199
|
*/
|
|
200
200
|
static getWordList() {
|
|
201
|
-
return
|
|
201
|
+
return english_js_1.wordlist;
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
204
|
* Check if a word is valid in the BIP39 word list
|
|
205
205
|
*/
|
|
206
206
|
static isValidWord(word) {
|
|
207
|
-
return
|
|
207
|
+
return english_js_1.wordlist.includes(word.toLowerCase());
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
210
|
* Get suggestions for a partial word
|
|
211
211
|
*/
|
|
212
212
|
static getSuggestions(partial, limit = 5) {
|
|
213
213
|
const lowerPartial = partial.toLowerCase();
|
|
214
|
-
return
|
|
214
|
+
return english_js_1.wordlist.filter((word) => word.startsWith(lowerPartial)).slice(0, limit);
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
217
|
* Derive the public key from a phrase without storing
|
|
@@ -219,7 +219,7 @@ class RecoveryPhraseService {
|
|
|
219
219
|
*/
|
|
220
220
|
static async derivePublicKeyFromPhrase(phrase) {
|
|
221
221
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
222
|
-
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
222
|
+
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist)) {
|
|
223
223
|
throw new Error('Invalid recovery phrase');
|
|
224
224
|
}
|
|
225
225
|
const seed = await (0, bip39_1.mnemonicToSeed)(normalizedPhrase);
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.solveRegistrationPow = solveRegistrationPow;
|
|
12
12
|
require("./polyfill");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
14
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
15
15
|
const protocol_1 = require("@oxy.so/protocol");
|
|
16
16
|
/**
|
|
17
17
|
* How many attempts the grind loop runs before yielding to the event loop.
|
|
@@ -31,7 +31,7 @@ function yieldToEventLoop() {
|
|
|
31
31
|
* Grind a nonce for `publicKey`/`timestamp` that clears
|
|
32
32
|
* {@link REGISTRATION_POW_DIFFICULTY_BITS}, returned as a decimal counter.
|
|
33
33
|
*
|
|
34
|
-
* Hashes with `@noble/hashes/sha256` — pure JS, synchronous, identical output
|
|
34
|
+
* Hashes with `@noble/hashes/sha2.js`'s `sha256` — pure JS, synchronous, identical output
|
|
35
35
|
* on web/Node/React Native with no native module and no per-attempt bridge
|
|
36
36
|
* crossing (see the difficulty constant's own doc for why that distinction is
|
|
37
37
|
* the whole point). Nonces are sequential (0, 1, 2, …) rather than random: the
|
|
@@ -42,7 +42,7 @@ function yieldToEventLoop() {
|
|
|
42
42
|
async function solveRegistrationPow(publicKey, timestamp) {
|
|
43
43
|
for (let nonce = 0;; nonce += 1) {
|
|
44
44
|
const candidate = String(nonce);
|
|
45
|
-
const digest = (0,
|
|
45
|
+
const digest = (0, utils_js_1.bytesToHex)((0, sha2_js_1.sha256)((0, utils_js_1.utf8ToBytes)((0, protocol_1.registrationPowMessage)(publicKey, timestamp, candidate))));
|
|
46
46
|
if ((0, protocol_1.meetsRegistrationPowDifficulty)(digest, protocol_1.REGISTRATION_POW_DIFFICULTY_BITS)) {
|
|
47
47
|
return candidate;
|
|
48
48
|
}
|
package/dist/cjs/index.js
CHANGED
|
@@ -28,8 +28,8 @@ exports.packageInfo = exports.consumeOAuthReturnPath = exports.persistOAuthRetur
|
|
|
28
28
|
// The crypto shim MUST stay the first import. The root itself ships no crypto
|
|
29
29
|
// library (`__tests__/rootEntryGraph.test.ts`), but `@oxy.so/protocol`'s root
|
|
30
30
|
// entry (reached by the OAuth/PKCE and device helpers) does, and Metro does not
|
|
31
|
-
// tree-shake: on Hermes,
|
|
32
|
-
//
|
|
31
|
+
// tree-shake: on Hermes, the shim has to exist before any of it evaluates. See
|
|
32
|
+
// the note in `./crypto/polyfill`.
|
|
33
33
|
require("./crypto/polyfill");
|
|
34
34
|
// ---------------------------------------------------------------------------
|
|
35
35
|
// API client
|
package/dist/esm/crypto/aead.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
// Loading the polyfill guarantees `globalThis.crypto.getRandomValues` exists on
|
|
23
23
|
// every platform (native crypto on web/Node; expo-crypto-backed shim on RN).
|
|
24
24
|
import './polyfill.js';
|
|
25
|
-
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
|
|
25
|
+
import { xchacha20poly1305 } from '@noble/ciphers/chacha.js';
|
|
26
26
|
/** Key length for XChaCha20-Poly1305, in bytes (256-bit). */
|
|
27
27
|
export const AEAD_KEY_LENGTH = 32;
|
|
28
28
|
/** Nonce length for XChaCha20-Poly1305, in bytes (192-bit). */
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* directly: `@noble/hashes` must load after this entry's polyfill, and through
|
|
7
7
|
* the ONE lazy root, so it never lands in an app's startup JavaScript.
|
|
8
8
|
*/
|
|
9
|
-
import { sha256 } from '@noble/hashes/
|
|
10
|
-
import { bytesToHex } from '@noble/hashes/utils';
|
|
9
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
10
|
+
import { bytesToHex } from '@noble/hashes/utils.js';
|
|
11
11
|
export function createContentHasher() {
|
|
12
12
|
const hash = sha256.create();
|
|
13
13
|
return {
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* ESM/CJS safe: static `import` only, no `require()`.
|
|
12
12
|
*/
|
|
13
|
-
import { hmac } from '@noble/hashes/hmac';
|
|
14
|
-
import { sha256, sha512 } from '@noble/hashes/sha2';
|
|
13
|
+
import { hmac } from '@noble/hashes/hmac.js';
|
|
14
|
+
import { sha256, sha512 } from '@noble/hashes/sha2.js';
|
|
15
15
|
import { deriveSecp256k1PublicKey, normalizeSecp256k1PrivateKey, signSecp256k1Digest, tweakAddSecp256k1PrivateKey, } from '@oxy.so/protocol/secp256k1';
|
|
16
16
|
import { hkdfSha256 } from './kdf.js';
|
|
17
17
|
/**
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* Commons from its own; the person checks they match before the link is
|
|
6
6
|
* confirmed, so a photographed QR cannot slip another key in.
|
|
7
7
|
*/
|
|
8
|
-
import { sha256 } from '@noble/hashes/
|
|
9
|
-
import { utf8ToBytes } from '@noble/hashes/utils';
|
|
8
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
9
|
+
import { utf8ToBytes } from '@noble/hashes/utils.js';
|
|
10
10
|
const DOMAIN = 'oxy-identity-link-code/v1';
|
|
11
11
|
export function deriveIdentityLinkCode(linkId, publicKey) {
|
|
12
12
|
const digest = sha256(utf8ToBytes(`${DOMAIN}|${linkId}|${publicKey.trim().toLowerCase()}`));
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* its own JSON.
|
|
7
7
|
*/
|
|
8
8
|
import './polyfill.js';
|
|
9
|
-
import { sha256 } from '@noble/hashes/
|
|
10
|
-
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';
|
|
9
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
10
|
+
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils.js';
|
|
11
11
|
import { signMessage } from '@oxy.so/protocol/sign';
|
|
12
12
|
import { buildIdentityProofMessage, canonicalJson, IDENTITY_PROOF_VERSION, } from '@oxy.so/contracts/client';
|
|
13
13
|
/** SHA-256 hex of the canonical JSON of `payload` — the `payloadDigest` claim. */
|
package/dist/esm/crypto/index.js
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* internal barrel) made Metro hoist the shared stack into the always-loaded
|
|
11
11
|
* common chunk, which is the cost the lazy loading exists to avoid.
|
|
12
12
|
*/
|
|
13
|
-
// MUST stay the first import:
|
|
14
|
-
//
|
|
13
|
+
// MUST stay the first import: the shim has to exist before any module below
|
|
14
|
+
// evaluates or draws randomness (see `./polyfill`).
|
|
15
15
|
import './polyfill.js';
|
|
16
16
|
export { KeyManager, IdentityAlreadyExistsError, IdentityPersistError, IdentityUnavailableError, } from './keyManager.js';
|
|
17
17
|
export { readIdentityMarker, updateIdentityMarker } from './identityMarker.js';
|
package/dist/esm/crypto/kdf.js
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
*
|
|
10
10
|
* ESM/CJS safe: static `import` only, no `require()`.
|
|
11
11
|
*/
|
|
12
|
-
import { hkdf } from '@noble/hashes/hkdf';
|
|
13
|
-
import { sha256 } from '@noble/hashes/
|
|
12
|
+
import { hkdf } from '@noble/hashes/hkdf.js';
|
|
13
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
14
14
|
/**
|
|
15
15
|
* Derive `length` bytes of keying material from `ikm` using HKDF-SHA256
|
|
16
16
|
* (RFC 5869 — extract-then-expand).
|
|
@@ -17,20 +17,20 @@
|
|
|
17
17
|
* global WebCrypto, and a `require('node:crypto')` here made web bundlers ship
|
|
18
18
|
* Node's crypto, stream and buffer polyfills (~600 KB) to every browser.
|
|
19
19
|
*
|
|
20
|
-
* # Evaluation order — this module must import NOTHING that
|
|
20
|
+
* # Evaluation order — this module must import NOTHING that reaches a crypto library
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* on
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* to `buffer` and `@oxy.so/protocol/random`,
|
|
32
|
-
* and `index.ts` imports this file first.
|
|
33
|
-
* guards both halves.
|
|
22
|
+
* ES imports are evaluated before the importing module's body, so every module
|
|
23
|
+
* this file imports runs BEFORE the shim below is installed. This file used to
|
|
24
|
+
* import `@oxy.so/protocol`'s root entry, which reaches `@noble/curves` →
|
|
25
|
+
* `@noble/hashes` through the envelope signer, and `@noble/hashes` 1.x read
|
|
26
|
+
* `globalThis.crypto` once, at evaluation: on Hermes (no `globalThis.crypto` at
|
|
27
|
+
* startup) it captured `undefined` before the shim existed, and every identity
|
|
28
|
+
* creation on Android failed with `crypto.getRandomValues must be defined`.
|
|
29
|
+
* Noble 2.x reads the global on every call, so that capture is gone, but the
|
|
30
|
+
* shim still has to exist before any module body that reads it runs. Its
|
|
31
|
+
* imports are therefore limited to `buffer` and `@oxy.so/protocol/random`,
|
|
32
|
+
* both free of crypto libraries, and `index.ts` imports this file first.
|
|
33
|
+
* `__tests__/polyfillOrder.test.ts` guards both halves.
|
|
34
34
|
*
|
|
35
35
|
*/
|
|
36
36
|
import _cjs_buffer from 'buffer';
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* app. Adding another language means one more subpath import, ideally lazy.
|
|
14
14
|
*/
|
|
15
15
|
import { generateMnemonic, mnemonicToSeed, validateMnemonic } from '@scure/bip39';
|
|
16
|
-
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
16
|
+
import { wordlist } from '@scure/bip39/wordlists/english.js';
|
|
17
17
|
import { KeyManager } from './keyManager.js';
|
|
18
18
|
import { hkdfSha256 } from './kdf.js';
|
|
19
19
|
/**
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* `auth/registrationPow.ts` — this file is only the solve loop.
|
|
8
8
|
*/
|
|
9
9
|
import './polyfill.js';
|
|
10
|
-
import { sha256 } from '@noble/hashes/
|
|
11
|
-
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';
|
|
10
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
11
|
+
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils.js';
|
|
12
12
|
import { meetsRegistrationPowDifficulty, registrationPowMessage, REGISTRATION_POW_DIFFICULTY_BITS, } from '@oxy.so/protocol';
|
|
13
13
|
/**
|
|
14
14
|
* How many attempts the grind loop runs before yielding to the event loop.
|
|
@@ -28,7 +28,7 @@ function yieldToEventLoop() {
|
|
|
28
28
|
* Grind a nonce for `publicKey`/`timestamp` that clears
|
|
29
29
|
* {@link REGISTRATION_POW_DIFFICULTY_BITS}, returned as a decimal counter.
|
|
30
30
|
*
|
|
31
|
-
* Hashes with `@noble/hashes/sha256` — pure JS, synchronous, identical output
|
|
31
|
+
* Hashes with `@noble/hashes/sha2.js`'s `sha256` — pure JS, synchronous, identical output
|
|
32
32
|
* on web/Node/React Native with no native module and no per-attempt bridge
|
|
33
33
|
* crossing (see the difficulty constant's own doc for why that distinction is
|
|
34
34
|
* the whole point). Nonces are sequential (0, 1, 2, …) rather than random: the
|
package/dist/esm/index.js
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
// The crypto shim MUST stay the first import. The root itself ships no crypto
|
|
23
23
|
// library (`__tests__/rootEntryGraph.test.ts`), but `@oxy.so/protocol`'s root
|
|
24
24
|
// entry (reached by the OAuth/PKCE and device helpers) does, and Metro does not
|
|
25
|
-
// tree-shake: on Hermes,
|
|
26
|
-
//
|
|
25
|
+
// tree-shake: on Hermes, the shim has to exist before any of it evaluates. See
|
|
26
|
+
// the note in `./crypto/polyfill`.
|
|
27
27
|
import './crypto/polyfill.js';
|
|
28
28
|
// ---------------------------------------------------------------------------
|
|
29
29
|
// API client
|
|
@@ -17,20 +17,20 @@
|
|
|
17
17
|
* global WebCrypto, and a `require('node:crypto')` here made web bundlers ship
|
|
18
18
|
* Node's crypto, stream and buffer polyfills (~600 KB) to every browser.
|
|
19
19
|
*
|
|
20
|
-
* # Evaluation order — this module must import NOTHING that
|
|
20
|
+
* # Evaluation order — this module must import NOTHING that reaches a crypto library
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* on
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* to `buffer` and `@oxy.so/protocol/random`,
|
|
32
|
-
* and `index.ts` imports this file first.
|
|
33
|
-
* guards both halves.
|
|
22
|
+
* ES imports are evaluated before the importing module's body, so every module
|
|
23
|
+
* this file imports runs BEFORE the shim below is installed. This file used to
|
|
24
|
+
* import `@oxy.so/protocol`'s root entry, which reaches `@noble/curves` →
|
|
25
|
+
* `@noble/hashes` through the envelope signer, and `@noble/hashes` 1.x read
|
|
26
|
+
* `globalThis.crypto` once, at evaluation: on Hermes (no `globalThis.crypto` at
|
|
27
|
+
* startup) it captured `undefined` before the shim existed, and every identity
|
|
28
|
+
* creation on Android failed with `crypto.getRandomValues must be defined`.
|
|
29
|
+
* Noble 2.x reads the global on every call, so that capture is gone, but the
|
|
30
|
+
* shim still has to exist before any module body that reads it runs. Its
|
|
31
|
+
* imports are therefore limited to `buffer` and `@oxy.so/protocol/random`,
|
|
32
|
+
* both free of crypto libraries, and `index.ts` imports this file first.
|
|
33
|
+
* `__tests__/polyfillOrder.test.ts` guards both halves.
|
|
34
34
|
*
|
|
35
35
|
*/
|
|
36
36
|
import { Buffer } from 'buffer';
|
|
@@ -11,7 +11,7 @@ import './polyfill';
|
|
|
11
11
|
* Grind a nonce for `publicKey`/`timestamp` that clears
|
|
12
12
|
* {@link REGISTRATION_POW_DIFFICULTY_BITS}, returned as a decimal counter.
|
|
13
13
|
*
|
|
14
|
-
* Hashes with `@noble/hashes/sha256` — pure JS, synchronous, identical output
|
|
14
|
+
* Hashes with `@noble/hashes/sha2.js`'s `sha256` — pure JS, synchronous, identical output
|
|
15
15
|
* on web/Node/React Native with no native module and no per-attempt bridge
|
|
16
16
|
* crossing (see the difficulty constant's own doc for why that distinction is
|
|
17
17
|
* the whole point). Nonces are sequential (0, 1, 2, …) rather than random: the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxy.so/core",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.14.0",
|
|
4
4
|
"description": "OxyHQ SDK Foundation — API client, authentication, cryptographic identity, and shared utilities",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
"license": "SEE LICENSE IN LICENSE",
|
|
161
161
|
"homepage": "https://oxy.so",
|
|
162
162
|
"engines": {
|
|
163
|
-
"node": "
|
|
163
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
164
164
|
},
|
|
165
165
|
"scripts": {
|
|
166
166
|
"build": "bun run check:compact-locales && node scripts/build-workspace-deps.mjs @oxy.so/telemetry && bun run build:cjs && bun run build:esm && bun run build:types && node scripts/mark-module-formats.mjs && node -e \"const p='../app-preset/metro/source-stamp.js';require('node:fs').existsSync(p)&&require(p).writeStamp(process.cwd())\"",
|
|
@@ -179,12 +179,12 @@
|
|
|
179
179
|
"test:bun": "cd bun-tests && bun test"
|
|
180
180
|
},
|
|
181
181
|
"dependencies": {
|
|
182
|
-
"@noble/ciphers": "^
|
|
183
|
-
"@noble/hashes": "^
|
|
182
|
+
"@noble/ciphers": "^2.4.0",
|
|
183
|
+
"@noble/hashes": "^2.4.0",
|
|
184
184
|
"@oxy.so/contracts": "6.5.0",
|
|
185
|
-
"@oxy.so/protocol": "^1.
|
|
185
|
+
"@oxy.so/protocol": "^1.6.0",
|
|
186
186
|
"@oxy.so/telemetry": "^2.1.0",
|
|
187
|
-
"@scure/bip39": "^
|
|
187
|
+
"@scure/bip39": "^2.4.0",
|
|
188
188
|
"buffer": "^6.0.3",
|
|
189
189
|
"express-rate-limit": "^8.6.0",
|
|
190
190
|
"helmet": "^8.0.0",
|
|
@@ -195,7 +195,7 @@
|
|
|
195
195
|
"zod": "^4.6.7"
|
|
196
196
|
},
|
|
197
197
|
"peerDependencies": {
|
|
198
|
-
"@react-native-async-storage/async-storage": "<
|
|
198
|
+
"@react-native-async-storage/async-storage": "<4.0.0",
|
|
199
199
|
"expo-crypto": "<59.0.0",
|
|
200
200
|
"expo-secure-store": "<59.0.0",
|
|
201
201
|
"express": "^4.0.0",
|
|
@@ -223,7 +223,7 @@
|
|
|
223
223
|
}
|
|
224
224
|
},
|
|
225
225
|
"devDependencies": {
|
|
226
|
-
"@react-native-async-storage/async-storage": "^
|
|
226
|
+
"@react-native-async-storage/async-storage": "^3.1.1",
|
|
227
227
|
"@types/express": "^4.17.25",
|
|
228
228
|
"@types/invariant": "^2.2.34",
|
|
229
229
|
"@types/node": "^20.19.43",
|
package/src/crypto/aead.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
// Loading the polyfill guarantees `globalThis.crypto.getRandomValues` exists on
|
|
24
24
|
// every platform (native crypto on web/Node; expo-crypto-backed shim on RN).
|
|
25
25
|
import './polyfill';
|
|
26
|
-
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
|
|
26
|
+
import { xchacha20poly1305 } from '@noble/ciphers/chacha.js';
|
|
27
27
|
|
|
28
28
|
/** Key length for XChaCha20-Poly1305, in bytes (256-bit). */
|
|
29
29
|
export const AEAD_KEY_LENGTH = 32;
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* directly: `@noble/hashes` must load after this entry's polyfill, and through
|
|
7
7
|
* the ONE lazy root, so it never lands in an app's startup JavaScript.
|
|
8
8
|
*/
|
|
9
|
-
import { sha256 } from '@noble/hashes/
|
|
10
|
-
import { bytesToHex } from '@noble/hashes/utils';
|
|
9
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
10
|
+
import { bytesToHex } from '@noble/hashes/utils.js';
|
|
11
11
|
|
|
12
12
|
export interface ContentHasher {
|
|
13
13
|
update(chunk: Uint8Array): void;
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* ESM/CJS safe: static `import` only, no `require()`.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import { hmac } from '@noble/hashes/hmac';
|
|
15
|
-
import { sha256, sha512 } from '@noble/hashes/sha2';
|
|
14
|
+
import { hmac } from '@noble/hashes/hmac.js';
|
|
15
|
+
import { sha256, sha512 } from '@noble/hashes/sha2.js';
|
|
16
16
|
import {
|
|
17
17
|
deriveSecp256k1PublicKey,
|
|
18
18
|
normalizeSecp256k1PrivateKey,
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* confirmed, so a photographed QR cannot slip another key in.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { sha256 } from '@noble/hashes/
|
|
10
|
-
import { utf8ToBytes } from '@noble/hashes/utils';
|
|
9
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
10
|
+
import { utf8ToBytes } from '@noble/hashes/utils.js';
|
|
11
11
|
|
|
12
12
|
const DOMAIN = 'oxy-identity-link-code/v1';
|
|
13
13
|
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import './polyfill';
|
|
10
|
-
import { sha256 } from '@noble/hashes/
|
|
11
|
-
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';
|
|
10
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
11
|
+
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils.js';
|
|
12
12
|
import { signMessage } from '@oxy.so/protocol/sign';
|
|
13
13
|
import type { IdentityProof, IdentityProofClaims } from '@oxy.so/contracts';
|
|
14
14
|
import {
|
package/src/crypto/index.ts
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
* common chunk, which is the cost the lazy loading exists to avoid.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
// MUST stay the first import:
|
|
15
|
-
//
|
|
14
|
+
// MUST stay the first import: the shim has to exist before any module below
|
|
15
|
+
// evaluates or draws randomness (see `./polyfill`).
|
|
16
16
|
import './polyfill';
|
|
17
17
|
|
|
18
18
|
export {
|
package/src/crypto/kdf.ts
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
* ESM/CJS safe: static `import` only, no `require()`.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { hkdf } from '@noble/hashes/hkdf';
|
|
14
|
-
import { sha256 } from '@noble/hashes/
|
|
13
|
+
import { hkdf } from '@noble/hashes/hkdf.js';
|
|
14
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Derive `length` bytes of keying material from `ikm` using HKDF-SHA256
|
package/src/crypto/polyfill.ts
CHANGED
|
@@ -17,20 +17,20 @@
|
|
|
17
17
|
* global WebCrypto, and a `require('node:crypto')` here made web bundlers ship
|
|
18
18
|
* Node's crypto, stream and buffer polyfills (~600 KB) to every browser.
|
|
19
19
|
*
|
|
20
|
-
* # Evaluation order — this module must import NOTHING that
|
|
20
|
+
* # Evaluation order — this module must import NOTHING that reaches a crypto library
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* on
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* to `buffer` and `@oxy.so/protocol/random`,
|
|
32
|
-
* and `index.ts` imports this file first.
|
|
33
|
-
* guards both halves.
|
|
22
|
+
* ES imports are evaluated before the importing module's body, so every module
|
|
23
|
+
* this file imports runs BEFORE the shim below is installed. This file used to
|
|
24
|
+
* import `@oxy.so/protocol`'s root entry, which reaches `@noble/curves` →
|
|
25
|
+
* `@noble/hashes` through the envelope signer, and `@noble/hashes` 1.x read
|
|
26
|
+
* `globalThis.crypto` once, at evaluation: on Hermes (no `globalThis.crypto` at
|
|
27
|
+
* startup) it captured `undefined` before the shim existed, and every identity
|
|
28
|
+
* creation on Android failed with `crypto.getRandomValues must be defined`.
|
|
29
|
+
* Noble 2.x reads the global on every call, so that capture is gone, but the
|
|
30
|
+
* shim still has to exist before any module body that reads it runs. Its
|
|
31
|
+
* imports are therefore limited to `buffer` and `@oxy.so/protocol/random`,
|
|
32
|
+
* both free of crypto libraries, and `index.ts` imports this file first.
|
|
33
|
+
* `__tests__/polyfillOrder.test.ts` guards both halves.
|
|
34
34
|
*
|
|
35
35
|
*/
|
|
36
36
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { generateMnemonic, mnemonicToSeed, validateMnemonic } from '@scure/bip39';
|
|
17
|
-
import { wordlist } from '@scure/bip39/wordlists/english';
|
|
17
|
+
import { wordlist } from '@scure/bip39/wordlists/english.js';
|
|
18
18
|
import { KeyManager } from './keyManager';
|
|
19
19
|
import { hkdfSha256 } from './kdf';
|
|
20
20
|
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import './polyfill';
|
|
11
|
-
import { sha256 } from '@noble/hashes/
|
|
12
|
-
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils';
|
|
11
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
12
|
+
import { bytesToHex, utf8ToBytes } from '@noble/hashes/utils.js';
|
|
13
13
|
import {
|
|
14
14
|
meetsRegistrationPowDifficulty,
|
|
15
15
|
registrationPowMessage,
|
|
@@ -36,7 +36,7 @@ function yieldToEventLoop(): Promise<void> {
|
|
|
36
36
|
* Grind a nonce for `publicKey`/`timestamp` that clears
|
|
37
37
|
* {@link REGISTRATION_POW_DIFFICULTY_BITS}, returned as a decimal counter.
|
|
38
38
|
*
|
|
39
|
-
* Hashes with `@noble/hashes/sha256` — pure JS, synchronous, identical output
|
|
39
|
+
* Hashes with `@noble/hashes/sha2.js`'s `sha256` — pure JS, synchronous, identical output
|
|
40
40
|
* on web/Node/React Native with no native module and no per-attempt bridge
|
|
41
41
|
* crossing (see the difficulty constant's own doc for why that distinction is
|
|
42
42
|
* the whole point). Nonces are sequential (0, 1, 2, …) rather than random: the
|
package/src/index.ts
CHANGED
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
// The crypto shim MUST stay the first import. The root itself ships no crypto
|
|
24
24
|
// library (`__tests__/rootEntryGraph.test.ts`), but `@oxy.so/protocol`'s root
|
|
25
25
|
// entry (reached by the OAuth/PKCE and device helpers) does, and Metro does not
|
|
26
|
-
// tree-shake: on Hermes,
|
|
27
|
-
//
|
|
26
|
+
// tree-shake: on Hermes, the shim has to exist before any of it evaluates. See
|
|
27
|
+
// the note in `./crypto/polyfill`.
|
|
28
28
|
import './crypto/polyfill';
|
|
29
29
|
|
|
30
30
|
// ---------------------------------------------------------------------------
|