Skip to content
Open
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ import {
crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES,
crypto_aead_xchacha20poly1305_ietf_keygen,
crypto_box_beforenm,
crypto_box_easy,
crypto_box_keypair,
crypto_box_seed_keypair,
crypto_box_open_easy,
crypto_box_BEFORENMBYTES,
crypto_box_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES,
crypto_box_SEEDBYTES,
Expand Down
44 changes: 44 additions & 0 deletions cpp/react-native-libsodium.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ namespace ReactNativeLibsodium
jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_pwhash_OPSLIMIT_INTERACTIVE", static_cast<int>(crypto_pwhash_OPSLIMIT_INTERACTIVE));
jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_pwhash_MEMLIMIT_INTERACTIVE", static_cast<int>(crypto_pwhash_MEMLIMIT_INTERACTIVE));
jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_box_PUBLICKEYBYTES", static_cast<int>(crypto_box_PUBLICKEYBYTES));
jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_box_BEFORENMBYTES", static_cast<int>(crypto_box_BEFORENMBYTES));
jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_box_SECRETKEYBYTES", static_cast<int>(crypto_box_SECRETKEYBYTES));
jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_box_NONCEBYTES", static_cast<int>(crypto_box_NONCEBYTES));
jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_box_SEEDBYTES", static_cast<int>(crypto_box_SEEDBYTES));
Expand Down Expand Up @@ -1122,6 +1123,49 @@ namespace ReactNativeLibsodium

jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_box_seal_open", std::move(jsi_crypto_box_seal_open));

auto jsi_crypto_box_beforenm = jsi::Function::createFromHostFunction(
jsiRuntime,
jsi::PropNameID::forUtf8(jsiRuntime, "jsi_crypto_box_beforenm"),
2,
[](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments, size_t count) -> jsi::Value
{
const std::string functionName = "crypto_box_beforenm";

std::string publicKeyArgumentName = "publicKey";
unsigned int publicKeyArgumentPosition = 0;
JsiArgType publicKeyArgType = validateIsStringOrArrayBuffer(functionName, runtime, arguments[publicKeyArgumentPosition], publicKeyArgumentName, true);

std::string privateKeyArgumentName = "privateKey";
unsigned int privateKeyArgumentPosition = 1;
JsiArgType privateKeyArgType = validateIsStringOrArrayBuffer(functionName, runtime, arguments[privateKeyArgumentPosition], privateKeyArgumentName, true);

auto publicKey = arguments[publicKeyArgumentPosition].asObject(runtime).getArrayBuffer(runtime);
auto privateKey = arguments[privateKeyArgumentPosition].asObject(runtime).getArrayBuffer(runtime);

if (publicKey.length(runtime) != crypto_box_PUBLICKEYBYTES)
{
throw jsi::JSError(runtime, "invalid publicKey length");
}

if (privateKey.length(runtime) != crypto_box_SECRETKEYBYTES)
{
throw jsi::JSError(runtime, "invalid privateKey length");
}

// Allocate memory for the shared secret
std::vector<uint8_t> sharedSecret(crypto_box_BEFORENMBYTES);

int result = crypto_box_beforenm(
sharedSecret.data(),
publicKey.data(runtime),
privateKey.data(runtime));

throwOnBadResult(functionName, runtime, result);
return arrayBufferAsObject(runtime, sharedSecret);
});

jsiRuntime.global().setProperty(jsiRuntime, "jsi_crypto_box_beforenm", std::move(jsi_crypto_box_beforenm));

auto jsi_crypto_pwhash = jsi::Function::createFromHostFunction(
jsiRuntime,
jsi::PropNameID::forUtf8(jsiRuntime, "jsi_crypto_pwhash"),
Expand Down
1 change: 1 addition & 0 deletions example/src/components/TestResults.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import '../tests/crypto_aead_xchacha20poly1305_ietf_keygen_test';
import '../tests/crypto_auth_keygen_test';
import '../tests/crypto_auth_test';
import '../tests/crypto_auth_verify_test';
import '../tests/crypto_box_beforenm_test';
import '../tests/crypto_box_easy_test';
import '../tests/crypto_box_keypair_test';
import '../tests/crypto_box_open_easy_test';
Expand Down
2 changes: 2 additions & 0 deletions example/src/tests/constants_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
crypto_aead_xchacha20poly1305_ietf_KEYBYTES,
crypto_auth_BYTES,
crypto_auth_KEYBYTES,
crypto_box_BEFORENMBYTES,
crypto_box_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES,
crypto_box_SEEDBYTES,
Expand All @@ -22,6 +23,7 @@ test('constants', () => {
expect(crypto_auth_KEYBYTES).toEqual(32);
expect(crypto_secretbox_KEYBYTES).toEqual(32);
expect(crypto_secretbox_NONCEBYTES).toEqual(24);
expect(crypto_box_BEFORENMBYTES).toEqual(32);
expect(crypto_box_PUBLICKEYBYTES).toEqual(32);
expect(crypto_box_SECRETKEYBYTES).toEqual(32);
expect(crypto_box_SEEDBYTES).toEqual(32);
Expand Down
41 changes: 41 additions & 0 deletions example/src/tests/crypto_box_beforenm_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
crypto_box_BEFORENMBYTES,
crypto_box_beforenm,
crypto_box_keypair,
} from 'react-native-libsodium';
import { expect, test } from '../utils/testRunner';

test('crypto_box_beforenm', () => {
const alice = crypto_box_keypair();
const bob = crypto_box_keypair();

// produces symmetric shared keys
const sharedAlice = crypto_box_beforenm(bob.publicKey, alice.privateKey);
const sharedBob = crypto_box_beforenm(alice.publicKey, bob.privateKey);

expect(sharedAlice.length).toEqual(crypto_box_BEFORENMBYTES);
expect(sharedBob.length).toEqual(crypto_box_BEFORENMBYTES);
expect(sharedAlice).toEqual(sharedBob);

// validates its inputs
expect(() => {
crypto_box_beforenm(
alice.publicKey.slice(0, alice.publicKey.length - 1),
alice.privateKey
);
}).toThrow();

expect(() => {
crypto_box_beforenm(
alice.publicKey,
alice.privateKey.slice(0, alice.privateKey.length - 1)
);
}).toThrow();

expect(() => {
crypto_box_beforenm(
new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
alice.privateKey
);
}).toThrow();
});
18 changes: 18 additions & 0 deletions src/lib.native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ if (Libsodium && typeof Libsodium.install === 'function') {
declare global {
var jsi_crypto_auth_BYTES: number;
var jsi_crypto_auth_KEYBYTES: number;
var jsi_crypto_box_BEFORENMBYTES: number;
var jsi_crypto_secretbox_KEYBYTES: number;
var jsi_crypto_secretbox_NONCEBYTES: number;
var jsi_crypto_box_PUBLICKEYBYTES: number;
Expand Down Expand Up @@ -133,6 +134,10 @@ declare global {
publicKey: ArrayBuffer,
secretKey: ArrayBuffer
): ArrayBuffer;
function jsi_crypto_box_beforenm(
publicKey: ArrayBuffer,
privateKey: ArrayBuffer
): ArrayBuffer;
function jsi_crypto_generichash(
hashLength: number,
message: string | ArrayBuffer,
Expand Down Expand Up @@ -186,6 +191,7 @@ declare global {

export const crypto_auth_BYTES = global.jsi_crypto_auth_BYTES;
export const crypto_auth_KEYBYTES = global.jsi_crypto_auth_KEYBYTES;
export const crypto_box_BEFORENMBYTES = global.jsi_crypto_box_BEFORENMBYTES;
export const crypto_secretbox_KEYBYTES = global.jsi_crypto_secretbox_KEYBYTES;
export const crypto_secretbox_NONCEBYTES =
global.jsi_crypto_secretbox_NONCEBYTES;
Expand Down Expand Up @@ -621,6 +627,16 @@ export function crypto_box_seal_open(
return convertToOutputFormat(result, outputFormat);
}

export function crypto_box_beforenm(
publicKey: Uint8Array,
privateKey: Uint8Array,
outputFormat: OutputFormat
) {
let result: ArrayBuffer;
result = global.jsi_crypto_box_beforenm(publicKey.buffer, privateKey.buffer);
return convertToOutputFormat(result, outputFormat);
}

export function crypto_generichash(
hash_length: number,
message: string | Uint8Array,
Expand Down Expand Up @@ -858,8 +874,10 @@ export default {
crypto_box_keypair,
crypto_box_NONCEBYTES,
crypto_box_open_easy,
crypto_box_BEFORENMBYTES,
crypto_box_PUBLICKEYBYTES,
crypto_box_SECRETKEYBYTES,
crypto_box_beforenm,
crypto_generichash,
crypto_generichash_BYTES,
crypto_generichash_BYTES_MIN,
Expand Down