【问题标题】:Storing a passwords in NSString without being readable in memory将密码存储在 NSString 中而不在内存中读取
【发布时间】:2009-04-14 22:44:37
【问题描述】:

我需要将密码存储在NSString 对象中;但是,我想要一些方法来混淆它们,所以它们不能直接从内存中读取。

这是一个 Mac OS X (10.5) 应用程序,但也适用于 iPhone 的解决方案将不胜感激。

【问题讨论】:

  • 为什么你特别需要将它们存储在一个字符串中,为什么有人试图获取那个内存?

标签: iphone cocoa security nsstring passwords


【解决方案1】:

如果您使用钥匙串来存储密码,那么您可以处理不透明的钥匙串SecKeychainItemRefs,而不是传递字符串,只在需要的地方检索明文。这也是 Mac 用户期望他们的密码被处理的方式。不幸的是,不知道为什么你“需要将密码存储在 NSString 对象中”,我无法判断这是否真的是真的:-)

【讨论】:

    【解决方案2】:

    您不能在将它们放入 NSString 之前先对它们进行 md5 处理吗?然后当你去测试时,md5输入字符串并将其与存储的内容进行比较?

    【讨论】:

    • 是的。但是您将无法使用 md5 字符串进行身份验证或使用任何密码。
    • 它会阻止他们读取密码,但允许访问不同的哈希值。
    • 字符串确实需要随机访问,因此需要能够将它们转换回可用状态。
    【解决方案3】:

    在 iPhone 上,沙盒会阻止任何人访问您的密码。在桌面上它不是那么容易。

    您应该将密码存储为散列而不是明文。我相信这会在不影响功能的情况下为您提供所需的结果。您永远无法做的唯一想法是再次访问明文密码 - 如果您想分析它的强度或将其传递给另一个服务。但总的来说,哈希不会牺牲功能。

    以下代码在 rawPassword 中获取密码,并将其 SHA-1 哈希存储在 passwordHash 中。

    #import <CommonCrypto/CommonDigest.h>
    
    const char* utf8PasswordRepresentation = [rawPassword UTF8String];
    unsigned char * rawHash = malloc(CC_SHA1_DIGEST_LENGTH);
    
    CC_SHA1(utf8PasswordRepresentation, strlen(utf8PasswordRepresentation), rawHash);
    
    NSMutableString* passwordHash = [NSMutableString CC_SHA1_DIGEST_LENGTH*2];
    for (int i = 0 ; i< CC_SHA1_DIGEST_LENGTH; i++)
        [passwordHash appendFormat:@"%02x" , rawHash[i]];
    

    注意这里没有内存管理。

    查看维基百科条目以获取 explanation of password hashing。

    在 intertubes 周围有许多相同的代码版本。

    【讨论】:

    • 你错过了 stringWithCapacity: line 8
    【解决方案4】:

    我认为张贴者指的是在内存中混淆密码,所以你不能只从内存中读取 ivar 的内容。来自 google 的 GData 库有一些有用的代码,用于对存储为实例变量中的 NSMutableData 的密码进行异或运算。

    source for GDataServiceBase.m

    // XorPlainMutableData is a simple way to keep passwords held in heap objects
    // from being visible as plain-text
    static void XorPlainMutableData(NSMutableData *mutable) {
    
        // this helps avoid storing passwords on the heap in plaintext
        const unsigned char theXORValue = 0x95; // 0x95 = 0xb10010101
    
        unsigned char *dataPtr = [mutable mutableBytes];
        NSUInteger length = [mutable length];
    
        for (NSUInteger idx = 0; idx < length; idx++) {
            dataPtr[idx] ^= theXORValue;
        }
    }
    

    您可以使用 XOR 保存/恢复密码(请参阅同一文件中的 #password 和 #setUserCredentialsWithUsername:password: 方法)。 XOR 不是高科技加密,但足以阻止随意窥探。对于 GData 客户端,您可能在应用程序中有一个长期存在的服务/管理器对象,该对象保留对密码数据的引用,我认为这是一种合理的方法。

    【讨论】:

    • 谢谢布赖恩,最初这就是我所指的,但格雷厄姆李的回答确实更好地解决了我的问题。但这也很有用+1
    【解决方案5】:

    可以在此处找到一组非常有用的代码,用于在钥匙串中存储和检索密码:

    http://log.scifihifi.com/post/55837387/simple-iphone-keychain-code

    我用过,效果很好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-06
      • 2015-06-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多