我需要在 Objective C 中生成 HMAC-SHA1。但我没有找到任何可行的方法。我尝试了 CommonCrypto,使用 CCHMAC,但没有用。我需要生成一个 hmac 并在生成 HOTP 编号之后。
有人在Objective C或C中有任何示例代码吗?
我需要在 Objective C 中生成 HMAC-SHA1。但我没有找到任何可行的方法。我尝试了 CommonCrypto,使用 CCHMAC,但没有用。我需要生成一个 hmac 并在生成 HOTP 编号之后。
有人在Objective C或C中有任何示例代码吗?
以下是使用 SHA-256 生成 HMAC 的方法:
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 库,但如果我没记错的话,该算法非常简单。
这是生成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=
这是完整的解决方案,无需任何额外的库或 hack:
+(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 库,因为它已经编码。
这在不使用自定义协议的情况下工作,使用来自 http://cocoawithlove.com/2009/07/hashvalue-object-for-holding-md5-and.html的一些代码
哈希SHA256.h
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
@interface HashSHA256 : NSObject {
}
- (NSString *) hashedValue :(NSString *) key andData: (NSString *) data ;
@end
哈希SHA256.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;
}
这是在没有外部文件返回十六进制字符串的情况下执行此操作的方法:
-(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 中进行了测试并且工作正常!
我花了一整天,试图将生成的哈希(字节)转换为可读数据。我使用了上面答案中的base64编码解决方案,它对我来说根本不起作用(顺便说一句,你需要一个外部.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);
出于兴趣,为什么要创建(unsigned char cHMAC)然后转换为(NSData),然后将其转换为(NSMutableString),然后最终转换为(HexString)?
您可以通过切割中间人(即完全没有 NSData 和 NSMutableString,更快更好的性能)来更快地做到这一点,也可以将 (unsigned char) 更改为 (uint8_t []),毕竟它们都是十六进制数组!,以下:
-(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;
}
我希望这有帮助,
问候
海德·萨蒂