在Settings.bundle中存储密码以及使用CFPreferencesCopyAppValue获取的安全隐患

时间:2009-08-08 11:06:59

标签: iphone cocoa-touch security sdk settings.bundle

对于这个问题看似显而易见的道歉,但无论出于何种原因,我都无法在Apple文档中找到关于存储Settings.bundle密码信息的位置和方式的明确答案。我的问题:如果我需要为应用程序存储一些凭据,并且我使用Settings.bundle,以便在Apple的设置区域中使用IsSecure = YES将密码输入到PSTextFieldSpecifier文本字段中,然后我使用我的应用程序访问该值CFPreferencesCopyAppValue,从未将其写入NSUserDefaults并且只通过网络安全地发送,与在我自己的应用程序设置中使用钥匙串存储和检索密码相比,该存储和检索方法有多安全?感谢您的投入。

3 个答案:

答案 0 :(得分:8)

CFPreferencesCopyAppValue只是访问使用NSUserDefaults时获得的相同信息的Core Foundation方式。在安全性方面,功能完全相同。也就是说,它没有加密。只有在它被遮挡的意义上它才是安全的。 “正确”的答案是使用钥匙串。

与此相反的是,许多应用程序使用NSUserDefaults来存储密码。您可以争辩说,除非密码控制对任何值的信息的访问,否则尝试使用钥匙串是不值得的。这让我想到第二个支持在Settings应用程序中使用安全字段的论点:keychain API很可怕,至少根据我的经验,编写无错误的代码很棘手。

答案 1 :(得分:8)

不要在设置包中保存用户密码。
这不安全。

请记住,您不需要知道原始密码是什么,您需要知道用户输入的密码是否匹配原始密码。在iOS中处理密码的正确方法是

  • 使用钥匙串,正如其他人提到的那样
  • 使用SHA-512或其他加密方式生成加密单向散列函数,并将生成的散列和盐存储在NSUserDefaults

在这些选项中,加密密码和存储hash + salt是目前最简单的选择。以下是您存储密码的方法:

  1. 从用户那里获取密码
  2. 创建随机盐值
  3. 使用SHA-512和随机盐值
  4. 创建仅向前哈希
  5. 将生成的哈希值和salt值存储在NSUserDefaults中 - 黑客无法使用这些值来确定原始密码,因此无需将它们存储在安全的位置。
  6. 现在,当用户输入密码并且你必须验证它是否正确时,这就是你要做的:

    1. 从用户那里获取密码
    2. NSUserDefaults
    3. 获取以前保存的哈希值+ salt值
    4. 使用您用于加密原始密码的相同单向散列函数创建仅向前散列 - 向其传递尝试的密码和来自NSUserDefaults
    5. 的salt值
    6. 将生成的哈希值与NSUSerDefaults中存储的哈希值进行比较。如果它们相同,则用户输入正确的密码。
    7. 以下是生成salt和仅向前哈希的代码:

      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/

答案 2 :(得分:3)

iPhone上的钥匙串将是最安全的,除非您使用自定义加密,这很难做到(并导出)。 NSUserDefaults不被视为安全。