使用SHA512像C#一样对密码字符串进行哈希处理。

22

我正在为我的iPhone应用程序开发登录功能,因此我想使用SHA512哈希算法对密码进行哈希,然后将结果作为NSString返回(结果应与C#中的SHA512相同)。在互联网上花费了很多时间,但仍然没有找到解决方案! :(

有人有解决方案和示例代码吗?请帮帮我! 非常感谢!

[更新] 在我的C#代码中,密码是使用SecureString存储的,因此这可能导致Objective-C和C#之间的字节数组不同。

2个回答

32

该函数将使用SHA512哈希算法对字符串进行哈希处理。生成的字符串是哈希值的十六进制表示:

+ (NSString *) createSHA512:(NSString *)source {

    const char *s = [source cStringUsingEncoding:NSASCIIStringEncoding];

    NSData *keyData = [NSData dataWithBytes:s length:strlen(s)];

    uint8_t digest[CC_SHA512_DIGEST_LENGTH] = {0};

    CC_SHA512(keyData.bytes, keyData.length, digest);

    NSData *out = [NSData dataWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];

    return [out description];
}

别忘了加入正确的头文件:

#include <CommonCrypto/CommonDigest.h>

亲爱的Philippe,我有一个问题,就是在比较C#和Objective-C之间的哈希密码时出现了不同。在我的C#代码中,我使用SecureString来存储密码,所以我必须使用Marshal Copy来获取字节数组,并且我发现每个密码字符后面都附加了0字节,也许这就是导致哈希密码不同的原因。我不知道该如何解决它,你能再次帮助我吗?谢谢! - Son Nguyen
每个字符后面我也得到了一个额外的0字节...这个有解决办法吗? - BoldAsLove
没关系,我一直以为我的字节数组转十六进制字符串的转换在Java端是正确的......但实际上不是我写的代码,我需要吸取教训,永远不要做出假设。我的Java端十六进制转换有误,每个字符后面都漏掉了一个额外的0。感谢@Leybaert提供可用的代码。 - BoldAsLove
你的回答只使用了“描述”,这并不像它应该的那样好。描述只是一个包含对象内容十六进制表示形式的字符串,以属性列表格式进行格式化,而不是纯字符串。 - Wingzero

18

我正在使用这个。

它与 PHP SHA512 算法的输出匹配:

<?php `hash('sha512', 'The quick brown fox jumped over the lazy dog.');` ?>


Objective-C 代码:

+(NSString *)createSHA512:(NSString *)string
{
    const char *cstr = [string cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:string.length];
    uint8_t digest[CC_SHA512_DIGEST_LENGTH];
    CC_SHA512(data.bytes, data.length, digest);
    NSMutableString* output = [NSMutableString  stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];

    for(int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++)
        [output appendFormat:@"%02x", digest[i]];
    return output;
}

1
+1 这对我来说更有效。答案的输出对于 PHP 比较是不可取的:<9870d986 f510384d 932cdff5 13fb1886 0eee6d6f 1e90e794 bd25b980 bd0a48d1 d5fdd937 f454408f e93f5a61 e8724993 0e153424 41a24f9f 3059a9ea 3e029f2a> 而这个答案的输出类似于:9870d986f510384d932cdff513fb18860eee6d6f1e90e794bd25b980bd0a48d1d5fdd937f454408fe93f5a61e87249930e15342441a24f9f3059a9ea3e029f2a。 - capikaw
2
为什么在输出中必须乘以2:CC_SHA512_DIGEST_LENGTH * 2? - J.Williams
1
@SisterRay 顾名思义,它是512位,即64字节。 但这是哈希值,也许你想知道的是哈希值在字符串中的特定表示方式,通常情况下,这取决于给定的表示方式。 如果你用十六进制写哈希值,那么它将有128个字符。 如果你用Base64编码写哈希值,那么它将有86字节(或者带填充的话为88字节)。 - Wingzero
我从https://dev59.com/mGMl5IYBdhLWcg3wp4Wk借来的。 - Wingzero

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接