Creating SHA1 Hash from NSString

前端 未结 7 1205
梦毁少年i
梦毁少年i 2020-12-23 19:57

How can I create a SHA1 from a NSString.

Let\'s say the NSString is set up as:

NSString *message = @\"Message\";

I can

相关标签:
7条回答
  • 2020-12-23 20:16

    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
    
    0 讨论(0)
  • 2020-12-23 20:18

    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
    
    0 讨论(0)
  • 2020-12-23 20:23

    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.

    0 讨论(0)
  • 2020-12-23 20:27

    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];
    }
    
    0 讨论(0)
  • 2020-12-23 20:33

    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

    0 讨论(0)
  • 2020-12-23 20:38
    - (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;
    }
    
    0 讨论(0)
提交回复
热议问题