- Upgrade to 1.0

This commit is contained in:
giuseppenuc committed 2016-12-28 18:49:02 +01:00
1 parent 4e66c377fd
commit 0c2b3f1c25
452 files changed
+33888 -16806

No files matched your search

+19
View File
@@ -0,0 +1,19 @@
//
// NAAEAD.h
// NAChloride
//
// Created by Gabriel on 6/18/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NAAEAD : NSObject
@property (getter=isSecureDataEnabled) BOOL secureDataEnabled;
- (NSData *)encryptChaCha20Poly1305:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key additionalData:(NSData *)additionalData error:(NSError **)error;
- (NSData *)decryptChaCha20Poly1305:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key additionalData:(NSData *)additionalData error:(NSError **)error;
@end
+98
View File
@@ -0,0 +1,98 @@
//
// NAAEAD.m
// NAChloride
//
// Created by Gabriel on 6/18/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import "NAAEAD.h"
#import "NAInterface.h"
#import "NASecureData.h"
#import "sodium.h"
@implementation NAAEAD
+ (void)initialize { NAChlorideInit(); }
- (NSData *)encryptChaCha20Poly1305:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key additionalData:(NSData *)additionalData error:(NSError **)error {
if (!nonce || [nonce length] != NAAEADNonceSize) {
if (error) *error = NAError(NAErrorCodeInvalidNonce, @"Invalid nonce");
return nil;
}
if (!data) {
if (error) *error = NAError(NAErrorCodeInvalidData, @"Invalid data");
return nil;
}
if (!additionalData) {
if (error) *error = NAError(NAErrorCodeInvalidAdditionalData, @"Invalid additional data");
return nil;
}
if (!key || [key length] != NAAEADKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid key");
return nil;
}
NSMutableData *outData = [NSMutableData dataWithLength:[data length] + NAAEADASize];
unsigned long long outLength;
int retval = crypto_aead_chacha20poly1305_encrypt([outData mutableBytes], &outLength,
[data bytes], [data length],
[additionalData bytes], [additionalData length],
NULL,
[nonce bytes],
[key bytes]);
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeFailure, @"AEAD encrypt failed");
return nil;
}
return outData;
}
- (NSData *)decryptChaCha20Poly1305:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key additionalData:(NSData *)additionalData error:(NSError **)error {
if (!nonce || [nonce length] != NAAEADNonceSize) {
if (error) *error = NAError(NAErrorCodeInvalidNonce, @"Invalid nonce");
return nil;
}
if (!data) {
if (error) *error = NAError(NAErrorCodeInvalidData, @"Invalid data");
return nil;
}
if (!additionalData) {
if (error) *error = NAError(NAErrorCodeInvalidAdditionalData, @"Invalid additional data");
return nil;
}
if (!key || [key length] != NAAEADKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid key");
return nil;
}
__block unsigned long long outLength;
__block int retval = -1;
NSMutableData *outData = NAData(self.secureDataEnabled, data.length, ^(void *bytes, NSUInteger length) {
retval = crypto_aead_chacha20poly1305_decrypt(bytes, &outLength,
NULL,
[data bytes], [data length],
[additionalData bytes], [additionalData length],
[nonce bytes],
[key bytes]);
});
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeVerificationFailed, @"Verification failed");
return nil;
}
return [outData na_truncate:outData.length - (NSUInteger)outLength];
}
@end
+24
View File
@@ -0,0 +1,24 @@
//
// NAAuth.h
// NAChloride
//
// Created by Gabriel on 6/16/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
Computes an authentication tag for a message and a secret key, and provides a way to verify that a given tag is valid for a given message and a key.
*/
@interface NAAuth : NSObject
- (NSData *)auth:(NSData *)data key:(NSData *)key error:(NSError **)error;
/*!
Returns YES if verifies OK.
*/
- (BOOL)verify:(NSData *)auth data:(NSData *)data key:(NSData *)key error:(NSError **)error;
@end
+50
View File
@@ -0,0 +1,50 @@
//
// NAAuth.m
// NAChloride
//
// Created by Gabriel on 6/16/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import "NAAuth.h"
#import "NAInterface.h"
#import "sodium.h"
@implementation NAAuth
+ (void)initialize { NAChlorideInit(); }
- (NSData *)auth:(NSData *)data key:(NSData *)key error:(NSError **)error {
if (!key || [key length] != NAAuthKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid key");
return nil;
}
NSMutableData *outData = [NSMutableData dataWithLength:NAAuthSize];
crypto_auth([outData mutableBytes], [data bytes], [data length], [key bytes]);
return outData;
}
- (BOOL)verify:(NSData *)auth data:(NSData *)data key:(NSData *)key error:(NSError **)error {
if (!key || [key length] != NAAuthKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid key");
return NO;
}
if (!auth || [auth length] != NAAuthSize) {
if (error) *error = NAError(NAErrorCodeInvalidData, @"Invalid data");
return NO;
}
if (crypto_auth_verify([auth bytes], [data bytes], [data length], [key bytes]) != 0) {
if (error) *error = NAError(NAErrorCodeVerificationFailed, @"Verification failed");
return NO; // Message forged!
}
return YES;
}
@end
+21
View File
@@ -0,0 +1,21 @@
//
// NABox.h
// NAChloride
//
// Created by Gabriel on 6/18/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "NABoxKeypair.h"
@interface NABox : NSObject
@property (getter=isSecureDataEnabled) BOOL secureDataEnabled;
- (NSData *)encrypt:(NSData *)data nonce:(NSData *)nonce keypair:(NABoxKeypair *)keypair error:(NSError **)error;
- (NSData *)decrypt:(NSData *)data nonce:(NSData *)nonce keypair:(NABoxKeypair *)keypair error:(NSError **)error;
@end
+78
View File
@@ -0,0 +1,78 @@
//
// NABox.m
// NAChloride
//
// Created by Gabriel on 6/18/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import "NABox.h"
#import "NAInterface.h"
#import "sodium.h"
@implementation NABox
+ (void)initialize { NAChlorideInit(); }
- (NSData *)encrypt:(NSData *)data nonce:(NSData *)nonce keypair:(NABoxKeypair *)keypair error:(NSError **)error {
if (!nonce || [nonce length] != NABoxNonceSize) {
if (error) *error = NAError(NAErrorCodeInvalidNonce, @"Invalid nonce");
return nil;
}
if (!data) {
if (error) *error = NAError(NAErrorCodeInvalidData, @"Invalid data");
return nil;
}
if (!keypair) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid keypair");
return nil;
}
NSMutableData *outData = [NSMutableData dataWithLength:[data length] + NABoxMACSize];
int retval = crypto_box_easy([outData mutableBytes],
[data bytes], [data length],
[nonce bytes],
[keypair.publicKey bytes],
[keypair.secretKey bytes]);
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeFailure, @"Encrypt (box) failed");
return nil;
}
return outData;
}
- (NSData *)decrypt:(NSData *)data nonce:(NSData *)nonce keypair:(NABoxKeypair *)keypair error:(NSError **)error {
if (!nonce || [nonce length] != NABoxNonceSize) {
if (error) *error = NAError(NAErrorCodeInvalidNonce, @"Invalid nonce");
return nil;
}
if (!data) {
if (error) *error = NAError(NAErrorCodeInvalidData, @"Invalid data");
return nil;
}
__block int retval = -1;
NSMutableData *outData = NAData(self.secureDataEnabled, data.length, ^(void *bytes, NSUInteger length) {
retval = crypto_box_open_easy(bytes,
[data bytes], [data length],
[nonce bytes],
[keypair.publicKey bytes],
[keypair.secretKey bytes]);
});
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeVerificationFailed, @"Verification failed");
return nil;
}
return [outData na_truncate:NABoxMACSize];
}
@end
+22
View File
@@ -0,0 +1,22 @@
//
// NABoxKeypair.h
// NAChloride
//
// Created by Gabriel on 6/18/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "NASecureData.h"
@interface NABoxKeypair : NSObject
@property (readonly) NSData *publicKey;
@property (readonly) NASecureData *secretKey;
- (instancetype)initWithPublicKey:(NSData *)publicKey secretKey:(NASecureData *)secretKey error:(NSError **)error;
+ (instancetype)generate:(NSError **)error;
@end
+57
View File
@@ -0,0 +1,57 @@
//
// NABoxKeypair.m
// NAChloride
//
// Created by Gabriel on 6/18/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import "NABoxKeypair.h"
#import "NAInterface.h"
#import "NASecureData.h"
#import "sodium.h"
@interface NABoxKeypair ()
@property NSData *publicKey;
@property NASecureData *secretKey;
@end
@implementation NABoxKeypair
+ (void)initialize { NAChlorideInit(); }
- (instancetype)initWithPublicKey:(NSData *)publicKey secretKey:(NASecureData *)secretKey error:(NSError **)error {
if ((self = [super init])) {
if (!publicKey || [publicKey length] != NABoxPublicKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid public key");
return nil;
}
if (!secretKey || [secretKey length] != NABoxPublicKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid secret key");
return nil;
}
_publicKey = publicKey;
_secretKey = secretKey;
}
return self;
}
+ (instancetype)generate:(NSError **)error {
NSMutableData *publicKey = [NSMutableData dataWithLength:NABoxPublicKeySize];
__block int retval = -1;
NASecureData *secretKey = [NASecureData secureReadOnlyDataWithLength:NABoxSecretKeySize completion:^(void *bytes, NSUInteger length) {
retval = crypto_box_keypair([publicKey mutableBytes], bytes);
}];
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeFailure, @"Keypair generate failed");
return nil;
}
return [[NABoxKeypair alloc] initWithPublicKey:publicKey secretKey:secretKey error:error];
}
@end
+30
View File
@@ -0,0 +1,30 @@
//
// NAChloride.h
// NAChloride
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
//! Project version number for NAChloride.
FOUNDATION_EXPORT double NAChlorideVersionNumber;
//! Project version string for NAChloride.
FOUNDATION_EXPORT const unsigned char NAChlorideVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <NAChloride/PublicHeader.h>
#import <NAChloride/NAInterface.h>
#import <NAChloride/NASecretBox.h>
#import <NAChloride/NABox.h>
#import <NAChloride/NABoxKeypair.h>
#import <NAChloride/NAAuth.h>
#import <NAChloride/NAAEAD.h>
#import <NAChloride/NAOneTimeAuth.h>
#import <NAChloride/NAScrypt.h>
#import <NAChloride/NAStream.h>
#import <NAChloride/NARandom.h>
#import <NAChloride/NASecureData.h>
+64
View File
@@ -0,0 +1,64 @@
//
// NAInterface.h
// NAChloride
//
// Created by Gabriel on 6/25/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM (NSInteger, NAErrorCode) {
NAErrorCodeFailure = 1, // Generic failure
NAErrorCodeInvalidNonce = 100,
NAErrorCodeInvalidKey = 101,
NAErrorCodeInvalidData = 102,
NAErrorCodeInvalidSalt = 103,
NAErrorCodeInvalidAdditionalData = 104, // For AEAD
NAErrorCodeVerificationFailed = 205, // Verification failed
};
extern const size_t NASecretBoxKeySize;
extern const size_t NASecretBoxNonceSize;
extern const size_t NASecretBoxMACSize;
extern const size_t NABoxPublicKeySize;
extern const size_t NABoxSecretKeySize;
extern const size_t NABoxNonceSize;
extern const size_t NABoxMACSize;
extern const size_t NAAuthKeySize;
extern const size_t NAAuthSize;
extern const size_t NAOneTimeAuthKeySize;
extern const size_t NAOneTimeAuthSize;
extern const size_t NAScryptSaltSize;
extern const size_t NAStreamKeySize;
extern const size_t NAStreamNonceSize;
extern const size_t NAXSalsaKeySize;
extern const size_t NAXSalsaNonceSize;
extern const size_t NAAEADKeySize;
extern const size_t NAAEADNonceSize;
extern const size_t NAAEADASize;
// Thread safe libsodium init
void NAChlorideInit(void);
// Don't call this directly (use NAChlorideInit). This is made accessible for testing.
int NASodiumInit(void);
typedef id (^NAWork)(NSError **error);
typedef void (^NACompletion)(NSError *error, id output);
void NADispatch(dispatch_queue_t queue, NAWork work, NACompletion completion);
#define NAError(CODE, DESC) [NSError errorWithDomain:@"NAChloride" code:CODE userInfo:@{NSLocalizedDescriptionKey: DESC}];
typedef void (^NADataCompletion)(void *bytes, NSUInteger length);
+60
View File
@@ -0,0 +1,60 @@
//
// NAInterface.m
// NACL
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NAInterface.h"
#import "sodium.h"
const size_t NASecretBoxKeySize = crypto_secretbox_KEYBYTES;
const size_t NASecretBoxNonceSize = crypto_secretbox_NONCEBYTES;
const size_t NASecretBoxMACSize = crypto_secretbox_MACBYTES;
const size_t NABoxPublicKeySize = crypto_box_PUBLICKEYBYTES;
const size_t NABoxSecretKeySize = crypto_box_SECRETKEYBYTES;
const size_t NABoxNonceSize = crypto_box_NONCEBYTES;
const size_t NABoxMACSize = crypto_box_MACBYTES;
const size_t NAAuthKeySize = crypto_auth_KEYBYTES;
const size_t NAAuthSize = crypto_auth_BYTES;
const size_t NAOneTimeAuthKeySize = crypto_onetimeauth_KEYBYTES;
const size_t NAOneTimeAuthSize = crypto_onetimeauth_BYTES;
const size_t NAScryptSaltSize = crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
const size_t NAStreamKeySize = crypto_stream_KEYBYTES;
const size_t NAStreamNonceSize = crypto_stream_NONCEBYTES;
const size_t NAXSalsaKeySize = crypto_stream_xsalsa20_KEYBYTES;
const size_t NAXSalsaNonceSize = crypto_stream_xsalsa20_NONCEBYTES;
const size_t NAAEADKeySize = crypto_aead_chacha20poly1305_KEYBYTES;
const size_t NAAEADNonceSize = crypto_aead_chacha20poly1305_NPUBBYTES;
const size_t NAAEADASize = crypto_aead_chacha20poly1305_ABYTES;
void NAChlorideInit(void) {
static dispatch_once_t sodiumInit;
dispatch_once(&sodiumInit, ^{ NASodiumInit(); });
}
int NASodiumInit(void) {
return sodium_init();
}
void NADispatch(dispatch_queue_t queue, NAWork work, NACompletion completion) {
dispatch_async(queue, ^{
NSError *error = nil;
id output = work(&error);
dispatch_async(dispatch_get_main_queue(), ^{
completion(error, output);
});
});
}
+24
View File
@@ -0,0 +1,24 @@
//
// NAOneTimeAuth.h
// NAChloride
//
// Created by Gabriel on 9/24/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
Generates a MAC for a given message and shared key using Poly1305 algorithm
(key may NOT be reused across messages).
*/
@interface NAOneTimeAuth : NSObject
- (NSData *)auth:(NSData *)data key:(NSData *)key error:(NSError **)error;
/*!
Returns YES if verifies OK.
*/
- (BOOL)verify:(NSData *)auth data:(NSData *)data key:(NSData *)key error:(NSError **)error;
@end
+49
View File
@@ -0,0 +1,49 @@
//
// NAOneTimeAuth.m
// NAChloride
//
// Created by Gabriel on 9/24/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NAOneTimeAuth.h"
#import "NAInterface.h"
#import "sodium.h"
@implementation NAOneTimeAuth
+ (void)initialize { NAChlorideInit(); }
- (NSData *)auth:(NSData *)data key:(NSData *)key error:(NSError **)error {
if (!key || [key length] != NAOneTimeAuthKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid key");
return nil;
}
NSMutableData *outData = [NSMutableData dataWithLength:NAOneTimeAuthSize];
crypto_onetimeauth([outData mutableBytes], [data bytes], [data length], [key bytes]);
return outData;
}
- (BOOL)verify:(NSData *)auth data:(NSData *)data key:(NSData *)key error:(NSError **)error {
if (!key || [key length] != NAOneTimeAuthKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid key");
return NO;
}
if (!auth || [auth length] != NAOneTimeAuthSize) {
if (error) *error = NAError(NAErrorCodeInvalidData, @"Invalid data");
return NO;
}
if (crypto_onetimeauth_verify([auth bytes], [data bytes], [data length], [key bytes]) != 0) {
if (error) *error = NAError(NAErrorCodeVerificationFailed, @"Verification failed");
return NO; // Message forged!
}
return YES;
}
@end
+25
View File
@@ -0,0 +1,25 @@
//
// NARandom.h
// NAChloride
//
// Created by Gabriel on 6/16/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "NASecureData.h"
@interface NARandom : NSObject
/*!
Random data of length bytes.
*/
+ (NSData *)randomData:(NSUInteger)length;
/*!
Random & secure data of length bytes.
*/
+ (NASecureData *)randomSecureReadOnlyData:(NSUInteger)length;
@end
+32
View File
@@ -0,0 +1,32 @@
//
// NARandom.m
// NAChloride
//
// Created by Gabriel on 6/16/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import "NARandom.h"
#import "NAInterface.h"
#import "sodium.h"
@implementation NARandom
+ (void)initialize { NAChlorideInit(); }
+ (NSData *)randomData:(NSUInteger)length {
NSMutableData *outData = [NSMutableData dataWithLength:length];
randombytes_buf([outData mutableBytes], length);
return outData;
}
+ (NASecureData *)randomSecureReadOnlyData:(NSUInteger)length {
NASecureData *secureData = [NASecureData secureReadOnlyDataWithLength:length completion:^(void *bytes, NSUInteger length) {
randombytes_buf(bytes, length);
}];
return secureData;
}
@end
+29
View File
@@ -0,0 +1,29 @@
//
// NAScrypt.h
// NAChloride
//
// Created by Gabriel on 6/19/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NAScrypt : NSObject
/*!
Key derivation.
@param password Password
@param salt Must be NAScryptSaltSize
Default opslimit is crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE.
Default memlimit is crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE.
*/
+ (NSData *)scrypt:(NSData *)password salt:(NSData *)salt error:(NSError **)error;
/*!
Use the default scrypt. This is for advanced use only.
*/
+ (NSData *)scrypt:(NSData *)password salt:(NSData *)salt N:(uint64_t)N r:(uint32_t)r p:(uint32_t)p length:(size_t)length error:(NSError **)error;
@end
+51
View File
@@ -0,0 +1,51 @@
//
// NAScrypt.m
// NAChloride
//
// Created by Gabriel on 6/19/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NAScrypt.h"
#import "NAInterface.h"
#import "sodium.h"
@implementation NAScrypt
+ (void)initialize { NAChlorideInit(); }
+ (NSData *)scrypt:(NSData *)password salt:(NSData *)salt error:(NSError **)error {
if (!salt || [salt length] != NAScryptSaltSize) {
if (error) *error = NAError(NAErrorCodeInvalidSalt, @"Invalid salt")
return nil;
}
NSMutableData *key = [NSMutableData dataWithLength:crypto_box_SEEDBYTES];
int retval = crypto_pwhash_scryptsalsa208sha256([key mutableBytes], key.length, password.bytes, password.length, salt.bytes, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE, crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeFailure, @"Scrypt failed");
return nil;
}
return key;
}
+ (NSData *)scrypt:(NSData *)password salt:(NSData *)salt N:(uint64_t)N r:(uint32_t)r p:(uint32_t)p length:(size_t)length error:(NSError **)error {
NSMutableData *outData = [NSMutableData dataWithLength:length];
int retval = crypto_pwhash_scryptsalsa208sha256_ll((uint8_t *)password.bytes, password.length, (uint8_t *)salt.bytes, salt.length, N, r, p, [outData mutableBytes], outData.length);
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeFailure, @"Scrypt failed");
return nil;
}
NSAssert([outData length] == length, @"Mismatched output length");
return outData;
}
@end
+22
View File
@@ -0,0 +1,22 @@
//
// NASecretBox.h
// NACL
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
/*!
Encrypts and authenticates a message using a shared key and nonce.
*/
@interface NASecretBox : NSObject
@property (getter=isSecureDataEnabled) BOOL secureDataEnabled;
- (NSData *)encrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error;
- (NSData *)decrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error;
@end
+84
View File
@@ -0,0 +1,84 @@
//
// NASecretBox.m
// NACL
//
// Created by Gabriel Handford on 1/16/14.
// Copyright (c) 2014 Gabriel Handford. All rights reserved.
//
#import "NASecretBox.h"
#import "NAInterface.h"
#import "NASecureData.h"
#import "sodium.h"
@implementation NASecretBox
+ (void)initialize { NAChlorideInit(); }
- (NSData *)encrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error {
if (!nonce || [nonce length] != NASecretBoxNonceSize) {
if (error) *error = NAError(NAErrorCodeInvalidNonce, @"Invalid nonce");
return nil;
}
if (!data) {
if (error) *error = NAError(NAErrorCodeInvalidData, @"Invalid data");
return nil;
}
if (!key || [key length] != NASecretBoxKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid key");
return nil;
}
// Add space for authentication tag of size MACBYTES
NSMutableData *outData = [NSMutableData dataWithLength:[data length] + NASecretBoxMACSize];
int retval = crypto_secretbox_easy([outData mutableBytes],
[data bytes], [data length],
[nonce bytes],
[key bytes]);
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeFailure, @"Encrypt (secret box) failed");
return nil;
}
return outData;
}
- (NSData *)decrypt:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error {
if (!nonce || [nonce length] != NASecretBoxNonceSize) {
if (error) *error = NAError(NAErrorCodeInvalidNonce, @"Invalid nonce");
return nil;
}
if (!data) {
if (error) *error = NAError(NAErrorCodeInvalidData, @"Invalid data");
return nil;
}
if (!key || [key length] != NASecretBoxKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid key");
return nil;
}
__block int retval = -1;
NSMutableData *outData = NAData(self.secureDataEnabled, data.length, ^(void *bytes, NSUInteger length) {
retval = crypto_secretbox_open_easy(bytes,
[data bytes], [data length],
[nonce bytes], [key bytes]);
});
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeVerificationFailed, @"Verification failed");
return nil;
}
// Remove MAC bytes from data
return [outData na_truncate:NASecretBoxMACSize];
}
@end
+52
View File
@@ -0,0 +1,52 @@
//
// NASecureData.h
// NAChloride
//
// Created by Gabriel on 6/19/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "NAInterface.h"
typedef NS_ENUM (NSInteger, NASecureDataProtection) {
NASecureDataProtectionReadWrite = 0, // Default no protection
NASecureDataProtectionReadOnly,
NASecureDataProtectionNoAccess,
};
/*!
Secure memory using libsodium.
*/
@interface NASecureData : NSMutableData // Subclassing for convienience
@property (nonatomic) NASecureDataProtection protection;
/*!
Secure and read only data.
*/
+ (instancetype)secureReadOnlyDataWithLength:(NSUInteger)length completion:(NADataCompletion)completion;
/*!
Secure data is has read/write protection in this block.
*/
- (void)readWrite:(void (^)(NASecureData *secureData))completion;
/*!
Truncate.
*/
- (NASecureData *)truncate:(NSUInteger)length;
@end
// Optional building of secure NSData
NSMutableData *NAData(BOOL secure, NSUInteger length, NADataCompletion completion);
@interface NSMutableData (NASecureData)
- (NSData *)na_truncate:(NSUInteger)length;
@end
+100
View File
@@ -0,0 +1,100 @@
//
// NASecureData.m
// NAChloride
//
// Created by Gabriel on 6/19/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import "NASecureData.h"
#import "NAInterface.h"
#import "sodium.h"
@interface NASecureData ()
@property void *secureBytes;
@property NSUInteger secureLength;
@end
@implementation NASecureData
+ (void)initialize { NAChlorideInit(); }
- (instancetype)initWithLength:(NSUInteger)length {
if ((self = [super init])) {
NAChlorideInit(); // It's already init'ed, but just to be safe
_secureLength = length;
_secureBytes = sodium_malloc(length);
}
return self;
}
+ (instancetype)secureReadOnlyDataWithLength:(NSUInteger)length completion:(NADataCompletion)completion {
NASecureData *secureData = [[NASecureData alloc] initWithLength:length];
completion(secureData.secureBytes, secureData.length);
secureData.protection = NASecureDataProtectionReadOnly;
return secureData;
}
- (void)dealloc {
sodium_free(_secureBytes);
}
- (void)setProtection:(NASecureDataProtection)protection {
switch (protection) {
// Keep these case statements order from most secure to least secure in case some jerk removes a break;
case NASecureDataProtectionReadWrite: sodium_mprotect_readwrite(_secureBytes); break;
case NASecureDataProtectionReadOnly: sodium_mprotect_readonly(_secureBytes); break;
case NASecureDataProtectionNoAccess: sodium_mprotect_noaccess(_secureBytes); break;
}
}
- (NSUInteger)length {
return _secureLength;
}
- (const void *)bytes {
return _secureBytes;
}
- (void *)mutableBytes {
return _secureBytes;
}
- (void)readWrite:(void (^)(NASecureData *secureData))completion {
NASecureDataProtection protection = self.protection;
self.protection = NASecureDataProtectionReadWrite;
completion(self);
self.protection = protection;
}
- (NASecureData *)truncate:(NSUInteger)length {
if (length == 0) return self;
return [NASecureData secureReadOnlyDataWithLength:(self.length - length) completion:^(void *bytes, NSUInteger length) {
memcpy(bytes, self.bytes, length);
}];
}
- (NSData *)na_truncate:(NSUInteger)length { return [self truncate:length]; }
@end
NSMutableData *NAData(BOOL secure, NSUInteger length, NADataCompletion completion) {
if (!secure) {
NSMutableData *data = [NSMutableData dataWithLength:length];
completion([data mutableBytes], length);
return data;
} else {
return [NASecureData secureReadOnlyDataWithLength:length completion:completion];
}
}
@implementation NSMutableData (NASecureData)
- (NSData *)na_truncate:(NSUInteger)length {
if (length == 0) return self;
return [NSData dataWithBytes:self.bytes length:self.length - length];
}
@end
+15
View File
@@ -0,0 +1,15 @@
//
// NAStream.h
// NAChloride
//
// Created by Gabriel on 6/18/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NAStream : NSObject
- (NSData *)xor:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error;
@end
+41
View File
@@ -0,0 +1,41 @@
//
// NAStream.m
// NAChloride
//
// Created by Gabriel on 6/18/15.
// Copyright (c) 2015 Gabriel Handford. All rights reserved.
//
#import "NAStream.h"
#import "NAInterface.h"
#import "sodium.h"
@implementation NAStream
+ (void)initialize { NAChlorideInit(); }
- (NSData *)xor:(NSData *)data nonce:(NSData *)nonce key:(NSData *)key error:(NSError **)error {
if (!nonce || [nonce length] < NAStreamNonceSize) {
if (error) *error = NAError(NAErrorCodeInvalidNonce, @"Invalid stream nonce");
return nil;
}
if (!key || [key length] != NAStreamKeySize) {
if (error) *error = NAError(NAErrorCodeInvalidKey, @"Invalid stream key");
return nil;
}
NSMutableData *outData = [NSMutableData dataWithLength:[data length]];
int retval = crypto_stream_xor([outData mutableBytes], [data bytes], [data length], [nonce bytes], [key bytes]);
if (retval != 0) {
if (error) *error = NAError(NAErrorCodeFailure, @"Stream failed");
return nil;
}
return outData;
}
@end