对于这个问题的看似显而易见的道歉,但无论出于何种原因,我都无法在 Apple 文档中找到关于 Settings.bundle 密码信息的存储位置和方式的明确答案。我的问题:如果我需要为应用程序存储一些凭据,并且我使用 Settings.bundle 以便使用 IsSecure = YES 将密码输入到 Apple 设置区域中的 PSTextFieldSpecifier 文本字段中,然后我使用我的应用程序访问该值CFPreferencesCopyAppValue,从不将其写入 NSUserDefaults 并且仅通过网络安全地发送,与在我自己的应用程序设置中使用钥匙串存储和检索密码相比,这种存储和检索方法的安全性如何?感谢您的输入。
3 回答
CFPreferencesCopyAppValue
只是访问您在使用时获得的相同信息的核心基础方式NSUserDefaults
。在安全性方面,功能完全相同。也就是说,它没有加密。只有在它被遮蔽的意义上,它才是安全的。“正确”的答案是使用钥匙串。
与之相反的是,许多应用程序都使用它NSUserDefaults
来存储密码。您可能会争辩说,除非密码控制对任何价值信息的访问,否则尝试使用钥匙串是不值得的。这让我想到了支持在设置应用程序中使用安全字段的第二个论点:钥匙串 API 是可怕的,至少根据我的经验,编写无错误代码是很棘手的。
不要将用户的密码保存在设置包中。
它不安全。
请记住,您不需要知道原始密码是什么,您需要知道用户输入的密码是否与原始密码匹配。在 iOS 中处理密码的正确方法是
- 正如其他人所提到的,使用钥匙串
- 使用 SHA-512 或其他加密生成加密单向哈希函数,并将生成的哈希和盐存储在
NSUserDefaults
在这些选项中,加密密码和存储哈希+盐是迄今为止最简单的。以下是存储密码的方法:
- 从用户那里获取密码
- 创建一个随机盐值
- 使用 SHA-512 和随机盐值创建只进哈希
- 将生成的哈希值和盐值存储在
NSUserDefaults
——黑客无法使用这些值来确定原始密码,因此无需将它们存储在安全的地方。
现在,当用户输入他们的密码并且您必须验证它是否正确时,您可以执行以下操作:
- 从用户那里获取密码
- 获取之前保存的 hash + salt 值
NSUserDefaults
- 使用与加密原始密码相同的单向散列函数创建一个只进散列 - 将尝试的密码和盐值传递给它
NSUserDefaults
- 将生成的哈希与存储在
NSUSerDefaults
. 如果它们相同,则用户输入了正确的密码。
这是生成盐和只进哈希的代码:
NSString *FZARandomSalt(void) {
uint8_t bytes[16] = {0};
int status = SecRandomCopyBytes(kSecRandomDefault, 16, bytes);
if (status == -1) {
NSLog(@"Error using randomization services: %s", strerror(errno));
return nil;
}
NSString *salt = [NSString stringWithFormat: @"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
bytes[0], bytes[1], bytes[2], bytes[3],
bytes[4], bytes[5], bytes[6], bytes[7],
bytes[8], bytes[9], bytes[10], bytes[11],
bytes[12], bytes[13], bytes[14], bytes[15]];
return salt;
}
NSData *FZAHashPassword(NSString *password, NSString *salt) {
NSCParameterAssert([salt length] >= 32);
uint8_t hashBuffer[64] = {0};
NSString *saltedPassword = [[salt substringToIndex: 32] stringByAppendingString: password];
const char *passwordBytes = [saltedPassword cStringUsingEncoding: NSUTF8StringEncoding];
NSUInteger length = [saltedPassword lengthOfBytesUsingEncoding: NSUTF8StringEncoding];
CC_SHA512(passwordBytes, length, hashBuffer);
for (NSInteger i = 0; i < 4999; i++) {
CC_SHA512(hashBuffer, 64, hashBuffer);
}
return [NSData dataWithBytes: hashBuffer length: 64];
}
此示例的代码可在此处找到:http: //blog.securemacprogramming.com/2011/04/storing-and-testing-credentials-cocoa-touch-edition/
iPhone 上的钥匙串将是最安全的,除非您使用自定义加密,这很难做到(和导出)。NSUserDefaults 不被认为是安全的。