2009-08-30 10 views
5

J'ai la fonction Objective-C suivant:Essayer d'écrire NSString fonction SHA1, mais il est de retour nul

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

} 

Ce que je suis en train de faire est de prendre une NSString et SHA1 encoder. Cette partie semble fonctionner, je pense que je tombe sur comment convertir l'objet NSData en une chaîne lisible. Si j'utilise l'encodage UTF8, je deviens vide, si je dis ASCII, j'obtiens des caractères étranges. Ce que je veux vraiment c'est la chaîne hexagonale, mais je n'ai aucune idée de comment l'obtenir. Ceci utilise le SDK iPhone 3.0.

Au moment où la chaîne que je passe passe à NULL.

+0

Problème séparé: ceci est mieux implémenté en tant que catégorie sur NSString plutôt que comme méthode de classe. La méthode serait - (NSString *) sha1String. Si vous trouvez que vous voulez garder une méthode de classe, il devrait avoir un nom comme + (NSString *) sha1StringForString: (NSString *) chaîne. La confusion entre un "sha1" (qui est une représentation binaire), et un sha1String est exactement pourquoi vous avez eu des problèmes en premier lieu. Une dénomination appropriée aidera à prévenir toute confusion ultérieure du même type. –

Répondre

3

Réponse courte: activez les avertissements gcc (-Wall).

Réponse longue:

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

est cassé: Vous essayez d'utiliser une chaîne C où un argument NSData est prévu. Utilisez

NSMutableData *dataToHash = [str dataUsingEncoding:NSUTF8StringEncoding]; 

à la place.

Le reste de la méthode prend le tampon SHA1 et essaie d'interpréter ces données comme une chaîne UTF-8 C, qui peut se bloquer ou donner un résultat inattendu. Premièrement, le tampon n'est pas une chaîne UTF-8. Deuxièmement, ce n'est pas null terminé.

Ce que vous voulez est de convertir le SHA1 en base 64 ou une chaîne similaire. Here's a nice post sur la façon de le faire.

+0

merci, je suis nouveau à la plupart de cette entreprise C, mais il semble assez facile à suivre – rustyshelf

1

C'est ce que j'ai fini avec, l'étape suivante serait de le convertir en une catégorie de NSString au lieu d'une méthode statique dans une classe d'aide:

+(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

Cela ne peut que créer des hachages pour les chaînes ASCII pur. –

+0

Merci pour le conseil, mais c'est tout ce dont j'ai besoin. – rustyshelf

26

Ma version de la fonction SHA1 (simplier):

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

Et 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

Vous n'avez pas besoin d'appeler minusculeChaîne. Changez simplement '02X' en '02x'. – Seunghoon

+0

parfait! merci beaucoup – virata

-1

glycol, Vous allez besoin de définir votre constante CC_SHA1_DIGEST_LENGTH, probablement à 20, car c'est la longueur d'un condensé SHA-1 selon la spécification NIST à http://www.itl.nist.gov/fipspubs/fip180-1.htm

+1

Cela est défini dans '' –