【问题标题】:Generating 64 bytes long NSData from key string从密钥字符串生成 64 字节长的 NSData
【发布时间】:2016-04-23 14:18:03
【问题描述】:

我认为这会生成随机的 64 字节 NSData。

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

我想像这样生成 64 字节的 NSData,但不是随机数据。 如何使用给定的键(如“com.this.is.akey”)生成 64 字节的 NSData。

试过这个,但它给了我错误的字节大小(不是 64 字节)。

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

【问题讨论】:

标签: ios objective-c xcode encryption realm


【解决方案1】:

您可以使用-[NSString dataUsingEncoding:]NSString 转换为NSData

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

如果数据长度小于或大于 64 字节,则应填充或截断数据以精确到 64 字节。

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

然后,您可以将NSData 对象传递给RLMRealmConfiguration.encryptionKey

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

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

【讨论】:

  • 关闭,但直接使用字符串进行加密非常不安全,应使用派生密钥,例如由 PBKDF2 创建的
【解决方案2】:

给定一个密钥字符串,应该使用密钥派生函数,例如 PBKDF2。

例子:

#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);

输出:派生密钥:

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

注意事项:

  1. 最好将盐值设置为随机值,并与派生密钥一起提供。

  2. 应设置迭代计数以提供合适的推导时间,可能为 100 毫秒。有一个相应的CCCalibratePBKDF 函数可以帮助解决这个问题。迭代计数也可以与派生密钥一起提供。

  3. 很抱歉,这似乎需要更多的工作,但安全性不容易做到。

【讨论】:

  • 因此,如果我每次都为字符串键(例如“this.is.akey”)提供相同的盐字符串(例如“salt”)和相同的迭代次数(例如 100),那么我会得到相同的结果输出。这是正确的吗?
  • 在注释 1 中,您说将盐设置为随机值。如果我改变盐,它不会影响输出吗?
  • 是的,相同的盐、密钥、迭代次数将产生相同的密钥。当使用随机盐时,它与加密数据一起传递,因此相同的盐用于解密。请参阅RNCryptor spec 了解正确完成的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 2016-02-12
  • 1970-01-01
  • 2012-01-31
  • 2021-07-07
相关资源
最近更新 更多