objective-c xcode hash sha1

objective c - Creando SHA1 Hash desde NSString



objective-c xcode (8)

Aquí hay una categoría concisa y altamente optimizada de 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

¿Cómo puedo crear un SHA1 desde un NSString ?

Digamos que NSString está configurado como:

NSString *message = @"Message";

Puedo usar PHP para crear un hash SHA1 con sha($message) . Pero desafortunadamente no funciona así dentro de Objective-C.


Estoy viendo algunas posibles mejoras diferentes a las respuestas en esta publicación.

  1. Nunca haga una categoría no prefijada. ¿Qué sucede si implementa - [NSString sha1Hash] en su biblioteca, y otra biblioteca en la misma aplicación implementa el mismo método con semántica ligeramente diferente? El que se use será aleatorio y dará lugar a errores difíciles de diagnosticar.
  2. Si desea una cadena, actualmente hay una codificación base64 en la biblioteca estándar. Menos trabajo que construir manualmente una cadena hexagonal.

Aquí está mi solución, adaptada del excelente SRHash.m de la biblioteca SocketRocket :

// 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


Me gusta bastante la respuesta de hypercrypt, pero me han alentado a publicar mi comentario.

Podrías mirar CC_SHA1 , o this pregunta SO relacionada.


Me gusta tanto la respuesta de hypercrypt que la incluí en un pequeño repositorio de git. Mira la categoría NSString en Github.

También siéntase libre de agregarlo con cualquier otro buen Crypto NSString


Me tomó un tiempo adaptar la solución @hypercrypt a Swift, así que decidí compartirlo con otras personas que pudieran tener el mismo problema.

Una cosa importante a tener en cuenta es que necesita la biblioteca CommonCrypto, pero esa biblioteca no tiene el módulo Swift. La solución más fácil es importarlo en su encabezado de puente:

#import <CommonCrypto/CommonCrypto.h>

Una vez importado allí, no necesita nada más. Solo use la extensión de cadena proporcionada:

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 } }

Tenga en cuenta que mi solución no tiene efecto de reserva de capacidad que tiene NSMutableString en la publicación original. Sin embargo, dudo que alguien vea la diferencia :)


Tengo esto en una categoría en NSString (disponible en 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; }


prueba esto:

#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]; }


- (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; }