【问题标题】:Casting NSString to unsigned char *将 NSString 转换为无符号字符 *
【发布时间】:2009-02-19 13:24:12
【问题描述】:

我正在尝试使用具有以下签名的函数来签署 HTTP 请求:

extern void hmac_sha1(const unsigned char *inText, int inTextLength, unsigned char* inKey, const unsigned int inKeyLength, unsigned char *outDigest);

这是我写的使用它的方法:

- (NSString *)sign: (NSString *)stringToSign {
    NSString *secretKey = @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    const unsigned char *inText = (unsigned char *)[stringToSign UTF8String];
    int inTextLength = [stringToSign length];
    unsigned char *inKey = (unsigned char *)[secretKey UTF8String];
    const unsigned int inKeyLength = (unsigned int)[secretKey length];
    unsigned char *outDigest;

    hmac_sha1(inText, inTextLength, inKey, inKeyLength, outDigest);
    NSString *output = [NSString stringWithUTF8String:(const char *)outDigest];

    return output;
}

问题是我确定这不是我应该进行这种转换的方式,因为在这个 hmac_sha1 函数中我得到了一个 EXC_BAD_ACCESS 异常。

由于我是 Objective-C 的新手并且几乎没有 C 方面的经验(惊讶!)我真的不知道要搜索什么。关于如何开始解决此问题的任何提示?

提前致谢!

顺便说一句,我得到了这个函数的参考here in stackoverflow

【问题讨论】:

    标签: objective-c iphone


    【解决方案1】:

    看起来问题不在于演员阵容,而在于outDigesthmac_sha1 的第五个参数应该指向一个已经分配的大小为 20 字节的缓冲区(我认为)。

    如果你改变那一行

    unsigned char *outDigest;
    

    #define HMACSHA1_DIGEST_SIZE 20
    void *outDigest = malloc(HMACSHA1_DIGEST_SIZE);
    

    这应该可以帮助您度过 hmac_sha1 内部的崩溃。

    那么你遇到了将outDigest 的数据转换为NSString 的问题。看起来hmac_sha1 会将 20 个字节的随机数据放在outDigest,而不是一个空终止的 UTF-8 字符串,所以stringWithUTF8String: 将不起作用。如果您必须返回 NSString,您可能想要使用类似的东西:

    NSString *output = [[NSString alloc] initWithBytesNoCopy:outDigest
                                         length:HMACSHA1_DIGEST_SIZE
                                         encoding:NSASCIIStringEncoding
                                         freeWhenDone:YES];
    

    我不认为 NSString 真的是摘要的正确类型,因此如果可以的话,可能值得更改您的方法以返回 NSData

    【讨论】:

    • 解决了。我仍然要对它进行 Base64 编码,所以我可以用作 HTTP GET 参数,所以我必须将它保存在 NSString 中。谢谢!
    【解决方案2】:

    这不是您的问题的一部分,但它仍然是一个错误,您不应该使用 -length 来获取 UTF8 字符串的字节数。该方法返回字符串中的 Unicode 字符数,而不是字节数。你要的是-lengthOfBytesUsingEncoding:

    NSUInteger byteCount = [stringToSign lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    

    还要注意,结果不考虑终止 NULL 字符。

    【讨论】:

    • 不知道为什么这被否决但这是上面代码的合法问题。特别是如果 stringToSign 包含任何多字节 UTF8 字符。在这种情况下,length 返回的值将与 UTF8String 返回的字节数不匹配。
    【解决方案3】:

    您确定在调用hmac_sha1 之前不需要为outDigest 分配一些内存吗?由于您传入的是指针,而不是指向指针的指针,因此无法在例程内部分配内存。

    【讨论】:

    • 我相信你是对的。查看koders.com/c/fid716FD533B2D3ED4F230292A6F9617821C8FDD3D4.aspx 中的代码,它似乎预计 outDigest 的长度为 20 个字节。
    • 我该怎么做?我试过 unsigned char *outDigest = (unsigned char *)malloc(64*sizeof(char));和 unsigned char outDigest[20];但我无法将结果转换为实际的 NSString。 (但至少异常消失了!)
    • 在不确切知道 hmac_sha1 返回什么的情况下很难确定,但 Will Harris 可能会有所作为。
    • 是的。就是这样。现在我要对它进行 base64 编码。 :) 谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多