Skip to content

Commit 111c0b8

Browse files
authored
feat: ed25519 API improvements (#560)
1 parent e371bcb commit 111c0b8

File tree

14 files changed

+141
-87
lines changed

14 files changed

+141
-87
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,5 @@ tsconfig.tsbuildinfo
184184
.java-version
185185

186186
# development stuffs
187-
example0/
188187
*scratch*
189188

bun.lockb

38.1 KB
Binary file not shown.

example/ios/Podfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ PODS:
3131
- ReactCommon/turbomodule/core
3232
- Yoga
3333
- OpenSSL-Universal (3.3.2000)
34-
- QuickCrypto (1.0.0-beta.5):
34+
- QuickCrypto (1.0.0-beta.7):
3535
- DoubleConversion
3636
- glog
3737
- hermes-engine
@@ -1720,7 +1720,7 @@ DEPENDENCIES:
17201720
- glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`)
17211721
- hermes-engine (from `../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
17221722
- NitroModules (from `../../node_modules/react-native-nitro-modules`)
1723-
- QuickCrypto (from `../node_modules/react-native-quick-crypto`)
1723+
- QuickCrypto (from `../../node_modules/react-native-quick-crypto`)
17241724
- RCT-Folly (from `../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
17251725
- RCT-Folly/Fabric (from `../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
17261726
- RCTDeprecation (from `../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`)
@@ -1807,7 +1807,7 @@ EXTERNAL SOURCES:
18071807
NitroModules:
18081808
:path: "../../node_modules/react-native-nitro-modules"
18091809
QuickCrypto:
1810-
:path: "../node_modules/react-native-quick-crypto"
1810+
:path: "../../node_modules/react-native-quick-crypto"
18111811
RCT-Folly:
18121812
:podspec: "../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
18131813
RCTDeprecation:
@@ -1940,7 +1940,7 @@ SPEC CHECKSUMS:
19401940
hermes-engine: 46f1ffbf0297f4298862068dd4c274d4ac17a1fd
19411941
NitroModules: 47399393665e69228b29a17f501c7b453679ccc0
19421942
OpenSSL-Universal: b60a3702c9fea8b3145549d421fdb018e53ab7b4
1943-
QuickCrypto: 8d76ae3a0bf60509f671193eb4ed666a80da34cb
1943+
QuickCrypto: 2a4bcacfec3cc81d56205e6b12f190d492f9a1e7
19441944
RCT-Folly: 84578c8756030547307e4572ab1947de1685c599
19451945
RCTDeprecation: fde92935b3caa6cb65cbff9fbb7d3a9867ffb259
19461946
RCTRequired: 75c6cee42d21c1530a6f204ba32ff57335d19007

example/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"devDependencies": {
4848
"@babel/core": "7.25.2",
4949
"@babel/plugin-transform-class-static-block": "7.26.0",
50-
"@babel/preset-env": "7.25.3",
50+
"@babel/preset-env": "7.26.0",
5151
"@babel/runtime": "7.25.0",
5252
"@eslint/compat": "^1.1.1",
5353
"@eslint/js": "^9.9.0",

example/src/tests/ed25519/ed25519_tests.ts

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/* eslint-disable @typescript-eslint/no-unused-expressions */
22
import { Ed, randomBytes, ab2str } from 'react-native-quick-crypto';
3+
import { Buffer } from '@craftzdog/react-native-buffer';
34
// import type {
45
// // KeyObject,
56
// // CFRGKeyPairType,
@@ -12,6 +13,10 @@ import { test } from '../util';
1213

1314
const SUITE = 'ed25519';
1415

16+
const encoder = new TextEncoder();
17+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
18+
const encode = (data: any): Uint8Array => encoder.encode(JSON.stringify(data));
19+
1520
/*
1621
const jwkOptions: GenerateKeyPairOptions = {
1722
publicKeyEncoding: {
@@ -75,25 +80,30 @@ test(SUITE, 'sign/verify - bad signature does not verify', async () => {
7580
expect(verified).to.be.false;
7681
});
7782

78-
test(
79-
SUITE,
80-
'sign/verify with non-internally generated private key',
81-
async () => {
82-
let ed1: Ed | null = new Ed('ed25519', {});
83-
await ed1.generateKeyPair();
84-
const priv = ed1.getPrivateKey();
85-
ed1 = null;
83+
test(SUITE, 'sign/verify - switched args does not verify', async () => {
84+
const ed = new Ed('ed25519', {});
85+
await ed.generateKeyPair();
86+
const signature = await ed.sign(data1.buffer);
87+
// verify(message, signature) is switched
88+
const verified = await ed.verify(data1.buffer, signature);
89+
expect(verified).to.be.false;
90+
});
8691

87-
const ed2 = new Ed('ed25519', {});
88-
const signature = await ed2.sign(data1.buffer, priv);
89-
const verified = await ed2.verify(signature, data1.buffer, priv);
90-
expect(verified).to.be.true;
91-
},
92-
);
92+
test(SUITE, 'sign/verify - non-internally generated private key', async () => {
93+
let ed1: Ed | null = new Ed('ed25519', {});
94+
await ed1.generateKeyPair();
95+
const priv = ed1.getPrivateKey();
96+
ed1 = null;
97+
98+
const ed2 = new Ed('ed25519', {});
99+
const signature = await ed2.sign(data1.buffer, priv);
100+
const verified = await ed2.verify(signature, data1.buffer, priv);
101+
expect(verified).to.be.true;
102+
});
93103

94104
test(
95105
SUITE,
96-
'sign/verify with bad non-internally generated private key',
106+
'sign/verify - bad non-internally generated private key',
97107
async () => {
98108
let ed1: Ed | null = new Ed('ed25519', {});
99109
await ed1.generateKeyPair();
@@ -108,3 +118,16 @@ test(
108118
expect(verified).to.be.false;
109119
},
110120
);
121+
122+
test(SUITE, 'sign/verify - Uint8Arrays', () => {
123+
const data = { b: 'world', a: 'hello' };
124+
125+
const ed1 = new Ed('ed25519', {});
126+
ed1.generateKeyPairSync();
127+
const priv = new Uint8Array(ed1.getPrivateKey());
128+
129+
const ed2 = new Ed('ed25519', {});
130+
const signature = new Uint8Array(ed2.signSync(encode(data), priv));
131+
const verified = ed2.verifySync(signature, encode(data), priv);
132+
expect(verified).to.be.true;
133+
});

example/tsconfig.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
"**.*.tsx",
1212
],
1313
"compilerOptions": {
14-
"jsx": "react"
14+
"jsx": "react",
15+
"paths": {
16+
"react-native-quick-crypto": ["../packages/react-native-quick-crypto/src"],
17+
},
1518
},
1619
}

packages/react-native-quick-crypto/QuickCrypto.podspec

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ require "json"
22

33
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
44

5-
Pod::UI.puts "[QuickCrypto] crypto just got quicker 💨"
5+
Pod::UI.puts "[QuickCrypto] 💨 crypto just got quicker"
66

77
Pod::Spec.new do |s|
88
s.name = "QuickCrypto"
@@ -12,7 +12,11 @@ Pod::Spec.new do |s|
1212
s.license = package["license"]
1313
s.authors = package["authors"]
1414

15-
s.platforms = { :ios => min_ios_version_supported }
15+
s.ios.deployment_target = min_ios_version_supported
16+
s.visionos.deployment_target = 1.0
17+
s.macos.deployment_target = 10.13
18+
s.tvos.deployment_target = 13.4
19+
1620
s.source = { :git => "https://github.com/margelo/react-native-quick-crypto.git", :tag => "#{s.version}" }
1721

1822
s.source_files = [
@@ -32,7 +36,6 @@ Pod::Spec.new do |s|
3236
load 'nitrogen/generated/ios/QuickCrypto+autolinking.rb'
3337
add_nitrogen_files(s)
3438

35-
install_modules_dependencies(s)
3639
s.dependency "OpenSSL-Universal"
37-
40+
install_modules_dependencies(s)
3841
end

packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEdKeyPairSpec.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ namespace margelo::nitro::crypto {
5858
virtual std::shared_ptr<ArrayBuffer> getPrivateKey() = 0;
5959
virtual std::shared_ptr<Promise<std::shared_ptr<ArrayBuffer>>> sign(const std::shared_ptr<ArrayBuffer>& message, const std::optional<std::shared_ptr<ArrayBuffer>>& key) = 0;
6060
virtual std::shared_ptr<ArrayBuffer> signSync(const std::shared_ptr<ArrayBuffer>& message, const std::optional<std::shared_ptr<ArrayBuffer>>& key) = 0;
61-
virtual std::shared_ptr<Promise<bool>> verify(const std::shared_ptr<ArrayBuffer>& message, const std::shared_ptr<ArrayBuffer>& signature, const std::optional<std::shared_ptr<ArrayBuffer>>& key) = 0;
62-
virtual bool verifySync(const std::shared_ptr<ArrayBuffer>& message, const std::shared_ptr<ArrayBuffer>& signature, const std::optional<std::shared_ptr<ArrayBuffer>>& key) = 0;
61+
virtual std::shared_ptr<Promise<bool>> verify(const std::shared_ptr<ArrayBuffer>& signature, const std::shared_ptr<ArrayBuffer>& message, const std::optional<std::shared_ptr<ArrayBuffer>>& key) = 0;
62+
virtual bool verifySync(const std::shared_ptr<ArrayBuffer>& signature, const std::shared_ptr<ArrayBuffer>& message, const std::optional<std::shared_ptr<ArrayBuffer>>& key) = 0;
6363
virtual void setCurve(const std::string& curve) = 0;
6464

6565
protected:

packages/react-native-quick-crypto/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@
9090
"jest": "29.7.0",
9191
"nitro-codegen": "0.18.2",
9292
"prettier": "3.3.3",
93-
"react-native-builder-bob": "0.33.3",
93+
"react-native-builder-bob": "0.35.2",
9494
"release-it": "17.6.0",
9595
"typescript": "5.1.6",
9696
"typescript-eslint": "^8.1.0"

packages/react-native-quick-crypto/src/ed.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { NitroModules } from 'react-native-nitro-modules';
2+
import { binaryLikeToArrayBuffer as toAB } from './utils';
23
import type { EdKeyPair } from './specs/edKeyPair.nitro';
3-
import type { CFRGKeyPairType, KeyPairGenConfig } from './utils';
4+
import type { BinaryLike, CFRGKeyPairType, KeyPairGenConfig } from './utils';
45

56
export class Ed {
67
type: CFRGKeyPairType;
@@ -44,33 +45,35 @@ export class Ed {
4445
return this.native.getPrivateKey();
4546
}
4647

47-
async sign(message: ArrayBuffer, key?: ArrayBuffer): Promise<ArrayBuffer> {
48-
return key ? this.native.sign(message, key) : this.native.sign(message);
48+
async sign(message: BinaryLike, key?: BinaryLike): Promise<ArrayBuffer> {
49+
return key
50+
? this.native.sign(toAB(message), toAB(key))
51+
: this.native.sign(toAB(message));
4952
}
5053

51-
signSync(message: ArrayBuffer, key?: ArrayBuffer): ArrayBuffer {
54+
signSync(message: BinaryLike, key?: BinaryLike): ArrayBuffer {
5255
return key
53-
? this.native.signSync(message, key)
54-
: this.native.signSync(message);
56+
? this.native.signSync(toAB(message), toAB(key))
57+
: this.native.signSync(toAB(message));
5558
}
5659

5760
async verify(
58-
message: ArrayBuffer,
59-
signature: ArrayBuffer,
60-
key?: ArrayBuffer,
61+
signature: BinaryLike,
62+
message: BinaryLike,
63+
key?: BinaryLike,
6164
): Promise<boolean> {
6265
return key
63-
? this.native.verify(message, signature, key)
64-
: this.native.verify(message, signature);
66+
? this.native.verify(toAB(signature), toAB(message), toAB(key))
67+
: this.native.verify(toAB(signature), toAB(message));
6568
}
6669

6770
verifySync(
68-
message: ArrayBuffer,
69-
signature: ArrayBuffer,
70-
key?: ArrayBuffer,
71+
signature: BinaryLike,
72+
message: BinaryLike,
73+
key?: BinaryLike,
7174
): boolean {
7275
return key
73-
? this.native.verifySync(message, signature, key)
74-
: this.native.verifySync(message, signature);
76+
? this.native.verifySync(toAB(signature), toAB(message), toAB(key))
77+
: this.native.verifySync(toAB(signature), toAB(message));
7578
}
7679
}

0 commit comments

Comments
 (0)