@oxy.so/protocol 1.1.4 → 1.2.1
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/.tsbuildinfo +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/platform/crypto.js +4 -7
- package/dist/cjs/platform/crypto.native.js +64 -34
- package/dist/cjs/secp256k1.js +24 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/platform/crypto.js +3 -6
- package/dist/esm/platform/crypto.native.js +63 -33
- package/dist/esm/secp256k1.js +23 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/platform/crypto.d.ts +3 -3
- package/dist/types/platform/crypto.native.d.ts +3 -3
- package/dist/types/platform/expoTypes.d.ts +52 -20
- package/dist/types/secp256k1.d.ts +8 -0
- package/package.json +2 -2
- package/src/__tests__/commonsIdentityBridge.test.ts +109 -0
- package/src/index.ts +9 -2
- package/src/platform/crypto.native.ts +101 -33
- package/src/platform/crypto.ts +19 -8
- package/src/platform/expoTypes.ts +55 -17
- package/src/secp256k1.ts +27 -0
package/dist/cjs/index.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* subpath so they never enter React Native / web bundles.
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.
|
|
14
|
+
exports.loadCommonsIdentityBridge = exports.getRandomBytesRN = exports.loadAsyncStorage = exports.loadSecureStore = exports.loadExpoCrypto = exports.loadNodeCrypto = exports.isNodeJS = exports.isReactNative = exports.isAuthorizedKey = exports.REGISTRATION_POW_DIFFICULTY_BITS = exports.meetsRegistrationPowDifficulty = exports.countLeadingZeroBits = exports.registrationPowMessage = exports.verifyCheckpointSignature = exports.signCheckpoint = exports.checkpointHash = exports.checkpointSigningInput = exports.verifyInclusionProof = exports.inclusionProof = exports.buildTransparencyTreeFromHeads = exports.buildTransparencyTree = exports.transparencyLeafHash = exports.EMPTY_TRANSPARENCY_ROOT = exports.verifyAndAppend = exports.DEFAULT_CLOCK_SKEW_MS = exports.verifyEnvelope = exports.checkContinuity = exports.UNCHAINED_SEQ = exports.verifyEnvelopeSignature = exports.signEnvelope = exports.verifySignature = exports.signMessage = exports.computeRecordId = exports.sha256 = exports.signedRecordSigningInput = exports.canonicalize = void 0;
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
// Envelope — canonical JSON, signing input, content address, signing/verify
|
|
17
17
|
// ---------------------------------------------------------------------------
|
|
@@ -76,4 +76,4 @@ Object.defineProperty(exports, "loadExpoCrypto", { enumerable: true, get: functi
|
|
|
76
76
|
Object.defineProperty(exports, "loadSecureStore", { enumerable: true, get: function () { return crypto_1.loadSecureStore; } });
|
|
77
77
|
Object.defineProperty(exports, "loadAsyncStorage", { enumerable: true, get: function () { return crypto_1.loadAsyncStorage; } });
|
|
78
78
|
Object.defineProperty(exports, "getRandomBytesRN", { enumerable: true, get: function () { return crypto_1.getRandomBytesRN; } });
|
|
79
|
-
Object.defineProperty(exports, "
|
|
79
|
+
Object.defineProperty(exports, "loadCommonsIdentityBridge", { enumerable: true, get: function () { return crypto_1.loadCommonsIdentityBridge; } });
|
|
@@ -111,7 +111,7 @@ exports.loadNodeCrypto = loadNodeCrypto;
|
|
|
111
111
|
exports.loadExpoCrypto = loadExpoCrypto;
|
|
112
112
|
exports.loadSecureStore = loadSecureStore;
|
|
113
113
|
exports.loadAsyncStorage = loadAsyncStorage;
|
|
114
|
-
exports.
|
|
114
|
+
exports.loadCommonsIdentityBridge = loadCommonsIdentityBridge;
|
|
115
115
|
const platform_1 = require("./platform");
|
|
116
116
|
// ---------------------------------------------------------------------------
|
|
117
117
|
// Node `crypto` — Node built-in
|
|
@@ -170,13 +170,10 @@ async function loadAsyncStorage() {
|
|
|
170
170
|
var random_1 = require("./random");
|
|
171
171
|
Object.defineProperty(exports, "getRandomBytesRN", { enumerable: true, get: function () { return random_1.getRandomBytesRN; } });
|
|
172
172
|
// ---------------------------------------------------------------------------
|
|
173
|
-
//
|
|
173
|
+
// Commons identity bridge — the `OxyIdentity` native module (native-only).
|
|
174
174
|
//
|
|
175
|
-
//
|
|
176
|
-
// always resolves to `null`. `@oxy.so/core`'s `KeyManager` treats `null` as "no
|
|
177
|
-
// bridge" and falls back to its package-private store — which is correct on web
|
|
178
|
-
// (there is no shared identity there).
|
|
175
|
+
// Web and Node have no Commons to ask, so this always resolves to `null`.
|
|
179
176
|
// ---------------------------------------------------------------------------
|
|
180
|
-
function
|
|
177
|
+
function loadCommonsIdentityBridge() {
|
|
181
178
|
return Promise.resolve(null);
|
|
182
179
|
}
|
|
@@ -58,7 +58,7 @@ exports.loadNodeCrypto = loadNodeCrypto;
|
|
|
58
58
|
exports.loadExpoCrypto = loadExpoCrypto;
|
|
59
59
|
exports.loadSecureStore = loadSecureStore;
|
|
60
60
|
exports.loadAsyncStorage = loadAsyncStorage;
|
|
61
|
-
exports.
|
|
61
|
+
exports.loadCommonsIdentityBridge = loadCommonsIdentityBridge;
|
|
62
62
|
const expo_modules_core_1 = require("expo-modules-core");
|
|
63
63
|
const optionalPeer_1 = require("./optionalPeer");
|
|
64
64
|
const random_native_1 = require("./random.native");
|
|
@@ -132,41 +132,71 @@ async function loadAsyncStorage() {
|
|
|
132
132
|
// Metro pointed at the same file.
|
|
133
133
|
var random_native_2 = require("./random.native");
|
|
134
134
|
Object.defineProperty(exports, "getRandomBytesRN", { enumerable: true, get: function () { return random_native_2.getRandomBytesRN; } });
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
135
|
+
const LOWER_HEX = /^[0-9a-f]+$/;
|
|
136
|
+
function record(value) {
|
|
137
|
+
return typeof value === 'object' && value !== null ? value : null;
|
|
138
|
+
}
|
|
139
|
+
function hexField(value, length) {
|
|
140
|
+
if (typeof value !== 'string' || !LOWER_HEX.test(value))
|
|
141
|
+
return null;
|
|
142
|
+
if (length !== undefined && value.length !== length)
|
|
143
|
+
return null;
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
function narrowDescription(value) {
|
|
147
|
+
const r = record(value);
|
|
148
|
+
const publicKey = hexField(r?.publicKey, 130);
|
|
149
|
+
const v = typeof r?.v === 'number' ? r.v : Number(r?.v);
|
|
150
|
+
if (!publicKey || !Number.isInteger(v))
|
|
151
|
+
return null;
|
|
152
|
+
return { v, publicKey };
|
|
153
|
+
}
|
|
154
|
+
function narrowProof(value) {
|
|
155
|
+
const r = record(value);
|
|
156
|
+
const publicKey = hexField(r?.publicKey, 130);
|
|
157
|
+
const signature = hexField(r?.signature);
|
|
158
|
+
const timestamp = typeof r?.timestamp === 'number' ? r.timestamp : Number(r?.timestamp);
|
|
159
|
+
if (!publicKey || !signature || !Number.isSafeInteger(timestamp) || timestamp <= 0)
|
|
160
|
+
return null;
|
|
161
|
+
return { publicKey, signature, timestamp };
|
|
162
|
+
}
|
|
163
|
+
function narrowSocialReceive(value) {
|
|
164
|
+
const r = record(value);
|
|
165
|
+
const signature = hexField(r?.signature);
|
|
166
|
+
const publicKey = hexField(r?.publicKey, 66);
|
|
167
|
+
if (!signature || !publicKey)
|
|
168
|
+
return null;
|
|
169
|
+
return { signature, publicKey };
|
|
170
|
+
}
|
|
171
|
+
/** Run one native call; a rejection or an unexpected shape is `null`. */
|
|
172
|
+
async function ask(call, narrow) {
|
|
173
|
+
try {
|
|
174
|
+
return narrow(await call());
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
let commonsIdentityBridgePromise = null;
|
|
181
|
+
function loadCommonsIdentityBridge() {
|
|
182
|
+
if (!commonsIdentityBridgePromise) {
|
|
183
|
+
commonsIdentityBridgePromise = Promise.resolve().then(() => {
|
|
155
184
|
const native = (0, expo_modules_core_1.requireOptionalNativeModule)('OxyIdentity');
|
|
156
|
-
if (native
|
|
157
|
-
typeof native.
|
|
158
|
-
typeof native.
|
|
159
|
-
typeof native.
|
|
160
|
-
typeof native.
|
|
161
|
-
return
|
|
162
|
-
getShared: native.getShared.bind(native),
|
|
163
|
-
putShared: native.putShared.bind(native),
|
|
164
|
-
hasShared: native.hasShared.bind(native),
|
|
165
|
-
clearShared: native.clearShared.bind(native),
|
|
166
|
-
};
|
|
185
|
+
if (!native ||
|
|
186
|
+
typeof native.describe !== 'function' ||
|
|
187
|
+
typeof native.proveIdentity !== 'function' ||
|
|
188
|
+
typeof native.deriveScopedSeed !== 'function' ||
|
|
189
|
+
typeof native.signSocialReceive !== 'function') {
|
|
190
|
+
return null;
|
|
167
191
|
}
|
|
168
|
-
|
|
192
|
+
const m = native;
|
|
193
|
+
return {
|
|
194
|
+
describe: () => ask(() => m.describe(), narrowDescription),
|
|
195
|
+
proveIdentity: (challenge) => ask(() => m.proveIdentity(challenge), narrowProof),
|
|
196
|
+
deriveScopedSeed: (info) => ask(() => m.deriveScopedSeed(info), (v) => hexField(v, 64)),
|
|
197
|
+
signSocialReceive: (index, digest) => ask(() => m.signSocialReceive(index, digest), narrowSocialReceive),
|
|
198
|
+
};
|
|
169
199
|
});
|
|
170
200
|
}
|
|
171
|
-
return
|
|
201
|
+
return commonsIdentityBridgePromise;
|
|
172
202
|
}
|
package/dist/cjs/secp256k1.js
CHANGED
|
@@ -16,6 +16,7 @@ exports.deriveSecp256k1PublicKey = deriveSecp256k1PublicKey;
|
|
|
16
16
|
exports.normalizeSecp256k1PublicKey = normalizeSecp256k1PublicKey;
|
|
17
17
|
exports.signSecp256k1Digest = signSecp256k1Digest;
|
|
18
18
|
exports.verifySecp256k1Digest = verifySecp256k1Digest;
|
|
19
|
+
exports.tweakAddSecp256k1PrivateKey = tweakAddSecp256k1PrivateKey;
|
|
19
20
|
exports.deriveSecp256k1SharedSecret = deriveSecp256k1SharedSecret;
|
|
20
21
|
const secp256k1_js_1 = require("@noble/curves/secp256k1.js");
|
|
21
22
|
const HEX = /^[0-9a-fA-F]+$/;
|
|
@@ -138,6 +139,29 @@ function verifySecp256k1Digest(publicKeyHex, digestHex, signatureDerHex) {
|
|
|
138
139
|
lowS: false,
|
|
139
140
|
});
|
|
140
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* `(privateKey + tweak) mod n`, the scalar step of BIP32 non-hardened child
|
|
144
|
+
* derivation (`CKDpriv`: the tweak is `IL`, the left half of the HMAC-SHA512).
|
|
145
|
+
*
|
|
146
|
+
* Throws, as BIP32 requires, when the tweak is not below the curve order or
|
|
147
|
+
* the sum is zero: that child is invalid and the caller must not use it.
|
|
148
|
+
*/
|
|
149
|
+
function tweakAddSecp256k1PrivateKey(privateKeyHex, tweakHex) {
|
|
150
|
+
const n = secp256k1_js_1.secp256k1.Point.Fn.ORDER;
|
|
151
|
+
const key = BigInt(`0x${normalizeSecp256k1PrivateKey(privateKeyHex)}`);
|
|
152
|
+
if (typeof tweakHex !== "string" || tweakHex.length !== 64 || !HEX.test(tweakHex)) {
|
|
153
|
+
throw new Error("secp256k1 tweak must be exactly 32 bytes of hexadecimal data");
|
|
154
|
+
}
|
|
155
|
+
const tweak = BigInt(`0x${tweakHex}`);
|
|
156
|
+
if (tweak >= n) {
|
|
157
|
+
throw new Error("secp256k1 tweak is not below the curve order");
|
|
158
|
+
}
|
|
159
|
+
const child = (key + tweak) % n;
|
|
160
|
+
if (child === 0n) {
|
|
161
|
+
throw new Error("secp256k1 tweaked private key is zero");
|
|
162
|
+
}
|
|
163
|
+
return child.toString(16).padStart(64, "0");
|
|
164
|
+
}
|
|
141
165
|
/** Derive the fixed-width 32-byte ECDH x-coordinate shared secret. */
|
|
142
166
|
function deriveSecp256k1SharedSecret(privateKeyHex, publicKeyHex) {
|
|
143
167
|
const encodedPoint = secp256k1_js_1.secp256k1.getSharedSecret(parsePrivateKey(privateKeyHex), parsePublicKey(publicKeyHex), true);
|