在 IOS 中实施 PBEKeySpec 加密

implementing PBEKeySpec encryption into IOS

这是我的 java 代码。现在我想在 Objective-C.

中实现相同的功能
int dkLen = 16;
int rounds = 1000;
PBEKeySpec keySpec = new PBEKeySpec(hashKey.toCharArray(),salt.getBytes(), rounds, dkLen * 8);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
return factory.generateSecret(keySpec).getEncoded();

这是我的 iOS 实现

- (void)getHashKey {
      NSString *hash_key=@"MY_HASHKEY";
      NSString *saltKey = @"MY_SALTKEY";

      int dkLen = 16;
      NSData *keyData = [hash_key dataUsingEncoding:NSUTF8StringEncoding];
      NSData *salt    = [saltKey dataUsingEncoding:NSUTF8StringEncoding];
      uint    rounds  = 1000;
      uint    keySize = kCCKeySizeAES128;

      NSMutableData *derivedKey = [NSMutableData dataWithLength:keySize];

      CCKeyDerivationPBKDF(kCCPBKDF2,               // algorithm
                           keyData.bytes,           // password
                           keyData.length,          // passwordLength
                           salt.bytes,              // salt
                           salt.length,             // saltLen
                           kCCPRFHmacAlgSHA1,       // PRF
                           rounds,                  // rounds
                           derivedKey.mutableBytes, // derivedKey
                           dkLen*8);                // derivedKeyLen

       NSString *myString = [[NSString alloc] initWithData:derivedKey encoding:NSASCIIStringEncoding];
       NSLog(@"derivedKey: %@", myString);
}

我在 iOS

中使用的算法有问题吗

使用 Common Crypto CCKeyDerivationPBKDF 函数和选项 kCCPRFHmacAlgSHA1

注意PBEKeySpeckeyLength以位为单位,CCKeyDerivationPBKDFderivedKeyLen以字节为单位。

要获得更详细的答案,请提供所有输入(hashKey、salt)和十六进制转储格式的输出加上轮数、以字节为单位的输出长度。

查看示例代码SO answer

Update for revised question code:

CCKeyDerivationPBKDF returns 8 位数据字节,本质上不是字符,即使强制进入 NSASCIIStringEncoding,许多字节也不可打印。即使没有返回错误也强制 NSASCIIStringEncoding 是不正确且无用的。而是使用返回的 NSData 或转换为 Base64 或 HexASCII 编码。

改变

NSString *myString =    [[NSString alloc] initWithData:derivedKey encoding:NSASCIIStringEncoding];

Output: A´Öº÷"ùïó

NSString * myString = [derivedKey base64EncodedStringWithOptions:0];

Output: QbTWgbr3FSL57/MfBQAz4A==

注意:1000 发通常被认为不够用,应该使用 10,000 到 100,000 范围内的东西。

iPhone 6S 的计时:

rounds  seconds
1000    0.003  
10000   0.032  
100000  0.309  
1000000 3.047