Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


This project wraps libsodium for:

  • Secure Memory
  • Random Data
  • Secret-Key
    • Authenticated Encryption
    • Authentication
    • AEAD
  • Public-Key
    • Authenticated Encryption
  • One-Time Authentication
  • Password Hashing: Scrypt
  • Stream Ciphers: XSalsa20

More wrappers are coming soon.

Do you want to work on crypto at Keybase? We're hiring.

If you are looking for other non-libsodium related crypto (that used to be here), see NACrypto.


pod "NAChloride"


You should call NAChlorideInit() to initialize on app start. It is thread safe and multiple calls are ignored. We automatically call this as well as a safety measure.


Secure Memory

See Securing Memory Allocations.

NASecureData *secureData = [NASecureData secureReadOnlyDataWithLength:length completion:^(void *bytes, NSUInteger length) {
  // Set the bytes here. After this it will be read-only.

// After the block executes, secureData is read-only. You can set it to no access (or read/write).
// If you set it to no access and secureData.bytes is accessed, it will SIGABRT. For example,
// = NASecureDataProtectionNoAccess;

Some classes like NASecretBox, NABox and NAAEAD have an option to enable secureMemory (on decrypt).

NASecureData subclasses NSMutableData for compatibility and usage with other APIs.

Generating Random Data

See Generating Random Data.

NSData *data = [NARandom randomData:32]; // 32 bytes of random data
NSData *data = [NARandom randomSecureReadOnlyData:32]; // 32 bytes of random, secure, read-only data

Secret-Key Cryptography

Authenticated Encryption

Encrypts and authenticates a message using a shared key and nonce.

See Authenticated Encryption.

NSData *key = [NARandom randomData:NASecretBoxKeySize];
NSData *nonce = [NARandom randomData:NASecretBoxNonceSize];
NSData *message = [@"This is a secret message" dataUsingEncoding:NSUTF8StringEncoding];

NASecretBox *secretBox = [[NASecretBox alloc] init];
NSError *error = nil;
NSData *encrypted = [secretBox encrypt:message nonce:nonce key:key error:&error];
// If an error occurred encrypted will be nil and error set

NSData *decrypted = [secretBox decrypt:encrypted nonce:nonce key:key error:&error];


See Authentication.

NSData *key = [NARandom randomData:NAAuthKeySize];
NSData *message = [@"This is a message" dataUsingEncoding:NSUTF8StringEncoding];

NSError *error = nil;
NAAuth *auth = [[NAAuth alloc] init];
NSData *authData = [auth auth:message key:key &error];
BOOL verified = [auth verify:authData data:message key:key error:&error];


See Authenticated Encryption with Additional Data.

NSData *key = [NARandom randomData:NAAEADKeySize];
NSData *nonce = [NARandom randomData:NAAEADNonceSize];
NSData *message = [@"This is a secret message" dataUsingEncoding:NSUTF8StringEncoding];
NSData *additionalData = [@"Additional data" dataUsingEncoding:NSUTF8StringEncoding];

NAAEAD *AEAD = [[NAAEAD alloc] init];
NSError *error = nil;
NSData *encryptedData = [AEAD encryptChaCha20Poly1305:message nonce:nonce key:key additionalData:additionalData error:&error];
NSData *decryptedData = [AEAD decryptChaCha20Poly1305:encryptedData nonce:nonce key:key additionalData:additionalData error:&error];

Public-Key Cryptography

Authenticated Encryption

See Authenticated Encryption.

NSError *error = nil;
NABoxKeypair *keypair = [NABoxKeypair generate:&error];

NSData *nonce = [NARandom randomData:NABoxNonceSize];
NSData *message = [@"This is a secret message" dataUsingEncoding:NSUTF8StringEncoding];

NABox *box = [[NABox alloc] init];
NSData *encryptedData = [box encrypt:message nonce:nonce keypair:keypair error:&error];
NSData *decryptedData = [box decrypt:encryptedData nonce:nonce keypair:keypair error:&error];

Password Hashing

See Password Hashing.

NSData *key = [@"toomanysecrets" dataUsingEncoding:NSUTF8StringEncoding];
NSData *salt = [NARandom randomData:NAScryptSaltSize];
NSError *error = nil;
NSData *data = [NAScrypt scrypt:key salt:salt error:&error];


One-Time Authentication

Generates a MAC for a given message and shared key using Poly1305 algorithm. Key may NOT be reused across messages.

See One-Time Authentication.

NSData *key = [NARandom randomData:NAOneTimeAuthKeySize];
NSData *message = [@"This is a message" dataUsingEncoding:NSUTF8StringEncoding];

NSError *error = nil;
NAOneTimeAuth *oneTimeAuth = [[NAOneTimeAuth alloc] init];
NSData *auth = [oneTimeAuth auth:message key:key error:&error];
BOOL verified = [oneTimeAuth verify:auth data:message key:key error:&error];

Stream Ciphers

See XSalsa20.

NSData *key = [NARandom randomData:NAStreamKeySize];
NSData *nonce = [NARandom randomData:NAStreamNonceSize];
NAStream *stream = [[NAStream alloc] init];
NSError *error = nil;
NSData *encrypted = [stream xor:message nonce:nonce key:key error:&error];
NSData *decrypted = [stream xor:encrypted nonce:nonce key:key error:&error];


There is a helper to dispatch these operations on a queue:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NADispatch(queue, ^id(NSError **error) {
  return [NAScrypt scrypt:password salt:salt error:error];
}, ^(NSError *error, NSData *data) {
  // This is on the main queue.
  // Error is set if it failed.