Algoritmo MD5 en Objective-C

Respuestas:

219

md5 está disponible en el iPhone y se puede agregar como una adición para ie NSStringy NSDatacomo a continuación.

MyAdditions.h

@interface NSString (MyAdditions)
- (NSString *)md5;
@end

@interface NSData (MyAdditions)
- (NSString*)md5;
@end

MyAdditions.m

#import "MyAdditions.h"
#import <CommonCrypto/CommonDigest.h> // Need to import for CC_MD5 access

@implementation NSString (MyAdditions)
- (NSString *)md5
{
    const char *cStr = [self UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5( cStr, (int)strlen(cStr), result ); // This is the md5 call
    return [NSString stringWithFormat:
        @"%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]
        ];  
}
@end

@implementation NSData (MyAdditions)
- (NSString*)md5
{
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5( self.bytes, (int)self.length, result ); // This is the md5 call
    return [NSString stringWithFormat:
        @"%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]
        ];  
}
@end

EDITAR

Agregué NSData md5 porque lo necesitaba yo mismo y pensé que este es un buen lugar para guardar este pequeño fragmento ...

Estos métodos se verifican utilizando los vectores de prueba NIST MD5 en http://www.nsrl.nist.gov/testdata/

epatel
fuente
¿Esto tira todo el archivo a la memoria?
openfrog
Esto no se trata de archivos. Si desea crear un MD5 a partir de un archivo con estos métodos, puede hacer NSData * fileContents = [NSData dataWithContentsOfFile: @ "<yourPath>"]; NSString * myHash = [fileContents md5]; Y sí, esto llevaría todo el archivo a la memoria. Si encuentra una solución que funcione con secuencias de archivos, publíquela como respuesta.
Klaas
1
Si necesita un archivo hash, debe usar CC_MD5_Init, luego CC_MD5_Update para todos los datos del archivo y luego CC_MD5_Finish.
Nickolay Olshevsky
77
Compilando para una arquitectura de 64 bits, la llamada strlenproduce la advertencia: "La conversión implícita pierde precisión entera: 'unsigned long' a 'CC_LONG' (también conocido como 'unsigned int')"
MaxGabriel
55

Puede usar la biblioteca de cifrado común incorporada para hacerlo. Recuerde importar:

#import <CommonCrypto/CommonDigest.h>

y entonces:

- (NSString *) md5:(NSString *) input
{
    const char *cStr = [input UTF8String];
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call

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

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

    return  output;
}
Bruno Koga
fuente
Implementé el código anterior, pero al ejecutar la aplicación se bloquea (CC_MD5 (cStr, strlen (cStr), digest) ----> esta línea arroja una excepción que dice EXC_BAD_ACCESS)
Nilesh Kumar
@wimcNilesh comprueba selfantes de ejecutar; si self es nulo, se estrellará.
brandonscript
44
Esta respuesta es mucho más limpia de leer que las otras; una cosa que necesita es un elenco (int)antes, strlenpor ejemplo (int)strlen...
brandonscript
Hay Este es un buen voto a favor +1, y ¿puede proporcionar también el método de descifrado md5 igual que el cifrado de su?
Ayaz
@Ayaz MD5 no se puede descifrar (al menos simplemente con un método).
albanx
9

Si el rendimiento es importante, puede usar esta versión optimizada. Es aproximadamente 5 veces más rápido que los que tienen stringWithFormato NSMutableString.

Esta es una categoría de NSString.

- (NSString *)md5
{
    const char* cStr = [self UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, strlen(cStr), result);

    static const char HexEncodeChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    char *resultData = malloc(CC_MD5_DIGEST_LENGTH * 2 + 1);

    for (uint index = 0; index < CC_MD5_DIGEST_LENGTH; index++) {
        resultData[index * 2] = HexEncodeChars[(result[index] >> 4)];
        resultData[index * 2 + 1] = HexEncodeChars[(result[index] % 0x10)];
    }
    resultData[CC_MD5_DIGEST_LENGTH * 2] = 0;

    NSString *resultString = [NSString stringWithCString:resultData encoding:NSASCIIStringEncoding];
    free(resultData);

    return resultString;
}
Pavel Alexeev
fuente
0

Bueno, ya que la gente pidió una versión de flujo de archivos. He modificado un pequeño fragmento hecho por Joel Lopes Da Silva que funciona con MD5, SHA1 y SHA512 Y está usando transmisiones. Está hecho para iOS pero también funciona con cambios mínimos en OSX (elimine el método ALAssetRepresentation). Puede hacer sumas de verificación para archivos dados una ruta de archivo o ALAssets (usando ALAssetRepresentation). Está agrupando datos en paquetes pequeños, lo que hace que el impacto en la memoria sea mínimo, independientemente del tamaño del archivo / tamaño del activo.

Actualmente se encuentra en github aquí: https://github.com/leetal/FileHash

Alexander W
fuente
El código que publicó Joel tiene una condición de carrera, y parece que el tuyo puede heredarlo. Vea el comentario que publiqué en la publicación de Joel. joel.lopes-da-silva.com/2010/09/07/…
xyzzycoder
¡Gracias! Parcheado ahora. Esto nunca fue un problema para mí ya que en la implementación original, siempre lo ejecutaba en un hilo dedicado;)
Alexander W
0

Cualquier razón para no usar la implementación de Apple: https://developer.apple.com/library/mac/documentation/Security/Conceptual/cryptoservices/GeneralPurposeCrypto/GeneralPurposeCrypto.html#//apple_ref/doc/uid/TP40011172-CH9-SW1

Busque la Guía de servicios criptográficos en el sitio para desarrolladores de Apple.

vpathak
fuente
El enlace cubre Common Crypto que utilizan la mayoría de las respuestas aquí.
zaph
1
Claro que el algo es igual. Pero tenga en cuenta que la implementación de su propio algoritmo criptográfico puede presentar fallas. Se necesita mucho endurecimiento para que sea correcto en todos los escenarios. Por lo tanto, es preferible usar la versión de la biblioteca, en el caso común.
vpathak