web-dev-qa-db-fra.com

Exemple de code Objective-C pour HMAC-SHA1

J'ai besoin de générer HMAC-SHA1 dans l'objectif C. Mais je n'ai rien trouvé qui fonctionne. J'ai essayé avec CommonCrypto, en utilisant CCHMAC, mais cela n'a pas fonctionné. J'ai besoin de générer un hmac et après générer un numéro HOTP.

Quelqu'un a un exemple de code en objectif C ou C?

62
Helena

Voici comment générer un HMAC à l'aide de SHA-256:

NSString *key;
NSString *data;

const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];

unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
                                      length:sizeof(cHMAC)];

NSString *hash = [HMAC base64Encoding];

Je ne connais pas de bibliothèque HOTP, mais l'algorithme était assez simple, si je me souviens bien.

72
Can Berk Güder

voici comment générer HMAC-SHA1 base64 .

Vous devez ajouter Base64.h et Base64.m à votre projet. Vous pouvez l'obtenir auprès de ici .

Si vous utilisez ARC, il affichera quelques erreurs dans Base64.m. Trouvez les lignes similaires comme celle-ci

return [[[self alloc] initWithBase64String:base64String] autorelease];

ce dont vous avez besoin est de supprimer la section de libération automatique. Le résultat final devrait ressembler à:

return [[self alloc] initWithBase64String:base64String];

Maintenant, dans votre projet général, importez "Base64.h" et le code suivant

#import "Base64.h"
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonHMAC.h>

- (NSString *)hmacsha1:(NSString *)data secret:(NSString *)key {

    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];

    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];

    NSString *hash = [HMAC base64String];

    return hash;
}

Avec

NSLog(@"Hash: %@", hash);  

vous obtiendrez quelque chose de similaire à ceci:

ghVEjPvxwLN1lBi0Jh46VpIchOc=

38
Zsivics Sanel

Ceci est la solution complète qui fonctionne sans aucune bibliothèque ou hacks supplémentaire:

+(NSString *)hmac:(NSString *)plainText withKey:(NSString *)key
{
    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [plainText cStringUsingEncoding:NSASCIIStringEncoding];

    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    NSData *HMACData = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];

    const unsigned char *buffer = (const unsigned char *)[HMACData bytes];
    NSString *HMAC = [NSMutableString stringWithCapacity:HMACData.length * 2];

    for (int i = 0; i < HMACData.length; ++i)
        HMAC = [HMAC stringByAppendingFormat:@"%02lx", (unsigned long)buffer[i]];

    return HMAC;
}

Vous n'avez pas à inclure de bibliothèque base64 tierce car elle est déjà encodée.

22
codeplasma

Cela fonctionne sans utiliser de protocoles personnalisés, en utilisant du code de http://cocoawithlove.com/2009/07/hashvalue-object-for-holding-md5-and.html

HashSHA256.h

#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>

@interface HashSHA256 : NSObject {


}

 - (NSString *) hashedValue :(NSString *) key andData: (NSString *) data ; 

@end

HashSHA256.m

#import "HashSHA256.h"

#import <CommonCrypto/CommonHMAC.h>


@implementation HashSHA256


- (NSString *) hashedValue :(NSString *) key andData: (NSString *) data {


    const char *cKey  = [key cStringUsingEncoding:NSUTF8StringEncoding];
    const char *cData = [data cStringUsingEncoding:NSUTF8StringEncoding];
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    NSString *hash;

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

    for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++)
        [output appendFormat:@"%02x", cHMAC[i]];
    hash = output;
    return hash;

}

@end

Usage:

- (NSString *) encodePassword: (NSString *) myPassword {
    HashSHA256 * hashSHA256 = [[HashSHA256 alloc] init];   
    NSString * result = [hashSHA256 hashedValue:mySecretSalt andData:myPassword];       
    return result;       
}
8
primulaveris

Voici comment le faire sans que les fichiers externes retournent une chaîne hexadécimale:

-(NSString *)hmac:(NSString *)plaintext withKey:(NSString *)key
{
    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [plaintext cStringUsingEncoding:NSASCIIStringEncoding];
    unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
    CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
    NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];
    const unsigned char *buffer = (const unsigned char *)[HMACData bytes];
    NSMutableString *HMAC = [NSMutableString stringWithCapacity:HMACData.length * 2];
    for (int i = 0; i < HMACData.length; ++i){
        [HMAC appendFormat:@"%02x", buffer[i]];
     }
   return HMAC;
}

Il a été testé dans xCode 5 avec iOS 7 et fonctionne très bien!

2
Neco

Je passe une journée entière à essayer de convertir le hachage généré (octets) en données lisibles. J'ai utilisé la solution encodée en base64 de la réponse ci-dessus et cela n'a pas fonctionné du tout pour moi (b.t.w. vous avez besoin et un .h externe pour pouvoir utiliser l'encodage base64, que j'avais).

Donc, ce que j'ai fait était ceci (qui fonctionne parfaitement sans un .h externe):

CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

// Now convert to NSData structure to make it usable again
NSData *out = [NSData dataWithBytes:cHMAC length:CC_SHA256_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:@""];
// hash is now a string with just the 40char hash value in it
NSLog(@"%@",hash);
2
bruno

Par intérêt, pourquoi créez-vous (caractère non signé cHMAC), puis convertissez-vous en (NSData), puis convertissez-le en (NSMutableString), puis convertissez-vous enfin en (HexString)?

Vous pouvez le faire plus rapidement en coupant l'intermédiaire (c'est-à-dire sans NSData et NSMutableString, des performances plus rapides et meilleures), en changeant également (caractère non signé) en (uint8_t []), après tout, ce sont tous des tableaux hexadécimaux de toute façon !, au dessous de:

-(NSString *)hmac:(NSString *)plaintext withKey:(NSString *)key
{
const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [plaintext cStringUsingEncoding:NSASCIIStringEncoding];

uint8_t cHMAC[CC_SHA1_DIGEST_LENGTH];

CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

NSString *Hash1 = @"";
for (int i=0; i< CC_SHA1_DIGEST_LENGTH; i++)
{
    Hash1 = [Hash1 stringByAppendingString:[NSString stringWithFormat:@"%02X", cHMAC[i]]];
}
return Hash1;
}

J'espère que ça aide,

Cordialement

Heider Sati

1
Heider Sati

Avez-vous vu les nouvelles classes MyCrypto de Jens Alfke?

Il en a exemple de code sur son blog .

0
Ford