Objective-C образец кода для HMAC-SHA1

Мне нужно создать HMAC-SHA1 в Objective C. Но я не нашел ничего, что работает. Я пробовал с CommonCrypto, используя CCHMAC, но не работал. Мне нужно сгенерировать hmac и после генерации числа HOTP.

У кого-нибудь есть код примера в Objective C или C?

Ответ 1

Здесь вы создаете HMAC, используя 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];

Я не знаю библиотеки HOTP, но алгоритм был довольно прост, если я правильно помню.

Ответ 2

вот как вы можете генерировать HMAC-SHA1 base64.

Вам нужно добавить Base64.h и Base64.m в свой проект. Вы можете получить его здесь.

Если вы используете ARC, он покажет некоторые ошибки в Base64.m. Найдите строки, похожие на это

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

вам нужно удалить раздел авторекламы. Конечный результат должен выглядеть так:

return [[self alloc] initWithBase64String:base64String];

Теперь в вашем общем проекте импортируйте "Base64.h" и следующий код

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

С

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

вы получите что-то похожее на это:

ghVEjPvxwLN1lBi0Jh46VpIchOc=

Ответ 3

Это полное решение, которое работает без дополнительных библиотек или хаков:

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

Вам не нужно включать стороннюю библиотеку base64, поскольку она уже закодирована.

Ответ 4

Это работает без использования пользовательских протоколов, используя некоторый код из 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

Использование:

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

Ответ 5

Я провожу целый день, пытаясь преобразовать сгенерированный хэш (байты) в читаемые данные. Я использовал базовое кодированное решение из вышеприведенного ответа, и он не работал вообще для меня (b.t.w. вам нужен и внешний .h, чтобы иметь возможность использовать кодировку base64, которая у меня была).

Итак, я сделал это (что отлично работает без внешнего .h):

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);

Ответ 6

Вот как вы делаете это без внешних файлов, возвращающих шестую строку:

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

Он был протестирован в xCode 5 с iOS 7 и отлично работает!

Ответ 7

Из интереса, почему вы создаете (unsigned char cHMAC), а затем конвертируете в (NSData), а затем конвертируете в (NSMutableString), а затем конвертируете, наконец, в (HexString)?

Вы могли бы сделать это быстрее, отрезав посредника (т.е. без NSData и NSMutableString в целом, более быструю и лучшую производительность), также меняя (unsigned char) на (uint8_t []), ведь все они шестых -arrays в любом случае!, ниже:

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

Я надеюсь, что это поможет,

Привет

Хайдер Сати