mirror of
https://github.com/selfxyz/self.git
synced 2026-01-10 07:08:10 -05:00
Replace react-native-quick-crypto with @noble/hashes (#841)
* Add tests for ethers polyfills * Add crypto utils * Inline crypto polyfills into ethers util * sort and update gemfile lock * update lock
This commit is contained in:
@@ -25,8 +25,8 @@ GEM
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.4.0)
|
||||
aws-partitions (1.1140.0)
|
||||
aws-sdk-core (3.228.0)
|
||||
aws-partitions (1.1141.0)
|
||||
aws-sdk-core (3.229.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
@@ -34,10 +34,10 @@ GEM
|
||||
bigdecimal
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
logger
|
||||
aws-sdk-kms (1.109.0)
|
||||
aws-sdk-kms (1.110.0)
|
||||
aws-sdk-core (~> 3, >= 3.228.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.195.0)
|
||||
aws-sdk-s3 (1.196.0)
|
||||
aws-sdk-core (~> 3, >= 3.228.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
|
||||
@@ -1448,29 +1448,6 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-nfc-manager (3.16.1):
|
||||
- React-Core
|
||||
- react-native-quick-crypto (0.7.14):
|
||||
- DoubleConversion
|
||||
- glog
|
||||
- hermes-engine
|
||||
- OpenSSL-Universal
|
||||
- RCT-Folly (= 2024.01.01.00)
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React
|
||||
- React-Core
|
||||
- React-debug
|
||||
- React-Fabric
|
||||
- React-featureflags
|
||||
- React-graphics
|
||||
- React-ImageManager
|
||||
- React-NativeModulesApple
|
||||
- React-RCTFabric
|
||||
- React-rendererdebug
|
||||
- React-utils
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- react-native-safe-area-context (5.5.1):
|
||||
- React-Core
|
||||
- react-native-sqlite-storage (6.0.1):
|
||||
@@ -1930,7 +1907,6 @@ DEPENDENCIES:
|
||||
- react-native-get-random-values (from `../../node_modules/react-native-get-random-values`)
|
||||
- "react-native-netinfo (from `../../node_modules/@react-native-community/netinfo`)"
|
||||
- react-native-nfc-manager (from `../../node_modules/react-native-nfc-manager`)
|
||||
- react-native-quick-crypto (from `../../node_modules/react-native-quick-crypto`)
|
||||
- react-native-safe-area-context (from `../../node_modules/react-native-safe-area-context`)
|
||||
- react-native-sqlite-storage (from `../../node_modules/react-native-sqlite-storage`)
|
||||
- React-nativeconfig (from `../../node_modules/react-native/ReactCommon`)
|
||||
@@ -2094,8 +2070,6 @@ EXTERNAL SOURCES:
|
||||
:path: "../../node_modules/@react-native-community/netinfo"
|
||||
react-native-nfc-manager:
|
||||
:path: "../../node_modules/react-native-nfc-manager"
|
||||
react-native-quick-crypto:
|
||||
:path: "../../node_modules/react-native-quick-crypto"
|
||||
react-native-safe-area-context:
|
||||
:path: "../../node_modules/react-native-safe-area-context"
|
||||
react-native-sqlite-storage:
|
||||
@@ -2261,7 +2235,6 @@ SPEC CHECKSUMS:
|
||||
react-native-get-random-values: d16467cf726c618e9c7a8c3c39c31faa2244bbba
|
||||
react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187
|
||||
react-native-nfc-manager: a280ef94cd4871a471b052f0dc70381cf1223049
|
||||
react-native-quick-crypto: 8c04031798c1902ec3c6f4def538911a8f744d03
|
||||
react-native-safe-area-context: 827032edf27079702cbd006f11dc79451a2d744b
|
||||
react-native-sqlite-storage: 0c84826214baaa498796c7e46a5ccc9a82e114ed
|
||||
React-nativeconfig: 31072ab0146e643594f6959c7f970a04b6c9ddd0
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.27.4",
|
||||
"@ethersproject/shims": "^5.7.0",
|
||||
"@noble/hashes": "^1.5.0",
|
||||
"@openpassport/zk-kit-lean-imt": "^0.0.6",
|
||||
"@openpassport/zk-kit-smt": "^0.0.1",
|
||||
"@peculiar/x509": "^1.12.3",
|
||||
@@ -124,7 +125,6 @@
|
||||
"react-native-localize": "^3.4.1",
|
||||
"react-native-nfc-manager": "^3.15.1",
|
||||
"react-native-passport-reader": "^1.0.3",
|
||||
"react-native-quick-crypto": "^0.7.12",
|
||||
"react-native-safe-area-context": "^5.5.1",
|
||||
"react-native-screens": "4.9.0",
|
||||
"react-native-sqlite-storage": "^6.0.1",
|
||||
|
||||
@@ -1,27 +1,55 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1; Copyright (c) 2025 Social Connect Labs, Inc.; Licensed under BUSL-1.1 (see LICENSE); Apache-2.0 from 2029-06-11
|
||||
|
||||
// https://docs.ethers.org/v6/cookbook/react-native/
|
||||
import { hmac } from '@noble/hashes/hmac';
|
||||
import { pbkdf2 as noblePbkdf2 } from '@noble/hashes/pbkdf2';
|
||||
import { sha256 as nobleSha256 } from '@noble/hashes/sha256';
|
||||
import { sha512 as nobleSha512 } from '@noble/hashes/sha512';
|
||||
import { ethers } from 'ethers';
|
||||
import crypto from 'react-native-quick-crypto';
|
||||
|
||||
ethers.randomBytes.register(length => {
|
||||
return new Uint8Array(crypto.randomBytes(length));
|
||||
});
|
||||
function randomBytes(length: number): Uint8Array {
|
||||
if (typeof globalThis.crypto?.getRandomValues !== 'function') {
|
||||
throw new Error('globalThis.crypto.getRandomValues is not available');
|
||||
}
|
||||
return globalThis.crypto.getRandomValues(new Uint8Array(length));
|
||||
}
|
||||
|
||||
ethers.computeHmac.register((algo, key, data) => {
|
||||
return crypto.createHmac(algo, key).update(data).digest();
|
||||
});
|
||||
function computeHmac(
|
||||
algo: 'sha256' | 'sha512',
|
||||
key: Uint8Array,
|
||||
data: Uint8Array,
|
||||
): Uint8Array {
|
||||
const hash = algo === 'sha256' ? nobleSha256 : nobleSha512;
|
||||
return hmac(hash, key, data);
|
||||
}
|
||||
|
||||
ethers.pbkdf2.register((passwd, salt, iter, keylen, algo) => {
|
||||
return crypto.pbkdf2Sync(passwd, salt, iter, keylen, algo);
|
||||
});
|
||||
function pbkdf2(
|
||||
password: Uint8Array,
|
||||
salt: Uint8Array,
|
||||
iterations: number,
|
||||
keylen: number,
|
||||
algo: 'sha256' | 'sha512',
|
||||
): Uint8Array {
|
||||
const hash = algo === 'sha256' ? nobleSha256 : nobleSha512;
|
||||
return noblePbkdf2(hash, password, salt, { c: iterations, dkLen: keylen });
|
||||
}
|
||||
|
||||
ethers.sha256.register(data => {
|
||||
// @ts-expect-error
|
||||
return crypto.createHash('sha256').update(data).digest();
|
||||
});
|
||||
function sha256(data: Uint8Array): Uint8Array {
|
||||
return nobleSha256.create().update(data).digest();
|
||||
}
|
||||
|
||||
ethers.sha512.register(data => {
|
||||
// @ts-expect-error
|
||||
return crypto.createHash('sha512').update(data).digest();
|
||||
});
|
||||
function sha512(data: Uint8Array): Uint8Array {
|
||||
return nobleSha512.create().update(data).digest();
|
||||
}
|
||||
|
||||
ethers.randomBytes.register(randomBytes);
|
||||
|
||||
ethers.computeHmac.register(computeHmac);
|
||||
|
||||
ethers.pbkdf2.register(pbkdf2);
|
||||
|
||||
ethers.sha256.register(sha256);
|
||||
|
||||
ethers.sha512.register(sha512);
|
||||
|
||||
export { computeHmac, pbkdf2, randomBytes, sha256, sha512 };
|
||||
|
||||
55
app/tests/utils/ethers.test.ts
Normal file
55
app/tests/utils/ethers.test.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1; Copyright (c) 2025 Social Connect Labs, Inc.; Licensed under BUSL-1.1 (see LICENSE); Apache-2.0 from 2029-06-11
|
||||
|
||||
// Register crypto polyfills
|
||||
import '../../src/utils/ethers';
|
||||
|
||||
import { ethers } from 'ethers';
|
||||
|
||||
describe('ethers crypto polyfills', () => {
|
||||
it('randomBytes returns requested length and unique values', () => {
|
||||
const a = ethers.randomBytes(16);
|
||||
const b = ethers.randomBytes(16);
|
||||
|
||||
expect(a).toHaveLength(16);
|
||||
expect(b).toHaveLength(16);
|
||||
expect(ethers.hexlify(a)).not.toBe(ethers.hexlify(b));
|
||||
});
|
||||
|
||||
it('computeHmac matches known vector', () => {
|
||||
const result = ethers.computeHmac(
|
||||
'sha256',
|
||||
ethers.toUtf8Bytes('key'),
|
||||
ethers.toUtf8Bytes('data'),
|
||||
);
|
||||
expect(ethers.hexlify(result)).toBe(
|
||||
'0x5031fe3d989c6d1537a013fa6e739da23463fdaec3b70137d828e36ace221bd0',
|
||||
);
|
||||
});
|
||||
|
||||
it('pbkdf2 derives expected key', () => {
|
||||
const derived = ethers.pbkdf2(
|
||||
ethers.toUtf8Bytes('password'),
|
||||
ethers.toUtf8Bytes('salt'),
|
||||
1000,
|
||||
32,
|
||||
'sha256',
|
||||
);
|
||||
expect(ethers.hexlify(derived)).toBe(
|
||||
'0x632c2812e46d4604102ba7618e9d6d7d2f8128f6266b4a03264d2a0460b7dcb3',
|
||||
);
|
||||
});
|
||||
|
||||
it('sha256 hashes data correctly', () => {
|
||||
const digest = ethers.sha256(ethers.toUtf8Bytes('hello'));
|
||||
expect(ethers.hexlify(digest)).toBe(
|
||||
'0x2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824',
|
||||
);
|
||||
});
|
||||
|
||||
it('sha512 hashes data correctly', () => {
|
||||
const digest = ethers.sha512(ethers.toUtf8Bytes('hello'));
|
||||
expect(ethers.hexlify(digest)).toBe(
|
||||
'0x9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043',
|
||||
);
|
||||
});
|
||||
});
|
||||
56
yarn.lock
56
yarn.lock
@@ -1099,16 +1099,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@craftzdog/react-native-buffer@npm:^6.0.5":
|
||||
version: 6.1.0
|
||||
resolution: "@craftzdog/react-native-buffer@npm:6.1.0"
|
||||
dependencies:
|
||||
ieee754: "npm:^1.2.1"
|
||||
react-native-quick-base64: "npm:^2.0.5"
|
||||
checksum: 10c0/ec6115d5ae1924a329b5ce7bebe147b7e2464e8529088dc1be75d8de67837976f0ecc555b486684a81b7a4e9d779335cf9c9a68afd03849f971e47456b55eafc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@cspotcode/source-map-support@npm:^0.8.0":
|
||||
version: 0.8.1
|
||||
resolution: "@cspotcode/source-map-support@npm:0.8.1"
|
||||
@@ -2570,7 +2560,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@noble/hashes@npm:1.8.0, @noble/hashes@npm:^1.4.0":
|
||||
"@noble/hashes@npm:1.8.0, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:^1.5.0":
|
||||
version: 1.8.0
|
||||
resolution: "@noble/hashes@npm:1.8.0"
|
||||
checksum: 10c0/06a0b52c81a6fa7f04d67762e08b2c476a00285858150caeaaff4037356dd5e119f45b2a530f638b77a5eeca013168ec1b655db41bae3236cb2e9d511484fc77
|
||||
@@ -4623,6 +4613,7 @@ __metadata:
|
||||
"@babel/plugin-transform-private-methods": "npm:^7.23.3"
|
||||
"@babel/runtime": "npm:^7.27.4"
|
||||
"@ethersproject/shims": "npm:^5.7.0"
|
||||
"@noble/hashes": "npm:^1.5.0"
|
||||
"@openpassport/zk-kit-lean-imt": "npm:^0.0.6"
|
||||
"@openpassport/zk-kit-smt": "npm:^0.0.1"
|
||||
"@peculiar/x509": "npm:^1.12.3"
|
||||
@@ -4716,7 +4707,6 @@ __metadata:
|
||||
react-native-localize: "npm:^3.4.1"
|
||||
react-native-nfc-manager: "npm:^3.15.1"
|
||||
react-native-passport-reader: "npm:^1.0.3"
|
||||
react-native-quick-crypto: "npm:^0.7.12"
|
||||
react-native-safe-area-context: "npm:^5.5.1"
|
||||
react-native-screens: "npm:4.9.0"
|
||||
react-native-sqlite-storage: "npm:^6.0.1"
|
||||
@@ -14605,7 +14595,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"events@npm:^3.2.0, events@npm:^3.3.0":
|
||||
"events@npm:^3.2.0":
|
||||
version: 3.3.0
|
||||
resolution: "events@npm:3.3.0"
|
||||
checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6
|
||||
@@ -20586,7 +20576,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"process@npm:^0.11.1, process@npm:^0.11.10":
|
||||
"process@npm:^0.11.1":
|
||||
version: 0.11.10
|
||||
resolution: "process@npm:0.11.10"
|
||||
checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3
|
||||
@@ -21140,29 +21130,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-quick-base64@npm:^2.0.5":
|
||||
version: 2.2.0
|
||||
resolution: "react-native-quick-base64@npm:2.2.0"
|
||||
peerDependencies:
|
||||
react: "*"
|
||||
react-native: "*"
|
||||
checksum: 10c0/f4c800aa3b4932228c406de86d70c8b4183e2522e941736d7edb4fbe7d9b6158e375cd197869a344f551fff8c5e609b4d6eb4d2ce6e8ef61dfb2aef42aadebff
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-quick-crypto@npm:^0.7.12":
|
||||
version: 0.7.14
|
||||
resolution: "react-native-quick-crypto@npm:0.7.14"
|
||||
dependencies:
|
||||
"@craftzdog/react-native-buffer": "npm:^6.0.5"
|
||||
events: "npm:^3.3.0"
|
||||
readable-stream: "npm:^4.5.2"
|
||||
string_decoder: "npm:^1.3.0"
|
||||
util: "npm:^0.12.5"
|
||||
checksum: 10c0/7074fb108f2205a521394128dfe44805fcb56145972ba7e6247e679c51a8b90b7114a400c80a2d9317f3ab317e36787fa89e419fe45549a32db76a41333ca921
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-native-safe-area-context@npm:^5.5.1":
|
||||
version: 5.5.1
|
||||
resolution: "react-native-safe-area-context@npm:5.5.1"
|
||||
@@ -21537,19 +21504,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"readable-stream@npm:^4.5.2":
|
||||
version: 4.7.0
|
||||
resolution: "readable-stream@npm:4.7.0"
|
||||
dependencies:
|
||||
abort-controller: "npm:^3.0.0"
|
||||
buffer: "npm:^6.0.3"
|
||||
events: "npm:^3.3.0"
|
||||
process: "npm:^0.11.10"
|
||||
string_decoder: "npm:^1.3.0"
|
||||
checksum: 10c0/fd86d068da21cfdb10f7a4479f2e47d9c0a9b0c862fc0c840a7e5360201580a55ac399c764b12a4f6fa291f8cee74d9c4b7562e0d53b3c4b2769f2c98155d957
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"readdirp@npm:^4.0.1":
|
||||
version: 4.1.2
|
||||
resolution: "readdirp@npm:4.1.2"
|
||||
@@ -23182,7 +23136,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"string_decoder@npm:^1.1.1, string_decoder@npm:^1.3.0":
|
||||
"string_decoder@npm:^1.1.1":
|
||||
version: 1.3.0
|
||||
resolution: "string_decoder@npm:1.3.0"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user