Skip to content

Commit

Permalink
feat: improve crypto_aead_xchacha20poly1305_ietf_encrypt to accept an…
Browse files Browse the repository at this point in the history
… Uin8Array for the message
  • Loading branch information
nikgraf committed Dec 13, 2022
1 parent 53eca47 commit d73a008
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 4 deletions.
77 changes: 77 additions & 0 deletions cpp/react-native-libsodium.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,83 @@ void installLibsodium(jsi::Runtime &jsiRuntime)

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

auto jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer = jsi::Function::createFromHostFunction(
jsiRuntime,
jsi::PropNameID::forUtf8(jsiRuntime, "jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer"),
6,
[](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments, size_t count) -> jsi::Value
{
if (arguments[0].isNull())
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] message can't be null");
}
if (!arguments[0].isObject() ||
!arguments[0].asObject(runtime).isArrayBuffer(runtime))
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] message must be an ArrayBuffer");
}
if (arguments[1].isNull())
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] additionalData can't be null");
}
if (!arguments[1].isString())
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] additionalData must be a string");
}
if (arguments[2].isNull())
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] nonce can't be null");
}
if (!arguments[2].isObject() ||
!arguments[2].asObject(runtime).isArrayBuffer(runtime))
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] nonce must be an ArrayBuffer");
}
if (arguments[3].isNull())
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] key can't be null");
}
if (!arguments[3].isObject() ||
!arguments[3].asObject(runtime).isArrayBuffer(runtime))
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] key must be an ArrayBuffer");
}

auto messageDataArrayBuffer =
arguments[0].asObject(runtime).getArrayBuffer(runtime);
const unsigned char *message = messageDataArrayBuffer.data(runtime);

std::string additionalData = arguments[1].asString(runtime).utf8(runtime);

auto nonceDataArrayBuffer =
arguments[2].asObject(runtime).getArrayBuffer(runtime);
const unsigned char *nonce = nonceDataArrayBuffer.data(runtime);

auto keyDataArrayBuffer =
arguments[3].asObject(runtime).getArrayBuffer(runtime);
const unsigned char *key = keyDataArrayBuffer.data(runtime);

unsigned long long cipherTextLength = messageDataArrayBuffer.size(runtime) + crypto_aead_xchacha20poly1305_ietf_ABYTES;
unsigned char cipherText[cipherTextLength];

int result = crypto_aead_xchacha20poly1305_ietf_encrypt(cipherText, &cipherTextLength, message, messageDataArrayBuffer.size(runtime), (unsigned char *)additionalData.data(), additionalData.length(), NULL, nonce, key);

if (result != 0)
{
throw jsi::JSError(runtime, "[react-native-libsodium][jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer] crypto_aead_xchacha20poly1305_ietf_encrypt failed");
}

jsi::Object returnBufferAsObject = runtime.global()
.getPropertyAsFunction(runtime, "ArrayBuffer")
.callAsConstructor(runtime, (int)cipherTextLength)
.asObject(runtime);
jsi::ArrayBuffer arraybuffer = returnBufferAsObject.getArrayBuffer(runtime);
memcpy(arraybuffer.data(runtime), cipherText, cipherTextLength);
return returnBufferAsObject;
});

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

auto jsi_crypto_aead_xchacha20poly1305_ietf_decrypt_from_arraybuffer = jsi::Function::createFromHostFunction(
jsiRuntime,
jsi::PropNameID::forUtf8(jsiRuntime, "jsi_crypto_aead_xchacha20poly1305_ietf_decrypt_from_arraybuffer"),
Expand Down
34 changes: 30 additions & 4 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,24 +251,50 @@ function LibsodiumTests() {
const aead_xchacha20poly1305_ietf_nonce = randombytes_buf(
crypto_aead_xchacha20poly1305_ietf_NPUBBYTES
);
const aead_xchacha20poly1305_ietf_encrypt =
const aead_xchacha20poly1305_ietf_encrypt_from_string =
crypto_aead_xchacha20poly1305_ietf_encrypt(
'Hello World',
'additional data',
null,
aead_xchacha20poly1305_ietf_nonce,
aead_xchacha20poly1305_ietf_key
);
const aead_xchacha20poly1305_ietf_encrypt_from_uin8array =
crypto_aead_xchacha20poly1305_ietf_encrypt(
from_base64(to_base64('Hello World')),
'additional data',
null,
aead_xchacha20poly1305_ietf_nonce,
aead_xchacha20poly1305_ietf_key
);

const aead_xchacha20poly1305_ietf_decrypt =
const aead_xchacha20poly1305_ietf_decrypt_encrypted_from_string =
crypto_aead_xchacha20poly1305_ietf_decrypt(
null,
aead_xchacha20poly1305_ietf_encrypt,
aead_xchacha20poly1305_ietf_encrypt_from_string,
'additional data',
aead_xchacha20poly1305_ietf_nonce,
aead_xchacha20poly1305_ietf_key
);
if (to_string(aead_xchacha20poly1305_ietf_decrypt) !== 'Hello World') {
if (
to_string(aead_xchacha20poly1305_ietf_decrypt_encrypted_from_string) !==
'Hello World'
) {
throw new Error('aead_xchacha20poly1305_ietf_decrypt failed');
}

const aead_xchacha20poly1305_ietf_decrypt_encrypted_from_uint8array =
crypto_aead_xchacha20poly1305_ietf_decrypt(
null,
aead_xchacha20poly1305_ietf_encrypt_from_uin8array,
'additional data',
aead_xchacha20poly1305_ietf_nonce,
aead_xchacha20poly1305_ietf_key
);
if (
to_string(aead_xchacha20poly1305_ietf_decrypt_encrypted_from_uint8array) !==
'Hello World'
) {
throw new Error('aead_xchacha20poly1305_ietf_decrypt failed');
}

Expand Down
17 changes: 17 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ declare global {
nonce: ArrayBuffer,
key: ArrayBuffer
): ArrayBuffer;
function jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer(
message: ArrayBuffer,
additionalData: string,
nonce: ArrayBuffer,
key: ArrayBuffer
): ArrayBuffer;
function jsi_crypto_aead_xchacha20poly1305_ietf_decrypt_from_arraybuffer(
ciphertext: ArrayBuffer,
additionalData: string,
Expand Down Expand Up @@ -605,6 +611,17 @@ export function crypto_aead_xchacha20poly1305_ietf_encrypt(
public_nonce.buffer,
key.buffer
);
} else if (
typeof message !== 'string' &&
typeof additional_data === 'string'
) {
result =
global.jsi_crypto_aead_xchacha20poly1305_ietf_encrypt_from_arraybuffer(
message.buffer,
additional_data,
public_nonce.buffer,
key.buffer
);
} else {
throw new Error(
'crypto_aead_xchacha20poly1305_ietf_encrypt: input type not yet implemented'
Expand Down

0 comments on commit d73a008

Please sign in to comment.