HMAC-SHA1的Objective-C示例代码

我需要在Objective C中生成HMAC-SHA1,但是我没有find任何可行的方法。 我尝试使用CCHMAC CommonCrypto,但没有工作。 我需要生成一个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库,但algorithm很简单,如果我记得正确。

这里是如何生成HMAC-SHA1 base64

您需要将Base64.h和Base64.m添加到您的项目。 你可以从这里得到它。

如果你使用ARC,它会在Base64.m中显示一些错误。 find像这样的相似的线条

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

你需要的是删除autorelease部分。 最终的结果应该是这样的:

 return [[self alloc] initWithBase64String:base64String]; 

现在在你的一般项目中input“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= 

这是完整的解决scheme,没有任何额外的库或黑客工作:

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

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

我花了一整天,试图将生成的散列(字节)转换为可读的数据。 我从上面的答案使用base64编码的解决scheme,并没有为我工作(顺便说一句,你需要一个外部.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); 

这是如何做到这一点,没有外部文件返回一个hexstring:

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

它在iOS 7的xCode 5中进行了testing,工作正常!

出于兴趣,为什么你创build(无符号字符cHMAC),然后转换成(NSData),然后将其转换为(NSMutableString),然后转换成(HexString)?

你可以通过切割中间人(即完全没有NSData和NSMutableString,更快和更好的性能),更快地将(unsigned char)转换为(uint8_t [])来完成这一切,毕竟它们都是hex数组!下面:

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

我希望这有帮助,

问候

Heider Sati

你见过Jens Alfke的新MyCrypto课程吗?

他的博客上有一些示例代码 。