feat: enable RNQC for encrypt/decrypt
This commit is contained in:
6
.changeset/proud-humans-flash.md
Normal file
6
.changeset/proud-humans-flash.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"jazz-react-native-core": patch
|
||||||
|
"cojson": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Enable react-native-quick-crypto xsalsa20 accelerated algorithm for encrypt/decrypt functions
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -20,6 +20,9 @@ __screenshots__
|
|||||||
# Playwright
|
# Playwright
|
||||||
test-results
|
test-results
|
||||||
|
|
||||||
|
# Java
|
||||||
|
.java-version
|
||||||
|
|
||||||
.husky
|
.husky
|
||||||
|
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export class PureJSCrypto extends CryptoProvider<Blake3State> {
|
|||||||
return this.blake3HashOnce(input).slice(0, 24);
|
return this.blake3HashOnce(input).slice(0, 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateJsonNonce(material: JsonValue): Uint8Array {
|
protected generateJsonNonce(material: JsonValue): Uint8Array {
|
||||||
return this.generateNonce(textEncoder.encode(stableStringify(material)));
|
return this.generateNonce(textEncoder.encode(stableStringify(material)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ import type {
|
|||||||
BinaryStreamInfo,
|
BinaryStreamInfo,
|
||||||
} from "./coValues/coStream.js";
|
} from "./coValues/coStream.js";
|
||||||
import type { InviteSecret } from "./coValues/group.js";
|
import type { InviteSecret } from "./coValues/group.js";
|
||||||
import type { AgentSecret } from "./crypto/crypto.js";
|
import { AgentSecret, textDecoder, textEncoder } from "./crypto/crypto.js";
|
||||||
import type { AgentID, RawCoID, SessionID } from "./ids.js";
|
import type { AgentID, RawCoID, SessionID } from "./ids.js";
|
||||||
import type { JsonObject, JsonValue } from "./jsonValue.js";
|
import type { JsonObject, JsonValue } from "./jsonValue.js";
|
||||||
import type * as Media from "./media.js";
|
import type * as Media from "./media.js";
|
||||||
@@ -108,6 +108,8 @@ export const cojsonInternals = {
|
|||||||
setCoValueLoadingRetryDelay(delay: number) {
|
setCoValueLoadingRetryDelay(delay: number) {
|
||||||
CO_VALUE_LOADING_CONFIG.RETRY_DELAY = delay;
|
CO_VALUE_LOADING_CONFIG.RETRY_DELAY = delay;
|
||||||
},
|
},
|
||||||
|
textEncoder,
|
||||||
|
textDecoder,
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@@ -169,18 +171,19 @@ export type {
|
|||||||
AccountRole,
|
AccountRole,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// biome-ignore format: off
|
||||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
export namespace CojsonInternalTypes {
|
export namespace CojsonInternalTypes {
|
||||||
export type CoValueKnownState = import("./sync.js").CoValueKnownState;
|
export type CoValueKnownState = import("./sync.js").CoValueKnownState;
|
||||||
export type CoJsonValue<T> = import("./jsonValue.js").CoJsonValue<T>;
|
export type CoJsonValue<T> = import("./jsonValue.js").CoJsonValue<T>;
|
||||||
export type DoneMessage = import("./sync.js").DoneMessage;
|
export type DoneMessage = import("./sync.js").DoneMessage;
|
||||||
|
export type Encrypted<T extends JsonValue, N extends JsonValue> = import("./crypto/crypto.js").Encrypted<T, N>;
|
||||||
|
export type KeySecret = import("./crypto/crypto.js").KeySecret;
|
||||||
export type KnownStateMessage = import("./sync.js").KnownStateMessage;
|
export type KnownStateMessage = import("./sync.js").KnownStateMessage;
|
||||||
export type LoadMessage = import("./sync.js").LoadMessage;
|
export type LoadMessage = import("./sync.js").LoadMessage;
|
||||||
export type NewContentMessage = import("./sync.js").NewContentMessage;
|
export type NewContentMessage = import("./sync.js").NewContentMessage;
|
||||||
export type SessionNewContent = import("./sync.js").SessionNewContent;
|
export type SessionNewContent = import("./sync.js").SessionNewContent;
|
||||||
// biome-ignore format: inserts spurious trialing comma that breaks some parsers
|
|
||||||
export type CoValueHeader = import("./coValueCore/verifiedState.js").CoValueHeader;
|
export type CoValueHeader = import("./coValueCore/verifiedState.js").CoValueHeader;
|
||||||
// biome-ignore format: inserts spurious trialing comma that breaks some parsers
|
|
||||||
export type Transaction = import("./coValueCore/verifiedState.js").Transaction;
|
export type Transaction = import("./coValueCore/verifiedState.js").Transaction;
|
||||||
export type TransactionID = import("./ids.js").TransactionID;
|
export type TransactionID = import("./ids.js").TransactionID;
|
||||||
export type Signature = import("./crypto/crypto.js").Signature;
|
export type Signature = import("./crypto/crypto.js").Signature;
|
||||||
@@ -191,3 +194,4 @@ export namespace CojsonInternalTypes {
|
|||||||
export type SignerSecret = import("./crypto/crypto.js").SignerSecret;
|
export type SignerSecret = import("./crypto/crypto.js").SignerSecret;
|
||||||
export type JsonObject = import("./jsonValue.js").JsonObject;
|
export type JsonObject = import("./jsonValue.js").JsonObject;
|
||||||
}
|
}
|
||||||
|
// biome-ignore format: on
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
"cojson-transport-ws": "workspace:*",
|
"cojson-transport-ws": "workspace:*",
|
||||||
"jazz-react-core": "workspace:*",
|
"jazz-react-core": "workspace:*",
|
||||||
"jazz-tools": "workspace:*",
|
"jazz-tools": "workspace:*",
|
||||||
|
"react-native-fast-encoder": "^0.2.0",
|
||||||
"react-native-nitro-modules": "0.25.2",
|
"react-native-nitro-modules": "0.25.2",
|
||||||
"react-native-quick-crypto": "1.0.0-beta.16"
|
"react-native-quick-crypto": "1.0.0-beta.16"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
import { base58 } from "@scure/base";
|
import { base58 } from "@scure/base";
|
||||||
import { JsonValue } from "cojson";
|
import {
|
||||||
|
JsonValue,
|
||||||
|
Stringified,
|
||||||
|
base64URLtoBytes,
|
||||||
|
bytesToBase64url,
|
||||||
|
} from "cojson";
|
||||||
import { CojsonInternalTypes, cojsonInternals } from "cojson";
|
import { CojsonInternalTypes, cojsonInternals } from "cojson";
|
||||||
import { PureJSCrypto } from "cojson/dist/crypto/PureJSCrypto"; // Importing from dist to not rely on the exports field
|
import { PureJSCrypto } from "cojson/dist/crypto/PureJSCrypto"; // Importing from dist to not rely on the exports field
|
||||||
import { Ed } from "react-native-quick-crypto";
|
import { Ed, xsalsa20 } from "react-native-quick-crypto";
|
||||||
const { stableStringify } = cojsonInternals;
|
const { stableStringify } = cojsonInternals;
|
||||||
|
|
||||||
const textEncoder = new TextEncoder();
|
|
||||||
|
|
||||||
export class RNQuickCrypto extends PureJSCrypto {
|
export class RNQuickCrypto extends PureJSCrypto {
|
||||||
ed: Ed;
|
ed: Ed;
|
||||||
|
|
||||||
@@ -30,7 +33,7 @@ export class RNQuickCrypto extends PureJSCrypto {
|
|||||||
): CojsonInternalTypes.Signature {
|
): CojsonInternalTypes.Signature {
|
||||||
const signature = new Uint8Array(
|
const signature = new Uint8Array(
|
||||||
this.ed.signSync(
|
this.ed.signSync(
|
||||||
textEncoder.encode(stableStringify(message)),
|
cojsonInternals.textEncoder.encode(stableStringify(message)),
|
||||||
base58.decode(secret.substring("signerSecret_z".length)),
|
base58.decode(secret.substring("signerSecret_z".length)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -44,8 +47,46 @@ export class RNQuickCrypto extends PureJSCrypto {
|
|||||||
): boolean {
|
): boolean {
|
||||||
return this.ed.verifySync(
|
return this.ed.verifySync(
|
||||||
base58.decode(signature.substring("signature_z".length)),
|
base58.decode(signature.substring("signature_z".length)),
|
||||||
textEncoder.encode(stableStringify(message)),
|
cojsonInternals.textEncoder.encode(stableStringify(message)),
|
||||||
base58.decode(id.substring("signer_z".length)),
|
base58.decode(id.substring("signer_z".length)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encrypt<T extends JsonValue, N extends JsonValue>(
|
||||||
|
value: T,
|
||||||
|
keySecret: CojsonInternalTypes.KeySecret,
|
||||||
|
nOnceMaterial: N,
|
||||||
|
): CojsonInternalTypes.Encrypted<T, N> {
|
||||||
|
const keySecretBytes = base58.decode(
|
||||||
|
keySecret.substring("keySecret_z".length),
|
||||||
|
);
|
||||||
|
const nOnce = this.generateJsonNonce(nOnceMaterial);
|
||||||
|
|
||||||
|
const plaintext = cojsonInternals.textEncoder.encode(
|
||||||
|
stableStringify(value),
|
||||||
|
);
|
||||||
|
const ciphertext = xsalsa20(keySecretBytes, nOnce, plaintext);
|
||||||
|
return `encrypted_U${bytesToBase64url(ciphertext)}` as CojsonInternalTypes.Encrypted<
|
||||||
|
T,
|
||||||
|
N
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptRaw<T extends JsonValue, N extends JsonValue>(
|
||||||
|
encrypted: CojsonInternalTypes.Encrypted<T, N>,
|
||||||
|
keySecret: CojsonInternalTypes.KeySecret,
|
||||||
|
nOnceMaterial: N,
|
||||||
|
): Stringified<T> {
|
||||||
|
const keySecretBytes = base58.decode(
|
||||||
|
keySecret.substring("keySecret_z".length),
|
||||||
|
);
|
||||||
|
const nOnce = this.generateJsonNonce(nOnceMaterial);
|
||||||
|
|
||||||
|
const ciphertext = base64URLtoBytes(
|
||||||
|
encrypted.substring("encrypted_U".length),
|
||||||
|
);
|
||||||
|
const plaintext = xsalsa20(keySecretBytes, nOnce, ciphertext);
|
||||||
|
|
||||||
|
return cojsonInternals.textDecoder.decode(plaintext) as Stringified<T>;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
pnpm-lock.yaml
generated
26
pnpm-lock.yaml
generated
@@ -2616,6 +2616,9 @@ importers:
|
|||||||
jazz-tools:
|
jazz-tools:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../jazz-tools
|
version: link:../jazz-tools
|
||||||
|
react-native-fast-encoder:
|
||||||
|
specifier: ^0.2.0
|
||||||
|
version: 0.2.0(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@15.0.1(typescript@5.6.2))(@types/react@19.0.0)(react@19.0.0))(react@19.0.0)
|
||||||
react-native-nitro-modules:
|
react-native-nitro-modules:
|
||||||
specifier: 0.25.2
|
specifier: 0.25.2
|
||||||
version: 0.25.2(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@15.0.1(typescript@5.6.2))(@types/react@19.0.0)(react@19.0.0))(react@19.0.0)
|
version: 0.25.2(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@15.0.1(typescript@5.6.2))(@types/react@19.0.0)(react@19.0.0))(react@19.0.0)
|
||||||
@@ -9641,6 +9644,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
|
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
|
||||||
|
flatbuffers@2.0.6:
|
||||||
|
resolution: {integrity: sha512-QTTZTXTbVfuOVQu2X6eLOw4vefUxnFJZxAKeN3rEPhjEzBtIbehimJLfVGHPM8iX0Na+9i76SBEg0skf0c0sCA==}
|
||||||
|
|
||||||
flatted@3.3.2:
|
flatted@3.3.2:
|
||||||
resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
|
resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
|
||||||
|
|
||||||
@@ -12527,6 +12533,13 @@ packages:
|
|||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
react-native: '*'
|
react-native: '*'
|
||||||
|
|
||||||
|
react-native-fast-encoder@0.2.0:
|
||||||
|
resolution: {integrity: sha512-E4mx81fRMVs0qq8is3cZTrbuEJdsDo8Nfe7qTxKZwsCianpYpA2QfyH6cEYumSOEht6l+KeRJ4RqcyfxMDyesg==}
|
||||||
|
engines: {node: '>= 18.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
react: 19.0.0
|
||||||
|
react-native: '*'
|
||||||
|
|
||||||
react-native-fetch-api@3.0.0:
|
react-native-fetch-api@3.0.0:
|
||||||
resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==}
|
resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==}
|
||||||
|
|
||||||
@@ -19144,7 +19157,7 @@ snapshots:
|
|||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
eslint-config-prettier: 8.10.0(eslint@8.57.1)
|
eslint-config-prettier: 8.10.0(eslint@8.57.1)
|
||||||
eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.1)
|
eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.1)
|
||||||
eslint-plugin-ft-flow: 2.0.3(@babel/eslint-parser@7.27.0(@babel/core@7.26.0)(eslint@8.57.1))(eslint@8.57.1)
|
eslint-plugin-ft-flow: 2.0.3(@babel/eslint-parser@7.27.0(@babel/core@7.27.1)(eslint@8.57.1))(eslint@8.57.1)
|
||||||
eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(jest@29.7.0(@types/node@22.15.18)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.15.18)(typescript@5.6.2)))(typescript@5.6.2)
|
eslint-plugin-jest: 27.9.0(@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(typescript@5.6.2))(eslint@8.57.1)(jest@29.7.0(@types/node@22.15.18)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@swc/core@1.10.1(@swc/helpers@0.5.15))(@types/node@22.15.18)(typescript@5.6.2)))(typescript@5.6.2)
|
||||||
eslint-plugin-react: 7.37.4(eslint@8.57.1)
|
eslint-plugin-react: 7.37.4(eslint@8.57.1)
|
||||||
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
|
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
|
||||||
@@ -22600,7 +22613,7 @@ snapshots:
|
|||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
ignore: 5.3.2
|
ignore: 5.3.2
|
||||||
|
|
||||||
eslint-plugin-ft-flow@2.0.3(@babel/eslint-parser@7.27.0(@babel/core@7.26.0)(eslint@8.57.1))(eslint@8.57.1):
|
eslint-plugin-ft-flow@2.0.3(@babel/eslint-parser@7.27.0(@babel/core@7.27.1)(eslint@8.57.1))(eslint@8.57.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/eslint-parser': 7.27.0(@babel/core@7.27.1)(eslint@8.57.1)
|
'@babel/eslint-parser': 7.27.0(@babel/core@7.27.1)(eslint@8.57.1)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
@@ -23509,6 +23522,8 @@ snapshots:
|
|||||||
flatted: 3.3.2
|
flatted: 3.3.2
|
||||||
keyv: 4.5.4
|
keyv: 4.5.4
|
||||||
|
|
||||||
|
flatbuffers@2.0.6: {}
|
||||||
|
|
||||||
flatted@3.3.2: {}
|
flatted@3.3.2: {}
|
||||||
|
|
||||||
flatted@3.3.3: {}
|
flatted@3.3.3: {}
|
||||||
@@ -26870,6 +26885,13 @@ snapshots:
|
|||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
react-native: 0.79.2(@babel/core@7.27.1)(@react-native-community/cli@15.0.1(typescript@5.6.2))(@types/react@19.0.0)(react@19.0.0)
|
react-native: 0.79.2(@babel/core@7.27.1)(@react-native-community/cli@15.0.1(typescript@5.6.2))(@types/react@19.0.0)(react@19.0.0)
|
||||||
|
|
||||||
|
react-native-fast-encoder@0.2.0(react-native@0.79.2(@babel/core@7.27.1)(@react-native-community/cli@15.0.1(typescript@5.6.2))(@types/react@19.0.0)(react@19.0.0))(react@19.0.0):
|
||||||
|
dependencies:
|
||||||
|
big-integer: 1.6.52
|
||||||
|
flatbuffers: 2.0.6
|
||||||
|
react: 19.0.0
|
||||||
|
react-native: 0.79.2(@babel/core@7.27.1)(@react-native-community/cli@15.0.1(typescript@5.6.2))(@types/react@19.0.0)(react@19.0.0)
|
||||||
|
|
||||||
react-native-fetch-api@3.0.0:
|
react-native-fetch-api@3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
p-defer: 3.0.0
|
p-defer: 3.0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user