从 NSString 创建 SHA1 哈希值

发布于 2024-12-06 12:00:59 字数 215 浏览 1 评论 0原文

如何从 NSString 创建 SHA1。

假设 NSString 设置为:

NSString *message = @"Message";

我可以使用 PHP 通过 sha($message) 创建 SHA1 哈希。但不幸的是,它在 Objective-C 中并不是这样工作的。

How can I create a SHA1 from a NSString.

Let's say the NSString is set up as:

NSString *message = @"Message";

I can use PHP to create a SHA1 hash with sha($message). But unfortunately it doesn't work like that within Objective-C.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

夏雨凉 2024-12-13 12:00:59

我在 NSString 上的一个类别中有这个(可在 https://github.com/hypercrypt/NSString-Hashes< /a>):

#import <CommonCrypto/CommonDigest.h>

...

- (NSString *)sha1
{
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];

    CC_SHA1(data.bytes, (CC_LONG)data.length, digest);

    NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];

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

    return output;
}

从 Xcode 10.0 开始,您应该使用 import CommonCrypto 来代替,因为它现在在 Swift 中原生可用!如果您最近迁移到 Xcode 10.0 并使用旧方法,这可能是您进行更改的提示:

命令 CompileSwift 失败,退出代码非零

I have this in a category on NSString (available at https://github.com/hypercrypt/NSString-Hashes):

#import <CommonCrypto/CommonDigest.h>

...

- (NSString *)sha1
{
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];

    CC_SHA1(data.bytes, (CC_LONG)data.length, digest);

    NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];

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

    return output;
}

Starting with Xcode 10.0, you should use import CommonCrypto instead since it is now natively available in Swift! If you have recently migrated to Xcode 10.0 and use the old approach, this can be your cue to make the change:

Command CompileSwift failed with a nonzero exit code

云雾 2024-12-13 12:00:59

我非常喜欢 hypercrypt 的答案,但我被鼓励发表评论。

您可以查看 CC_SHA1,或这个相关的SO问题。

I quite like hypercrypt's answer, but I've been encouraged to post my comment.

You could look at CC_SHA1, or this related SO question.

魔法少女 2024-12-13 12:00:59
- (NSString *)sha1:(NSString *)str {
const char *cStr = [str UTF8String];
unsigned char result[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(cStr, strlen(cStr), result);
NSString *s = [NSString  stringWithFormat:
           @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
           result[0], result[1], result[2], result[3], result[4],
           result[5], result[6], result[7],
           result[8], result[9], result[10], result[11], result[12],
           result[13], result[14], result[15],
           result[16], result[17], result[18], result[19]
           ];

return s;
}
- (NSString *)sha1:(NSString *)str {
const char *cStr = [str UTF8String];
unsigned char result[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(cStr, strlen(cStr), result);
NSString *s = [NSString  stringWithFormat:
           @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
           result[0], result[1], result[2], result[3], result[4],
           result[5], result[6], result[7],
           result[8], result[9], result[10], result[11], result[12],
           result[13], result[14], result[15],
           result[16], result[17], result[18], result[19]
           ];

return s;
}
稀香 2024-12-13 12:00:59

我花了一段时间才将 @hypercrypt 解决方案移植到 Swift,所以我决定与可能有相同问题的其他人分享。

需要注意的一件重要事情是,您需要 CommonCrypto 库,但该库没有 Swift 模块。最简单的解决方法是将其导入到桥接标头中:

#import <CommonCrypto/CommonCrypto.h>

导入后,您不需要任何其他内容。只需使用提供的字符串扩展:

extension String
{
    func sha1() -> String
    {
        var selfAsSha1 = ""

        if let data = self.dataUsingEncoding(NSUTF8StringEncoding)
        {
            var digest = [UInt8](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
            CC_SHA1(data.bytes, CC_LONG(data.length), &digest)

            for index in 0..<CC_SHA1_DIGEST_LENGTH
            {
                selfAsSha1 += String(format: "%02x", digest[Int(index)])
            }
        }

        return selfAsSha1
    }
}

请注意,我的解决方案不会影响原始帖子中 NSMutableString 的保留容量。不过我怀疑有人会看到其中的区别:)

It took me a while to port @hypercrypt solution to Swift so I decided to share it with others that might have the same problem.

One important thing to note is that you need CommonCrypto library, but that library does not have Swift module. The easiest workaround is to import it in your bridging header:

#import <CommonCrypto/CommonCrypto.h>

Once imported there, you do not need anything else. Just use String extension provided:

extension String
{
    func sha1() -> String
    {
        var selfAsSha1 = ""

        if let data = self.dataUsingEncoding(NSUTF8StringEncoding)
        {
            var digest = [UInt8](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0)
            CC_SHA1(data.bytes, CC_LONG(data.length), &digest)

            for index in 0..<CC_SHA1_DIGEST_LENGTH
            {
                selfAsSha1 += String(format: "%02x", digest[Int(index)])
            }
        }

        return selfAsSha1
    }
}

Notice that my solution does not take effect of reserving capacity what NSMutableString has in original post. However I doubt anyone will see the difference :)

油焖大侠 2024-12-13 12:00:59

试试这个:

#import <CommonCrypto/CommonDigest.h>

-(NSData *) selector
{
    unsigned char hashBytes[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1([dataToHash bytes], [dataToHash length], hashBytes);
    NSData *data = [[NSData alloc] initWithBytes:hashBytes length:CC_SHA1_DIGEST_LENGTH];
}

try this:

#import <CommonCrypto/CommonDigest.h>

-(NSData *) selector
{
    unsigned char hashBytes[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1([dataToHash bytes], [dataToHash length], hashBytes);
    NSData *data = [[NSData alloc] initWithBytes:hashBytes length:CC_SHA1_DIGEST_LENGTH];
}
对风讲故事 2024-12-13 12:00:59

我看到这篇文章中的答案有一些不同的可能的改进。

  1. 切勿创建无前缀的类别。如果您在库中实现 -[NSString sha1Hash],而同一应用程序中的另一个库实现了相同的方法,但语义略有不同,该怎么办?使用哪一个将是随机的,并导致难以诊断的错误。
  2. 如果你想要一个字符串,现在标准库中有base64编码。比手动构建十六进制字符串化的工作量更少。

这是我的解决方案, 改编自优秀的 SocketRocket 库的 SRHash。米:

// NSString+Sha1Digest.h
#import <Foundation/Foundation.h>

@interface NSString (LBDigest)
- (NSString *)lb_digestString;
@end

@interface NSData (LBDigest)
- (NSString *)lb_digestString;
@end

// NSString+SHA1Digest.m
#import "NSString+Sha1Digest.h"
#import <CommonCrypto/CommonDigest.h>

static NSData *LBSHA1HashFromBytes(const char *bytes, size_t length)
{
    uint8_t outputLength = CC_SHA1_DIGEST_LENGTH;
    unsigned char output[outputLength];
    CC_SHA1(bytes, (CC_LONG)length, output);

    return [NSData dataWithBytes:output length:outputLength];
}

static NSData *LBSHA1HashFromString(NSString *string)
{
    size_t length = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    return LBSHA1HashFromBytes(string.UTF8String, length);
}

@implementation NSData (LBDigest)
- (NSString *)lb_digestString;
{
    return [LBSHA1HashFromBytes(self.bytes, self.length) base64EncodedStringWithOptions:0];
}
@end

@implementation NSString (LBDigest)
- (NSString *)lb_digestString;
{
    return [LBSHA1HashFromString(self) base64EncodedStringWithOptions:0];
}
@end

I'm seeing a few different possible improvements to the answers in this post.

  1. Never make an unprefixed category. What if you implement -[NSString sha1Hash] in your library, and another library in the same app implements the same method with slightly different semantics? Which one is used will be random, and lead to hard-to-diagnose errors.
  2. If you want a string, there is base64-encoding in the standard library nowadays. Less work than manually building hex stringification.

Here's my solution, adapted from the excellent SocketRocket library's SRHash.m:

// NSString+Sha1Digest.h
#import <Foundation/Foundation.h>

@interface NSString (LBDigest)
- (NSString *)lb_digestString;
@end

@interface NSData (LBDigest)
- (NSString *)lb_digestString;
@end

// NSString+SHA1Digest.m
#import "NSString+Sha1Digest.h"
#import <CommonCrypto/CommonDigest.h>

static NSData *LBSHA1HashFromBytes(const char *bytes, size_t length)
{
    uint8_t outputLength = CC_SHA1_DIGEST_LENGTH;
    unsigned char output[outputLength];
    CC_SHA1(bytes, (CC_LONG)length, output);

    return [NSData dataWithBytes:output length:outputLength];
}

static NSData *LBSHA1HashFromString(NSString *string)
{
    size_t length = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    return LBSHA1HashFromBytes(string.UTF8String, length);
}

@implementation NSData (LBDigest)
- (NSString *)lb_digestString;
{
    return [LBSHA1HashFromBytes(self.bytes, self.length) base64EncodedStringWithOptions:0];
}
@end

@implementation NSString (LBDigest)
- (NSString *)lb_digestString;
{
    return [LBSHA1HashFromString(self) base64EncodedStringWithOptions:0];
}
@end
春花秋月 2024-12-13 12:00:59

这是一个简洁且高度优化的 NSString类别

@implementation NSString (PMUtils)
- (NSString *)sha1Hash
{
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
    NSData *hash = [data sha1Hash];
    return [hash hexString];
} 
@end

@implementation NSData (PMUtils)
- (NSString *) hexString
{
    NSUInteger bytesCount = self.length;
    if (bytesCount) {
        static char const *kHexChars = "0123456789ABCDEF";
        const unsigned char *dataBuffer = self.bytes;
        char *chars = malloc(sizeof(char) * (bytesCount * 2 + 1));
        char *s = chars;
        for (unsigned i = 0; i < bytesCount; ++i) {
            *s++ = kHexChars[((*dataBuffer & 0xF0) >> 4)];
            *s++ = kHexChars[(*dataBuffer & 0x0F)];
            dataBuffer++;
        }
        *s = '\0';
        NSString *hexString = [NSString stringWithUTF8String:chars];
        free(chars);
        return hexString;
    }
    return @"";
}
- (NSData *)sha1Hash
{
    unsigned char digest[CC_SHA1_DIGEST_LENGTH];
    if (CC_SHA1(self.bytes, (CC_LONG)self.length, digest)) {
        return [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
    }
    return nil;
}
@end

Here's a concise and highly optimized NSString category:

@implementation NSString (PMUtils)
- (NSString *)sha1Hash
{
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
    NSData *hash = [data sha1Hash];
    return [hash hexString];
} 
@end

@implementation NSData (PMUtils)
- (NSString *) hexString
{
    NSUInteger bytesCount = self.length;
    if (bytesCount) {
        static char const *kHexChars = "0123456789ABCDEF";
        const unsigned char *dataBuffer = self.bytes;
        char *chars = malloc(sizeof(char) * (bytesCount * 2 + 1));
        char *s = chars;
        for (unsigned i = 0; i < bytesCount; ++i) {
            *s++ = kHexChars[((*dataBuffer & 0xF0) >> 4)];
            *s++ = kHexChars[(*dataBuffer & 0x0F)];
            dataBuffer++;
        }
        *s = '\0';
        NSString *hexString = [NSString stringWithUTF8String:chars];
        free(chars);
        return hexString;
    }
    return @"";
}
- (NSData *)sha1Hash
{
    unsigned char digest[CC_SHA1_DIGEST_LENGTH];
    if (CC_SHA1(self.bytes, (CC_LONG)self.length, digest)) {
        return [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
    }
    return nil;
}
@end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文