Skip to content

Commit

Permalink
updates salt-manipulation to use BNRSalt
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-w committed Aug 14, 2013
1 parent 46e4fad commit 20ab921
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 46 deletions.
5 changes: 3 additions & 2 deletions BNRPersistence/BNRClassMetaData.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@


#import <Foundation/Foundation.h>
#import "BNRSalt.h"
@class BNRDataBuffer;

/*!
Expand Down Expand Up @@ -55,7 +56,7 @@
unsigned char classID;
volatile UInt32 lastPrimaryKey;
unsigned char versionNumber;
UInt32 encryptionKeySalt[2];
BNRSalt salt;
}

/*!
Expand Down Expand Up @@ -108,6 +109,6 @@
@method encryptionKeySalt
@abstract Returns the encryption key salt value used on with this class's data.
*/
- (const UInt32 *)encryptionKeySalt;
- (const BNRSalt *)encryptionKeySalt;

@end
16 changes: 7 additions & 9 deletions BNRPersistence/BNRClassMetaData.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ - (id)init
classID = 0;

// Randomize the salt to start with; if a class is being loaded the salt will be set in -readContentFromBuffer:.
BNRRandomBytes(encryptionKeySalt, 8);
BNRRandomBytes(&salt.word, sizeof(salt.word));
}
return self;
}
Expand All @@ -48,9 +48,8 @@ - (void)readContentFromBuffer:(BNRDataBuffer *)d
classID = [d readUInt8];
if ([d length] > 6)
{
size_t keylen = sizeof(encryptionKeySalt)/sizeof(*encryptionKeySalt);
for (int i = 0; i < keylen; i++)
encryptionKeySalt[i] = [d readUInt32];
for (int i = 0; i < BNR_SALT_WORD_COUNT; i++)
salt.word[i] = [d readUInt32];
}

}
Expand All @@ -60,9 +59,8 @@ - (void)writeContentToBuffer:(BNRDataBuffer *)d
[d writeUInt8:versionNumber];
[d writeUInt8:classID];

size_t keylen = sizeof(encryptionKeySalt)/sizeof(*encryptionKeySalt);
for (int i = 0; i < keylen; i++)
[d writeUInt32:encryptionKeySalt[i]];
for (int i = 0; i < BNR_SALT_WORD_COUNT; i++)
[d writeUInt32:salt.word[i]];
}
- (unsigned char )classID
{
Expand Down Expand Up @@ -90,8 +88,8 @@ - (void)setVersionNumber:(unsigned char)x
versionNumber = x;
}

- (const UInt32 *)encryptionKeySalt
- (const BNRSalt *)encryptionKeySalt
{
return encryptionKeySalt;
return &salt;
}
@end
1 change: 1 addition & 0 deletions BNRPersistence/BNRCrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Adam Preble on 4/8/10.
// Copyright 2010 Big Nerd Ranch. All rights reserved.
//
#import <sys/types.h>

/*! Fills |buffer| with |length| random bytes. */
void BNRRandomBytes(void *buffer, size_t length);
5 changes: 3 additions & 2 deletions BNRPersistence/BNRDataBuffer+Encryption.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

#import <Foundation/Foundation.h>
#import "BNRDataBuffer.h"
#import "BNRSalt.h"

@interface BNRDataBuffer (Encryption)

- (BOOL)decryptWithKey:(NSString *)key salt:(const UInt32 *)salt;
- (void)encryptWithKey:(NSString *)key salt:(const UInt32 *)salt;
- (BOOL)decryptWithKey:(NSString *)key salt:(const BNRSalt *)salt;
- (void)encryptWithKey:(NSString *)key salt:(const BNRSalt *)salt;

@end
44 changes: 23 additions & 21 deletions BNRPersistence/BNRDataBuffer+Encryption.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,27 @@
It is the caller's responsiblity to free() this memory.
@param outDataLength (output) Number of bytes of data in outData.
*/
BOOL CryptHelper(NSString *key, const UInt32 *salt, CCOperation operation, const void *data, size_t length, void **outData, size_t *outDataLength)
BOOL CryptHelper(NSString *key, const BNRSalt *salt, CCOperation operation, const void *data, size_t length, void **outData, size_t *outDataLength)
{
if (key == nil || [key length] == 0)
return NO;

*outData = NULL;
*outDataLength = 0;


NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];

// Create a hash of the key.
CC_MD5_CTX ctx;
CC_MD5_Init(&ctx);
CC_MD5_Update(&ctx, (void*)salt, 8);
CC_MD5_Update(&ctx, (void*)[key UTF8String], [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
CC_MD5_Update(&ctx, (void*)&salt->word, sizeof(salt->word));
CC_MD5_Update(&ctx, [keyData bytes], [keyData length]);
UInt32 md[4];
CC_MD5_Final((unsigned char*)md, &ctx);

CCCryptorRef cryptor = nil;
CCOptions options = operation == kCCEncrypt ? kCCOptionPKCS7Padding : 0;
CCCryptorStatus status = CCCryptorCreate(operation, kCCAlgorithmAES128, options, md, 4*sizeof(UInt32), NULL, &cryptor);
CCCryptorStatus status = CCCryptorCreate(operation, kCCAlgorithmAES128, options, md, sizeof(md), NULL/*IV*/, &cryptor);

if (status != kCCSuccess) {
NSLog(@"CCCryptorCreate(): error:%d", status);
Expand Down Expand Up @@ -90,21 +92,22 @@ BOOL CryptHelper(NSString *key, const UInt32 *salt, CCOperation operation, const

@implementation BNRDataBuffer (Encryption)

- (BOOL)decryptWithKey:(NSString *)key salt:(const UInt32 *)salt
- (BOOL)decryptWithKey:(NSString *)key salt:(const BNRSalt *)salt
{
if (key == nil || [key length] == 0)
return YES;

BOOL ret = YES;

UInt32 littleSalt[2];
littleSalt[0] = CFSwapInt32HostToLittle(salt[0]);
littleSalt[1] = CFSwapInt32HostToLittle(salt[1]);

BNRSalt littleSalt = *salt;
BNRSaltToLittle(&littleSalt);

void *decryptedBuffer = NULL;
size_t decryptedBufferLength;
BOOL success = CryptHelper(key, littleSalt, kCCDecrypt, buffer, length, &decryptedBuffer, &decryptedBufferLength);
if (success && decryptedBufferLength >= 8 && memcmp(decryptedBuffer, littleSalt, 8) == 0)
BOOL success = CryptHelper(key, &littleSalt, kCCDecrypt, buffer, length, &decryptedBuffer, &decryptedBufferLength);

size_t saltSize = sizeof(littleSalt.word);
if (success && decryptedBufferLength >= saltSize && memcmp(decryptedBuffer, &littleSalt.word, saltSize) == 0)
{
// Salt matches, so we believe the given key is good.
// Let's move the data into our own buffer.
Expand All @@ -122,27 +125,26 @@ - (BOOL)decryptWithKey:(NSString *)key salt:(const UInt32 *)salt
return ret;
}

- (void)encryptWithKey:(NSString *)key salt:(const UInt32 *)salt
- (void)encryptWithKey:(NSString *)key salt:(const BNRSalt *)salt
{
if (key == nil || [key length] == 0)
return;

UInt32 littleSalt[2];
littleSalt[0] = CFSwapInt32HostToLittle(salt[0]);
littleSalt[1] = CFSwapInt32HostToLittle(salt[1]);

BNRSalt littleSalt = *salt;
BNRSaltToLittle(&littleSalt);

// Create a scratch buffer so we can prepend the 8 bytes of salt.
// We will look for these salt bytes when decrypting to confirm that we were successful.
int scratchBufferLength = 8 + length;
UInt8 *scratchBuffer = (UInt8*)malloc(scratchBufferLength);
memcpy(scratchBuffer, littleSalt, 8);
memcpy(scratchBuffer, littleSalt.word, 8);
memcpy(scratchBuffer + 8, buffer, length);

void *encryptedBuffer = NULL;
size_t encryptedBufferLength = 0;
CryptHelper(key, littleSalt, kCCEncrypt, scratchBuffer, scratchBufferLength, &encryptedBuffer, &encryptedBufferLength);

CryptHelper(key, &littleSalt, kCCEncrypt, scratchBuffer, scratchBufferLength, &encryptedBuffer, &encryptedBufferLength);

free(scratchBuffer);

[self setData:encryptedBuffer length:encryptedBufferLength];
Expand Down
27 changes: 15 additions & 12 deletions BNRPersistence/BNRStore.m
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,28 @@ - (void)addClass:(Class)c
classes[classCount] = c;
}

- (void)getSalt:(BNRSalt *)salt forClass:(Class)c rowID:(UInt32)rowID
{
NSParameterAssert(salt != nil);
BNRClassMetaData *metaData = [self metaDataForClass:c];
*salt = *[metaData encryptionKeySalt];
StirBNRSaltWithWords(salt, 0, rowID);
}

- (BOOL)decryptBuffer:(BNRDataBuffer *)buffer ofClass:(Class)c rowID:(UInt32)rowID
{
if (buffer == nil)
return YES;

BNRClassMetaData *metaData = [self metaDataForClass:c];

UInt32 salt[2];
memcpy(salt, [metaData encryptionKeySalt], 8);
salt[1] = salt[1] ^ rowID;

return [buffer decryptWithKey:encryptionKey salt:salt];

BNRSalt salt;
[self getSalt:&salt forClass:c rowID:rowID];
return [buffer decryptWithKey:encryptionKey salt:&salt];
}
- (void)encryptBuffer:(BNRDataBuffer *)buffer ofClass:(Class)c rowID:(UInt32)rowID
{
UInt32 salt[2];
memcpy(salt, [[self metaDataForClass:c] encryptionKeySalt], 8);
salt[1] = salt[1] ^ rowID;
[buffer encryptWithKey:encryptionKey salt:salt]; // does not encrypt if encryptionKey is empty.
BNRSalt salt;
[self getSalt:&salt forClass:c rowID:rowID];
[buffer encryptWithKey:encryptionKey salt:&salt]; // does not encrypt if encryptionKey is empty.
}

#pragma mark Fetching
Expand Down

0 comments on commit 20ab921

Please sign in to comment.