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
|
||||
test-results
|
||||
|
||||
# Java
|
||||
.java-version
|
||||
|
||||
.husky
|
||||
|
||||
.vscode/*
|
||||
|
||||
@@ -67,7 +67,7 @@ export class PureJSCrypto extends CryptoProvider<Blake3State> {
|
||||
return this.blake3HashOnce(input).slice(0, 24);
|
||||
}
|
||||
|
||||
private generateJsonNonce(material: JsonValue): Uint8Array {
|
||||
protected generateJsonNonce(material: JsonValue): Uint8Array {
|
||||
return this.generateNonce(textEncoder.encode(stableStringify(material)));
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ import type {
|
||||
BinaryStreamInfo,
|
||||
} from "./coValues/coStream.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 { JsonObject, JsonValue } from "./jsonValue.js";
|
||||
import type * as Media from "./media.js";
|
||||
@@ -108,6 +108,8 @@ export const cojsonInternals = {
|
||||
setCoValueLoadingRetryDelay(delay: number) {
|
||||
CO_VALUE_LOADING_CONFIG.RETRY_DELAY = delay;
|
||||
},
|
||||
textEncoder,
|
||||
textDecoder,
|
||||
};
|
||||
|
||||
export {
|
||||
@@ -169,18 +171,19 @@ export type {
|
||||
AccountRole,
|
||||
};
|
||||
|
||||
// biome-ignore format: off
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
export namespace CojsonInternalTypes {
|
||||
export type CoValueKnownState = import("./sync.js").CoValueKnownState;
|
||||
export type CoJsonValue<T> = import("./jsonValue.js").CoJsonValue<T>;
|
||||
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 LoadMessage = import("./sync.js").LoadMessage;
|
||||
export type NewContentMessage = import("./sync.js").NewContentMessage;
|
||||
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;
|
||||
// biome-ignore format: inserts spurious trialing comma that breaks some parsers
|
||||
export type Transaction = import("./coValueCore/verifiedState.js").Transaction;
|
||||
export type TransactionID = import("./ids.js").TransactionID;
|
||||
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 JsonObject = import("./jsonValue.js").JsonObject;
|
||||
}
|
||||
// biome-ignore format: on
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"cojson-transport-ws": "workspace:*",
|
||||
"jazz-react-core": "workspace:*",
|
||||
"jazz-tools": "workspace:*",
|
||||
"react-native-fast-encoder": "^0.2.0",
|
||||
"react-native-nitro-modules": "0.25.2",
|
||||
"react-native-quick-crypto": "1.0.0-beta.16"
|
||||
},
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { base58 } from "@scure/base";
|
||||
import { JsonValue } from "cojson";
|
||||
import {
|
||||
JsonValue,
|
||||
Stringified,
|
||||
base64URLtoBytes,
|
||||
bytesToBase64url,
|
||||
} 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 { Ed } from "react-native-quick-crypto";
|
||||
import { Ed, xsalsa20 } from "react-native-quick-crypto";
|
||||
const { stableStringify } = cojsonInternals;
|
||||
|
||||
const textEncoder = new TextEncoder();
|
||||
|
||||
export class RNQuickCrypto extends PureJSCrypto {
|
||||
ed: Ed;
|
||||
|
||||
@@ -30,7 +33,7 @@ export class RNQuickCrypto extends PureJSCrypto {
|
||||
): CojsonInternalTypes.Signature {
|
||||
const signature = new Uint8Array(
|
||||
this.ed.signSync(
|
||||
textEncoder.encode(stableStringify(message)),
|
||||
cojsonInternals.textEncoder.encode(stableStringify(message)),
|
||||
base58.decode(secret.substring("signerSecret_z".length)),
|
||||
),
|
||||
);
|
||||
@@ -44,8 +47,46 @@ export class RNQuickCrypto extends PureJSCrypto {
|
||||
): boolean {
|
||||
return this.ed.verifySync(
|
||||
base58.decode(signature.substring("signature_z".length)),
|
||||
textEncoder.encode(stableStringify(message)),
|
||||
cojsonInternals.textEncoder.encode(stableStringify(message)),
|
||||
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:
|
||||
specifier: workspace:*
|
||||
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:
|
||||
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)
|
||||
@@ -9641,6 +9644,9 @@ packages:
|
||||
resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
flatbuffers@2.0.6:
|
||||
resolution: {integrity: sha512-QTTZTXTbVfuOVQu2X6eLOw4vefUxnFJZxAKeN3rEPhjEzBtIbehimJLfVGHPM8iX0Na+9i76SBEg0skf0c0sCA==}
|
||||
|
||||
flatted@3.3.2:
|
||||
resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==}
|
||||
|
||||
@@ -12527,6 +12533,13 @@ packages:
|
||||
react: 19.0.0
|
||||
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:
|
||||
resolution: {integrity: sha512-g2rtqPjdroaboDKTsJCTlcmtw54E25OjyaunUP0anOZn4Fuo2IKs8BVfe02zVggA/UysbmfSnRJIqtNkAgggNA==}
|
||||
|
||||
@@ -19144,7 +19157,7 @@ snapshots:
|
||||
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-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-react: 7.37.4(eslint@8.57.1)
|
||||
eslint-plugin-react-hooks: 4.6.2(eslint@8.57.1)
|
||||
@@ -22600,7 +22613,7 @@ snapshots:
|
||||
eslint: 8.57.1
|
||||
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:
|
||||
'@babel/eslint-parser': 7.27.0(@babel/core@7.27.1)(eslint@8.57.1)
|
||||
eslint: 8.57.1
|
||||
@@ -23509,6 +23522,8 @@ snapshots:
|
||||
flatted: 3.3.2
|
||||
keyv: 4.5.4
|
||||
|
||||
flatbuffers@2.0.6: {}
|
||||
|
||||
flatted@3.3.2: {}
|
||||
|
||||
flatted@3.3.3: {}
|
||||
@@ -26870,6 +26885,13 @@ snapshots:
|
||||
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:
|
||||
dependencies:
|
||||
p-defer: 3.0.0
|
||||
|
||||
Reference in New Issue
Block a user