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;
}
Я надеюсь, что это поможет,
Привет
Хайдер Сати
Ответ 8
Вы видели Jens Alfke новый MyCrypto классы?
У него есть пример кода в его блоге.