TweetNaCl.js и его JavaScript-реализации семейства nacl.js представляют собой компактные, полностью программные реализации криптографических примитивов NaCl (Networking and Cryptography library). В мобильных средах и React Native они часто становятся базовым решением для end-to-end шифрования, цифровых подписей и безопасного обмена данными без необходимости нативных модулей.
TweetNaCl.js — это порт оригинальной NaCl, написанный на чистом JavaScript с минимальной зависимостью от платформы. Это определяет его ключевые свойства:
Uint8ArrayОсновные алгоритмы:
Под обозначением nacl.js часто встречаются форки и обёртки над TweetNaCl:
В мобильных проектах React Native чаще используется комбинация:
tweetnacltweetnacl-utilrandomBytes или
crypto.getRandomValuesReact Native не является полноценной браузерной средой, поэтому возникают системные ограничения.
TweetNaCl.js требует криптографически стойкий генератор случайных чисел.
В браузере используется:
crypto.getRandomValues(new Uint8Array(32));
В React Native этого API нет по умолчанию.
Решения:
import 'react-native-get-random-values';
После подключения глобально появляется совместимый
crypto.
TweetNaCl работает только с Uint8Array. Однако мобильные
приложения часто оперируют строками.
Типичная проблема:
Используется преобразование:
import nacl from 'tweetnacl';
import util from 'tweetnacl-util';
const messageUint8 = util.decodeUTF8("секретное сообщение");
При использовании Hermes:
Рекомендуется избегать Buffer и использовать Uint8Array
напрямую.
TweetNaCl использует публично-асимметричные ключи Curve25519:
import nacl from 'tweetnacl';
const keyPair = nacl.box.keyPair();
const publicKey = keyPair.publicKey;
const secretKey = keyPair.secretKey;
В React Native важно хранить secretKey только в
защищённых хранилищах:
Модель box используется для публичного шифрования:
const nonce = nacl.randomBytes(24);
const encrypted = nacl.box(
messageUint8,
nonce,
recipientPublicKey,
senderSecretKey
);
Особенности мобильных приложений:
const decrypted = nacl.box.open(
encryptedMessage,
nonce,
senderPublicKey,
recipientSecretKey
);
Если данные повреждены или ключи не совпадают — возвращается
null.
Для хранения данных на устройстве используется symmetric encryption:
const key = nacl.randomBytes(32);
const nonce = nacl.randomBytes(24);
const encrypted = nacl.secretbox(messageUint8, nonce, key);
Применение в мобильных приложениях:
Подписи применяются для проверки целостности сообщений:
const keyPair = nacl.sign.keyPair();
const signed = nacl.sign(messageUint8, keyPair.secretKey);
const verified = nacl.sign.open(signed, keyPair.publicKey);
В мобильных API часто используется:
TweetNaCl не работает со строками напрямую.
Частые преобразования:
const encoded = util.encodeBase64(encrypted);
const decoded = util.decodeBase64(encoded);
Проблема в мобильных средах:
TweetNaCl.js написан без нативных ускорений, поэтому:
Рекомендации:
getRandomValuesTweetNaCl не решает задачу хранения ключей.
Типовая схема:
Nonce для box всегда 24 байта:
nacl.randomBytes(24)
Решается установкой polyfill:
import 'react-native-get-random-values';
Причины:
Ключевые практики:
TweetNaCl.js подходит для:
Не подходит для:
В Expo требуется:
expo-crypto или
react-native-get-random-valuesПример инициализации:
import 'react-native-get-random-values';
import nacl from 'tweetnacl';
Crypto service обычно инкапсулирует:
class CryptoService {
constructor(nacl, util) {
this.nacl = nacl;
this.util = util;
}
generateKeyPair() {
return this.nacl.box.keyPair();
}
encrypt(message, publicKey, secretKey) {
const nonce = this.nacl.randomBytes(24);
const messageUint8 = this.util.decodeUTF8(message);
const box = this.nacl.box(messageUint8, nonce, publicKey, secretKey);
return {
nonce: this.util.encodeBase64(nonce),
box: this.util.encodeBase64(box),
};
}
decrypt(box, nonce, publicKey, secretKey) {
return this.nacl.box.open(
this.util.decodeBase64(box),
this.util.decodeBase64(nonce),
publicKey,
secretKey
);
}
}
Работа TweetNaCl.js в React Native строится вокруг строгого соблюдения бинарных типов, корректного управления случайностью и грамотной интеграции с мобильными хранилищами ключей.