Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/.ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.3.4
2 changes: 1 addition & 1 deletion example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2811,7 +2811,7 @@ SPEC CHECKSUMS:
MMKVCore: f2dd4c9befea04277a55e84e7812f930537993df
NitroMmkv: afbc5b2fbf963be567c6c545aa1efcf6a9cec68e
NitroModules: 11bba9d065af151eae51e38a6425e04c3b223ff3
QuickCrypto: 422a7b7f5d0de18bec3837cbc2e7a865999334c0
QuickCrypto: 414c0c5f7353bc7bf87ef3ae02485cf41b4a66d1
RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669
RCTDeprecation: c4b9e2fd0ab200e3af72b013ed6113187c607077
RCTRequired: e97dd5dafc1db8094e63bc5031e0371f092ae92a
Expand Down
2 changes: 1 addition & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"react-native-mmkv": "4.0.1",
"react-native-nitro-modules": "0.33.2",
"react-native-quick-base64": "2.2.2",
"react-native-quick-crypto": "1.0.17",
"react-native-quick-crypto": "workspace:*",
"react-native-safe-area-context": "5.6.2",
"react-native-screens": "4.18.0",
"react-native-vector-icons": "10.3.0",
Expand Down
1 change: 1 addition & 0 deletions example/src/hooks/useTestsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import '../tests/hkdf/hkdf_tests';
import '../tests/hmac/hmac_tests';
import '../tests/jose/jose';
import '../tests/keys/create_keys';
import '../tests/keys/ed_keyobject';
import '../tests/keys/generate_key';
import '../tests/keys/generate_keypair';
import '../tests/keys/keyobject_from_tocryptokey_tests';
Expand Down
319 changes: 319 additions & 0 deletions example/src/tests/keys/ed_keyobject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,319 @@
import {
generateKeyPairSync,
generateKeyPair,
createPrivateKey,
createPublicKey,
KeyObject,
AsymmetricKeyObject,
Buffer,
} from 'react-native-quick-crypto';
import { expect } from 'chai';
import { test } from '../util';

const SUITE = 'keys.edKeyObject';

// --- Ed25519 KeyObject tests ---

test(SUITE, 'generateKeyPairSync ed25519 returns KeyObjects', () => {
const result = generateKeyPairSync('ed25519');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

expect(pub).to.be.an.instanceOf(KeyObject);
expect(priv).to.be.an.instanceOf(KeyObject);
expect(pub.type).to.equal('public');
expect(priv.type).to.equal('private');
expect(pub.asymmetricKeyType).to.equal('ed25519');
expect(priv.asymmetricKeyType).to.equal('ed25519');
});

test(SUITE, 'ed25519 KeyObject.export() works for PEM', () => {
const result = generateKeyPairSync('ed25519');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

const pubPem = pub.export({ type: 'spki', format: 'pem' });
const privPem = priv.export({ type: 'pkcs8', format: 'pem' });

expect(typeof pubPem).to.equal('string');
expect(typeof privPem).to.equal('string');
expect(pubPem as string).to.match(/^-----BEGIN PUBLIC KEY-----/);
expect(privPem as string).to.match(/^-----BEGIN PRIVATE KEY-----/);
});

test(SUITE, 'ed25519 KeyObject.export() works for DER', () => {
const result = generateKeyPairSync('ed25519');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

const pubDer = pub.export({ type: 'spki', format: 'der' });
const privDer = priv.export({ type: 'pkcs8', format: 'der' });

expect(Buffer.isBuffer(pubDer)).to.equal(true);
expect(Buffer.isBuffer(privDer)).to.equal(true);
});

test(SUITE, 'ed25519 with PEM encoding returns strings', () => {
const { publicKey, privateKey } = generateKeyPairSync('ed25519', {
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
});

expect(typeof publicKey).to.equal('string');
expect(typeof privateKey).to.equal('string');
expect(publicKey as string).to.match(/^-----BEGIN PUBLIC KEY-----/);
expect(privateKey as string).to.match(/^-----BEGIN PRIVATE KEY-----/);
});

test(SUITE, 'ed25519 with DER encoding returns ArrayBuffers', () => {
const { publicKey, privateKey } = generateKeyPairSync('ed25519', {
publicKeyEncoding: { type: 'spki', format: 'der' },
privateKeyEncoding: { type: 'pkcs8', format: 'der' },
});

expect(publicKey instanceof ArrayBuffer).to.equal(true);
expect(privateKey instanceof ArrayBuffer).to.equal(true);
expect((publicKey as ArrayBuffer).byteLength).to.be.greaterThan(0);
expect((privateKey as ArrayBuffer).byteLength).to.be.greaterThan(0);
});

// --- Round-trip tests ---

test(
SUITE,
'ed25519 round-trip: KeyObject -> export DER -> createKey -> export',
() => {
const result = generateKeyPairSync('ed25519');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

const privDer = priv.export({ type: 'pkcs8', format: 'der' });
const pubDer = pub.export({ type: 'spki', format: 'der' });

const recreatedPriv = createPrivateKey({
key: privDer,
format: 'der',
type: 'pkcs8',
});
const recreatedPub = createPublicKey({
key: pubDer,
format: 'der',
type: 'spki',
});

expect(recreatedPriv.type).to.equal('private');
expect(recreatedPub.type).to.equal('public');
expect(recreatedPriv.asymmetricKeyType).to.equal('ed25519');
expect(recreatedPub.asymmetricKeyType).to.equal('ed25519');

const reExportedPriv = recreatedPriv.export({
type: 'pkcs8',
format: 'der',
});
const reExportedPub = recreatedPub.export({ type: 'spki', format: 'der' });

expect(
Buffer.compare(Buffer.from(privDer), Buffer.from(reExportedPriv)),
).to.equal(0);
expect(
Buffer.compare(Buffer.from(pubDer), Buffer.from(reExportedPub)),
).to.equal(0);
},
);

test(
SUITE,
'ed25519 round-trip: KeyObject -> export PEM -> createKey -> export',
() => {
const result = generateKeyPairSync('ed25519');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

const privPem = priv.export({
type: 'pkcs8',
format: 'pem',
}) as string;
const pubPem = pub.export({ type: 'spki', format: 'pem' }) as string;

const recreatedPriv = createPrivateKey(privPem);
const recreatedPub = createPublicKey(pubPem);

expect(recreatedPriv.asymmetricKeyType).to.equal('ed25519');
expect(recreatedPub.asymmetricKeyType).to.equal('ed25519');

const reExportedPriv = recreatedPriv.export({
type: 'pkcs8',
format: 'pem',
}) as string;
const reExportedPub = recreatedPub.export({
type: 'spki',
format: 'pem',
}) as string;

expect(reExportedPriv).to.equal(privPem);
expect(reExportedPub).to.equal(pubPem);
},
);

// --- Ed448 KeyObject tests ---

test(SUITE, 'generateKeyPairSync ed448 returns KeyObjects', () => {
const result = generateKeyPairSync('ed448');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

expect(pub).to.be.an.instanceOf(KeyObject);
expect(priv).to.be.an.instanceOf(KeyObject);
expect(pub.asymmetricKeyType).to.equal('ed448');
expect(priv.asymmetricKeyType).to.equal('ed448');
});

test(SUITE, 'ed448 round-trip: KeyObject -> export -> recreate', () => {
const result = generateKeyPairSync('ed448');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

const privDer = priv.export({ type: 'pkcs8', format: 'der' });
const pubDer = pub.export({ type: 'spki', format: 'der' });

const recreatedPriv = createPrivateKey({
key: privDer,
format: 'der',
type: 'pkcs8',
});
const recreatedPub = createPublicKey({
key: pubDer,
format: 'der',
type: 'spki',
});

expect(recreatedPriv.asymmetricKeyType).to.equal('ed448');
expect(recreatedPub.asymmetricKeyType).to.equal('ed448');
});

// --- X25519 KeyObject tests ---

test(SUITE, 'generateKeyPairSync x25519 returns KeyObjects', () => {
const result = generateKeyPairSync('x25519');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

expect(pub).to.be.an.instanceOf(KeyObject);
expect(priv).to.be.an.instanceOf(KeyObject);
expect(pub.asymmetricKeyType).to.equal('x25519');
expect(priv.asymmetricKeyType).to.equal('x25519');
});

test(SUITE, 'x25519 round-trip: KeyObject -> export -> recreate', () => {
const result = generateKeyPairSync('x25519');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

const privDer = priv.export({ type: 'pkcs8', format: 'der' });
const pubDer = pub.export({ type: 'spki', format: 'der' });

const recreatedPriv = createPrivateKey({
key: privDer,
format: 'der',
type: 'pkcs8',
});
const recreatedPub = createPublicKey({
key: pubDer,
format: 'der',
type: 'spki',
});

expect(recreatedPriv.asymmetricKeyType).to.equal('x25519');
expect(recreatedPub.asymmetricKeyType).to.equal('x25519');
});

// --- X448 KeyObject tests ---

test(SUITE, 'generateKeyPairSync x448 returns KeyObjects', () => {
const result = generateKeyPairSync('x448');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

expect(pub).to.be.an.instanceOf(KeyObject);
expect(priv).to.be.an.instanceOf(KeyObject);
expect(pub.asymmetricKeyType).to.equal('x448');
expect(priv.asymmetricKeyType).to.equal('x448');
});

test(SUITE, 'x448 round-trip: KeyObject -> export -> recreate', () => {
const result = generateKeyPairSync('x448');
const pub = result.publicKey as AsymmetricKeyObject;
const priv = result.privateKey as AsymmetricKeyObject;

const privDer = priv.export({ type: 'pkcs8', format: 'der' });
const pubDer = pub.export({ type: 'spki', format: 'der' });

const recreatedPriv = createPrivateKey({
key: privDer,
format: 'der',
type: 'pkcs8',
});
const recreatedPub = createPublicKey({
key: pubDer,
format: 'der',
type: 'spki',
});

expect(recreatedPriv.asymmetricKeyType).to.equal('x448');
expect(recreatedPub.asymmetricKeyType).to.equal('x448');
});

// --- Async path tests ---

test(SUITE, 'generateKeyPair ed25519 async returns KeyObjects', async () => {
const result = await new Promise<{
publicKey: AsymmetricKeyObject;
privateKey: AsymmetricKeyObject;
}>((resolve, reject) => {
generateKeyPair('ed25519', {}, (err, pubKey, privKey) => {
if (err) reject(err);
else
resolve({
publicKey: pubKey as AsymmetricKeyObject,
privateKey: privKey as AsymmetricKeyObject,
});
});
});

expect(result.publicKey).to.be.an.instanceOf(KeyObject);
expect(result.privateKey).to.be.an.instanceOf(KeyObject);
expect(result.publicKey.type).to.equal('public');
expect(result.privateKey.type).to.equal('private');
});

test(
SUITE,
'generateKeyPair ed25519 async with PEM encoding returns strings',
async () => {
const { publicKey, privateKey } = await new Promise<{
publicKey: string;
privateKey: string;
}>((resolve, reject) => {
generateKeyPair(
'ed25519',
{
publicKeyEncoding: { type: 'spki', format: 'pem' },
privateKeyEncoding: { type: 'pkcs8', format: 'pem' },
},
(err, pubKey, privKey) => {
if (err) reject(err);
else
resolve({
publicKey: pubKey as string,
privateKey: privKey as string,
});
},
);
});

expect(typeof publicKey).to.equal('string');
expect(typeof privateKey).to.equal('string');
expect(publicKey).to.match(/^-----BEGIN PUBLIC KEY-----/);
expect(privateKey).to.match(/^-----BEGIN PRIVATE KEY-----/);
},
);
Loading
Loading