在上一部分iOS 关于CommonCrypto框架 ②(CommonCryptor AES|DES|3DES|CAST|BlowFish)中介绍了AES|DES|3DES|CAST|BlowFish等对称加密算法相关的内容,接下来就是<CommonDigest.h>
以及<CommonHMAC.h>
文件了。
之前在概述中说过,<CommonDigest.h>
文件中包含了MD5,SHA1,SHA256等哈希摘要算法的接口,我们可以使用它去对数据进行哈希摘要,而<CommonHMAC.h>
文件中则是有关HMAC
的接口文档了。
简单的介绍一下 Hash 以 HMAC.
Hash
Hash
,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。
Hash算法
在信息安全方面的应用主要体现在以下的3个方面:
- 文件校验
- 数字签名
- 鉴权协议
HMAC介绍
HMAC运算
利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。”
HMAC
主要应用在身份验证中,它的使用方法是这样的:
- 客户端发出登录请求(假设是浏览器的GET请求)
- 服务器返回一个随机值,并在会话中记录这个随机值
- 客户端将该随机值作为密钥,用户密码进行hmac运算,然后提交给服务器.
- 服务器读取用户数据库中的用户密码和步骤2中发送的随机值做与客户端一样的hmac运算,然后与用户发送的结果比较,如果结果一致则验证用户合法。
Digest 代码部分
在CommonDigest
中苹果说明 有关 *Init()
, *Update()
,
*Final()
的函数已经被弃用了,我们可以直接使用类似于CC_MD2()
, CC_SHA1()
这样的函数进行摘要。
例如
- MD5
- (NSData *)md5Data
{
unsigned char hash[CC_MD5_DIGEST_LENGTH];
(void) CC_MD5( [self bytes], (CC_LONG)[self length], hash );
return ( [NSData dataWithBytes: hash length: CC_MD5_DIGEST_LENGTH] );
}
- (NSString *)md5String {
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(self.bytes, (CC_LONG)self.length, result);
NSMutableString *hash = [NSMutableString
stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[hash appendFormat:@"%02x", result[i]];
}
return hash;
}
- SHA1
- (NSData *)sha1Data
{
unsigned char hash[CC_SHA1_DIGEST_LENGTH];
(void) CC_SHA1( [self bytes], (CC_LONG)[self length], hash );
return ( [NSData dataWithBytes: hash length: CC_SHA1_DIGEST_LENGTH] );
}
- (NSString *)sha1String {
unsigned char result[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(self.bytes, (CC_LONG)self.length, result);
NSMutableString *hash = [NSMutableString
stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
[hash appendFormat:@"%02x", result[i]];
}
return hash;
}
我们可以发现像MD2,MD4,MD5,SHA1,SHA224,SHA256,SHA384,SHA512这些摘要算法都是三步就可以获取到摘要后的数据或者字符串。
- 声明一个相应摘要算法长度的无符号字节数组.
- 通过相应函数,例如CC_SHA1(),传入对应参数:需要摘要的字节数组,需要摘要的数据长度以及 传入获取结果的字节数组
3.转换为NSData或者NSString类型数据.
HMAC代码部分
接下来看CommonHMAC
文件,分为三个部分
- HMAC算法的枚举
enum {
kCCHmacAlgSHA1,
kCCHmacAlgMD5,
kCCHmacAlgSHA256,
kCCHmacAlgSHA384,
kCCHmacAlgSHA512,
kCCHmacAlgSHA224
};
typedef uint32_t CCHmacAlgorithm;
- CCHmacInit()、CCHmacUpdate()、CCHmacFinal()函数.
- CCHmac()函数.
其实我们实现普通的HMAC密匙消息认证,只需要CCHmacAlgorithm
和CCHmac()
函数就可以了,实现代码部分:
- (NSData *)hmacDataUsingAlg:(CCHmacAlgorithm)alg withKey:(id)key {
NSParameterAssert([key isKindOfClass: [NSData class]] || [key isKindOfClass: [NSString class]]);
size_t size;
switch (alg) {
case kCCHmacAlgMD5: size = CC_MD5_DIGEST_LENGTH; break;
case kCCHmacAlgSHA1: size = CC_SHA1_DIGEST_LENGTH; break;
case kCCHmacAlgSHA224: size = CC_SHA224_DIGEST_LENGTH; break;
case kCCHmacAlgSHA256: size = CC_SHA256_DIGEST_LENGTH; break;
case kCCHmacAlgSHA384: size = CC_SHA384_DIGEST_LENGTH; break;
case kCCHmacAlgSHA512: size = CC_SHA512_DIGEST_LENGTH; break;
default: return nil;
}
NSMutableData * keyData;
if ( [key isKindOfClass: [NSData class]] )
keyData = (NSMutableData *) [key mutableCopy];
else
keyData = [[key dataUsingEncoding: NSUTF8StringEncoding] mutableCopy];
unsigned char result[size];
CCHmac(alg, [keyData bytes], keyData.length, self.bytes, self.length, result);
return [NSData dataWithBytes:result length:size];
}
我们只需要通过传入算法参数就可以完成对应的密钥消息认证, 例如传入kCCHmacAlgMD5
就是HMAC+MD5
。
关于哈希摘要就说这么多了,全部代码可以从Github下载。