Lee
Lee

Reputation: 35

Generating 64 bytes long NSData from key string

I think this generates random 64 bytes NSData.

uint8_t buffer[64];
SecRandomCopyBytes(kSecRandomDefault, 64, buffer);
NSData *keyData = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];

I want to generate 64 bytes NSData like this but not a random data. How can I generate 64 bytes NSData with a given key like "com.this.is.akey".

Tried this one but it gave me wrong bytes size(not 64 bytes).

NSString *base64EncodedString = [[@"somekey.here" dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
NSData *encodedData = [[NSData alloc] initWithBase64EncodedString:base64EncodedString
                                                          options:0];

Upvotes: 2

Views: 2363

Answers (2)

zaph
zaph

Reputation: 112857

Given a string for a key one should use a key derivation function such as PBKDF2.

Example:

#import <CommonCrypto/CommonCrypto.h>

NSString *keyString = @"com.this.is.key"; // Should use a random value
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
NSData *salt = [@"saltstring" dataUsingEncoding:NSUTF8StringEncoding];

NSMutableData *derivedKey = [NSMutableData dataWithLength:CC_SHA512_DIGEST_LENGTH];
CCKeyDerivationPBKDF(kCCPBKDF2,
                     keyData.bytes, keyData.length,
                     salt.bytes, salt.length,
                     kCCPRFHmacAlgSHA512,
                     10000, // Choose for desired timing
                     derivedKey.mutableBytes, derivedKey.length);

NSLog(@"derivedKey: %@", derivedKey);

Output: derivedKey:

065d2106 1da7ebcf d155a50a b1ee5540 dee8efce f4678c47 02164488 e92e05e5 30c1f12d a3813013 652aca1b 0016b258 610d7929 f240de72 3eab85d9 7e028b35

Notes:

  1. It is best to set the salt to a random value and provide it along with the derived key.

  2. The iteration count should set to provide a suitable derivation tine, perhaps 100ms. There is a corresponding CCCalibratePBKDF function the help with this. The iteration count can also be provided along with the derived key.

  3. Sorry if this seems to be more work that necessary but security is not easy to get right.

Upvotes: 1

kishikawa katsumi
kishikawa katsumi

Reputation: 10573

You can use -[NSString dataUsingEncoding:] to convert NSString to NSData.

NSString *key = @"com.this.is.akey";
NSData *keyData = [key dataUsingEncoding:NSASCIIStringEncoding];

If length of the data is less or greater than 64 bytes, you should pad or truncate data to exact 64 bytes.

if (keyData.length != 64) {
    NSMutableData *mutableData = keyData.mutableCopy;
    mutableData.length = 64;
    keyData = mutableData.copy;
}

Then, you can pass the NSData object to RLMRealmConfiguration.encryptionKey.

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.encryptionKey = keyData;

NSError *error = nil;
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];

Upvotes: 2

Related Questions