【问题标题】:Converting NSData bytes to NSString将 NSData 字节转换为 NSString
【发布时间】:2012-01-08 04:21:53
【问题描述】:

我正在尝试在 Objective-c (Mac OS) 中创建一个 16 字节和后来的 32 字节初始化向量。我拿了一些关于如何创建随机字节的代码并将其修改为 16 个字节,但我对此有一些困难。 NSData 转储十六进制,但 NSString 转储给出 nil,而 cstring NSLog 给出错误数量的字符(此处转储中未重现相同)。

这是我的终端输出:

2012-01-07 14:29:07.705 Test3Test[4633:80f] iv hex <48ea262d efd8f5f5 f8021126 fd74c9fd>
2012-01-07 14:29:07.710 Test3Test[4633:80f] IV string: (null)
2012-01-07 14:29:07.711 Test3Test[4633:80f] IV char string t^Q¶�^��^A

这里是主程序:

int main (int argc, const char * argv[])
{
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    //NSString *iv_string = [NSString stringWithCString:iv encoding:NSUTF8StringEncoding];
    testclass *obj = [testclass alloc];
    NSData *iv_data = [obj createRandomNSData];
    //[iv_string dataUsingEncoding:NSUTF8StringEncoding];
    NSLog(@"iv hex %@",iv_data);

    //NSString *iv_string = [[NSString alloc] initWithBytes:[iv_data bytes] length:16 encoding:NSUTF8StringE$
    NSString *iv_string = [[NSString alloc] initWithData:iv_data encoding:NSUTF8StringEncoding];
    NSLog(@"IV string: %@",iv_string);
    NSLog(@"IV char string %.*s",[iv_data bytes]);

    return 0;
]

(我在上面留下了一些我尝试过但也没有工作的注释代码)。

下面是我的随机数生成器,取自堆栈溢出示例:

@implementation testclass
-(NSData*)createRandomNSData
{
    int twentyMb           = 16;
    NSMutableData* theData = [NSMutableData dataWithCapacity:twentyMb];
    for( unsigned int i = 0 ; i < twentyMb/4 ; ++i )
    {
            u_int32_t randomBits = arc4random();
            [theData appendBytes:(void*)&randomBits length:4];
    }
    NSData *data = [NSData dataWithData:theData];
    [theData dealloc];
    return data;
}
@end

对于这里可能出现的问题,我真的一无所知。如果我有数据作为字节,它应该转换为字符串还是不一定?我在 stackoverflow 上查看了相关示例,但没有一个在这种情况下有效。

谢谢, 以利亚

【问题讨论】:

    标签: objective-c c cocoa encryption


    【解决方案1】:

    任意字节序列可能不是合法的 UTF8 编码。正如@Joachim Isaksson 指出的那样,很少有理由以这种方式转换为字符串。如果您需要将随机数据存储为字符串,则应使用 Base64 之类的编码方案,将NSData 序列化为 plist 或类似方法。您也不能简单地使用 cstring,因为 NULL 在随机字节序列内是合法的,但在 cstring 内是不合法的。

    您无需在 Mac 或 iOS 上构建自己的随机字节创建器。有一个名为SecRandomCopyBytes() 的内置函数。例如(来自Properly encrypting with AES with CommonCrypto):

    + (NSData *)randomDataOfLength:(size_t)length {
      NSMutableData *data = [NSMutableData dataWithLength:length];
    
      int result = SecRandomCopyBytes(kSecRandomDefault, 
                                      length,
                                      data.mutableBytes);
      NSAssert(result == 0, @"Unable to generate random bytes: %d",
               errno);
    
      return data;
    }
    

    【讨论】:

    • 谢谢。另外,如果我的 AES 密文总是有效的 UTF8 字符串,您是否知道?
    • AES 密文不能保证是有效的 UTF8 字符串。
    • 好的,所以我应该对密码和 IV 进行 base64 编码。然而,到目前为止,我一直能够将密文打印为 nsstring,而我从未能够转换这些随机字节 - 但我会保持安全并对其进行 b64 编码。我过去无法使用 int result = SecRandomCopyBytes(kSecRandomDefault, length, data.mutableBytes);编译器问我 kSecRandomDefault ,我感觉这个函数只是 iOS (和我的通用加密器版本有不同的头文件)
    • 如果您需要以 7 位安全方式(例如电子邮件)存储密码和 IV,您应该只对密码和 IV 进行 base64 编码。如果您可以将它们写入文件,则没有理由对它们进行编码。把它们写下来。 SecRandomCopyBytes() 是在 10.7 中添加的(我之前没有注意到)。如果你想向后移植它,源代码在 opensource.apple.com,我建议不要自己创建。
    【解决方案2】:

    当使用 UTF8 编码将 NSData 转换为 NSString 时,您不一定会得到相同数量的字节,因为并非所有二进制值都是有效的字符编码。我想说对二进制数据使用字符串是一个问题的根源。

    字符串有什么用? NSData 正是您想要用于存储二进制数据的数据类型。

    【讨论】:

    • 字符串的用途是将值存储在数据库中
    猜你喜欢
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-21
    • 2012-11-09
    • 2011-11-11
    相关资源
    最近更新 更多