Skip to content

Commit 2e091fa

Browse files
authored
feat: add getCurves() to enumerate supported EC curves (#913)
1 parent 7bf6e53 commit 2e091fa

8 files changed

Lines changed: 69 additions & 1 deletion

File tree

example/src/tests/ecdh/ecdh_tests.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { test } from '../util';
2-
import crypto, { Buffer } from 'react-native-quick-crypto';
2+
import crypto, { Buffer, getCurves } from 'react-native-quick-crypto';
33
import { assert } from 'chai';
44

55
const SUITE = 'ecdh';
@@ -68,3 +68,25 @@ test(SUITE, 'should work with string input', () => {
6868
const secret = alice.computeSecret(bobPubHex, 'hex');
6969
assert.isOk(secret);
7070
});
71+
72+
test(SUITE, 'getCurves - should return array of supported curves', () => {
73+
const curves = getCurves();
74+
assert.isArray(curves);
75+
assert.isAbove(curves.length, 0, 'should have at least one curve');
76+
77+
const expectedCurves = ['prime256v1', 'secp384r1', 'secp521r1', 'secp256k1'];
78+
for (const curve of expectedCurves) {
79+
assert.include(curves, curve, `should include ${curve}`);
80+
}
81+
82+
const isSorted = curves.every(
83+
(val: string, i: number) => i === 0 || val >= curves[i - 1]!,
84+
);
85+
assert.isTrue(isSorted, 'curves should be sorted alphabetically');
86+
});
87+
88+
test(SUITE, 'getCurves - should match crypto.getCurves()', () => {
89+
const named = getCurves();
90+
const fromDefault = crypto.getCurves();
91+
assert.deepEqual(named, fromDefault);
92+
});

packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <NitroModules/ArrayBuffer.hpp>
22
#include <NitroModules/Promise.hpp>
3+
#include <algorithm>
34
#include <memory>
45
#include <openssl/bio.h>
56
#include <openssl/buffer.h>
@@ -425,4 +426,24 @@ void HybridEcKeyPair::checkKeyPair() {
425426
}
426427
}
427428

429+
std::vector<std::string> HybridEcKeyPair::getSupportedCurves() {
430+
const size_t count = EC_get_builtin_curves(nullptr, 0);
431+
std::vector<EC_builtin_curve> curves(count);
432+
if (EC_get_builtin_curves(curves.data(), count) != count) {
433+
throw std::runtime_error("Failed to enumerate EC curves");
434+
}
435+
436+
std::vector<std::string> names;
437+
names.reserve(count);
438+
for (const auto& curve : curves) {
439+
const char* sn = OBJ_nid2sn(curve.nid);
440+
if (sn != nullptr) {
441+
names.emplace_back(sn);
442+
}
443+
}
444+
445+
std::sort(names.begin(), names.end());
446+
return names;
447+
}
448+
428449
} // namespace margelo::nitro::crypto

packages/react-native-quick-crypto/cpp/ec/HybridEcKeyPair.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class HybridEcKeyPair : public HybridEcKeyPairSpec {
3434
std::shared_ptr<ArrayBuffer> sign(const std::shared_ptr<ArrayBuffer>& data, const std::string& hashAlgorithm) override;
3535
bool verify(const std::shared_ptr<ArrayBuffer>& data, const std::shared_ptr<ArrayBuffer>& signature,
3636
const std::string& hashAlgorithm) override;
37+
std::vector<std::string> getSupportedCurves() override;
3738

3839
protected:
3940
void checkKeyPair();

packages/react-native-quick-crypto/nitrogen/generated/shared/c++/HybridEcKeyPairSpec.cpp

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,23 @@ import {
3434
import { Buffer } from '@craftzdog/react-native-buffer';
3535
import { ECDH } from './ecdh';
3636

37+
class EcUtils {
38+
private static _native: EcKeyPair | undefined;
39+
private static get native(): EcKeyPair {
40+
if (!this._native) {
41+
this._native = NitroModules.createHybridObject<EcKeyPair>('EcKeyPair');
42+
}
43+
return this._native;
44+
}
45+
public static getSupportedCurves(): string[] {
46+
return this.native.getSupportedCurves();
47+
}
48+
}
49+
50+
export function getCurves(): string[] {
51+
return EcUtils.getSupportedCurves();
52+
}
53+
3754
export class Ec {
3855
native: EcKeyPair;
3956

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as scrypt from './scrypt';
1414
import * as random from './random';
1515
import * as ecdh from './ecdh';
1616
import * as dh from './diffie-hellman';
17+
import { getCurves } from './ec';
1718
import { constants } from './constants';
1819

1920
// utils import
@@ -39,6 +40,7 @@ const QuickCrypto = {
3940
...dh,
4041
...utils,
4142
...subtle,
43+
getCurves,
4244
constants,
4345
Buffer,
4446
};
@@ -81,6 +83,7 @@ export * from './pbkdf2';
8183
export * from './scrypt';
8284
export * from './random';
8385
export * from './ecdh';
86+
export { getCurves } from './ec';
8487
export * from './diffie-hellman';
8588
export * from './utils';
8689
export * from './subtle';

packages/react-native-quick-crypto/src/specs/ecKeyPair.nitro.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,6 @@ export interface EcKeyPair
3535
signature: ArrayBuffer,
3636
hashAlgorithm: string,
3737
): boolean;
38+
39+
getSupportedCurves(): string[];
3840
}

0 commit comments

Comments
 (0)