2009-08-30 6 views
5

Ho la seguente funzione di Objective-C:cercando di scrivere NSString funzione SHA1, ma è il ritorno nullo

+(NSString *)stringToSha1:(NSString *)str{ 
    NSMutableData *dataToHash = [[NSMutableData alloc] init]; 
    [dataToHash appendData:[str dataUsingEncoding:NSUTF8StringEncoding]]; 

    unsigned char hashBytes[CC_SHA1_DIGEST_LENGTH]; 
    CC_SHA1([dataToHash bytes], [dataToHash length], hashBytes); 
    NSData *encodedData = [NSData dataWithBytes:hashBytes length:CC_SHA1_DIGEST_LENGTH]; 
    [dataToHash release]; 
    NSString *encodedStr = [NSString stringWithUTF8String:[encodedData bytes]]; 
    //NSString *encodedStr = [[NSString alloc] initWithBytes:[encodedData bytes] 
    //           length:[encodedData length] encoding: NSUTF8StringEncoding]; 
    NSLog(@"String is %@", encodedStr); 

    return encodedStr; 

} 

Quello che sto cercando di fare è prendere un NSString e SHA1 codificarlo. Sembra che quella parte funzioni, penso che dove sto cadendo sia come convertire l'oggetto NSData in una stringa leggibile. Se uso la codifica UTF8 divento vuoto, se dico ASCII ottengo strani caratteri. Quello che voglio veramente è la stringa esadecimale, ma non ho idea di come ottenerlo. Questo è l'utilizzo dell'SDK dell'iPhone 3.0.

Al momento in cui una stringa I passa torna indietro NULL.

+0

Problema distinto: questo è meglio implementato come categoria su NSString piuttosto che un metodo di classe. Il metodo sarebbe - (NSString *) sha1String. Se si scopre di voler mantenere un metodo di classe, dovrebbe avere un nome come + (NSString *) sha1StringForString: (NSString *) stringa. La confusione tra una "sha1" (che è una rappresentazione binaria) e una sha1String è esattamente il motivo per cui hai avuto problemi in primo luogo. La corretta denominazione aiuterà a prevenire successive confusioni dello stesso tipo. –

risposta

3

Risposta breve: attiva gli avvisi di gcc (-Wall).

Risposta lunga:

NSMutableData *dataToHash = [[NSMutableData alloc] init]; 
[dataToHash appendData:[str dataUsingEncoding:NSUTF8StringEncoding]]; 

è rotto: Si tenta di utilizzare una stringa C dove ci si aspetta un argomento NSData. Utilizzare

NSMutableData *dataToHash = [str dataUsingEncoding:NSUTF8StringEncoding]; 

invece.

Il resto del metodo accetta il buffer SHA1 e tenta di interpretare questi dati come una stringa UTF-8 C, che potrebbe causare arresti anomali o risultati imprevisti. Innanzitutto, il buffer non è una stringa UTF-8. In secondo luogo, non è terminato con null.

Quello che vuoi è convertire lo SHA1 in una base 64 o una stringa simile. Here's a nice post su come farlo.

+0

grazie, sono nuovo della maggior parte di questo business C, ma sembra abbastanza facile da seguire – rustyshelf

1

Questo è quello che ho finito con, il passo successivo sarebbe quello di convertirlo in essere una categoria di NSString invece di un metodo statico in una classe di supporto:

+(NSString *)stringToSha1:(NSString *)str{ 
    const char *s = [str cStringUsingEncoding:NSASCIIStringEncoding]; 
    NSData *keyData = [NSData dataWithBytes:s length:strlen(s)]; 

    // This is the destination 
    uint8_t digest[CC_SHA1_DIGEST_LENGTH] = {0}; 
    // This one function does an unkeyed SHA1 hash of your hash data 
    CC_SHA1(keyData.bytes, keyData.length, digest); 

    // Now convert to NSData structure to make it usable again 
    NSData *out = [NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]; 
    // description converts to hex but puts <> around it and spaces every 4 bytes 
    NSString *hash = [out description]; 
    hash = [hash stringByReplacingOccurrencesOfString:@" " withString:@""]; 
    hash = [hash stringByReplacingOccurrencesOfString:@"<" withString:@""]; 
    hash = [hash stringByReplacingOccurrencesOfString:@">" withString:@""]; 

    NSLog(@"Hash is %@ for string %@", hash, str); 

    return hash; 
} 
+1

Questo può creare solo hash per stringhe ASCII pure. –

+0

Grazie per il suggerimento, ma questo è tutto ciò di cui ho bisogno. – rustyshelf

26

La mia versione della funzione SHA1 (più semplice):

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

e MD5:

- (NSString *)md5:(NSString *)str { 
const char *cStr = [str UTF8String]; 
unsigned char result[CC_MD5_DIGEST_LENGTH]; 
CC_MD5(cStr, strlen(cStr), result); 
NSString *s = [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] 
       ]; 

    return s; 
} 
+3

Non è necessario chiamare la stringa minuscola. Basta cambiare '02X' in '02x'. – Seunghoon

+0

perfetto! Grazie mille – virata

-1

glicole, potrete è necessario definire la costante CC_SHA1_DIGEST_LENGTH, probabilmente a 20, poiché è la lunghezza di un digest SHA-1 secondo la specifica NIST a http://www.itl.nist.gov/fipspubs/fip180-1.htm

+1

Definito in '' –