iOS常用加密算法介绍和代码实践
ios系统库中定义了软件开发中常用的加解密算法,接口为c语言形式。具体包括了以下几个大类:
#include <commoncrypto/commoncryptor.h> //常用加解密算法 #include <commoncrypto/commondigest.h> //摘要算法 #include <commoncrypto/commonhmac.h> #include <commoncrypto/commonkeyderivation.h> #include <commoncrypto/commonsymmetrickeywrap.h>
其中第一类常用加解密算法就包含了aes,des,和已经废弃的rc4,第二类摘要算法,包括如md5,sha等。本文主要介绍aes,md5,sha三种最常用算法的实现。
1 对称密码算法--aes
aes主要应用在关键数据和文件的的保密同时又需要解密的情形,其加密密钥和解密密钥相同,根据密钥长度分为128、192和256三种级别,密钥长度越大安全性也就越大,但性能也就越低,根据实际业务的安全要求来决定就好。通常情况,对一些关键数据进行加密的对象都是字符串,加密结果也以字符串进行保存,所以在设计接口的时候参数和返回值均为字符串。(关于关键参数的意义放在代码后讲解。)
1.1 加密过程
-(nsstring *)aes256_encrypt:(nsstring *)key { const char *cstr = [self cstringusingencoding:nsutf8stringencoding]; nsdata *data = [nsdata datawithbytes:cstr length:self.length]; //对数据进行加密 char keyptr[kcckeysizeaes256+1]; bzero(keyptr, sizeof(keyptr)); [key getcstring:keyptr maxlength:sizeof(keyptr) encoding:nsutf8stringencoding]; nsuinteger datalength = [data length]; size_t buffersize = datalength + kccblocksizeaes128; void *buffer = malloc(buffersize); size_t numbytesencrypted = 0; cccryptorstatus cryptstatus = cccrypt(kccencrypt, kccalgorithmaes, kccoptionpkcs7padding | kccoptionecbmode, keyptr, kcckeysizeaes256, null, [data bytes], datalength, buffer, buffersize, &numbytesencrypted); if (cryptstatus == kccsuccess) { nsdata *result = [nsdata datawithbytesnocopy:buffer length:numbytesencrypted]; //base64 return [result base64encodedstringwithoptions:nsdatabase64encoding64characterlinelength]; }else { return nil; } }
1.2 解密过程
-(nsstring *)aes256_decrypt:(nsstring *)key { nsdata *data = [[nsdata alloc] initwithbase64encodeddata:[self datausingencoding:nsasciistringencoding] options:nsdatabase64decodingignoreunknowncharacters]; //对数据进行解密 char keyptr[kcckeysizeaes256+1]; bzero(keyptr, sizeof(keyptr)); [key getcstring:keyptr maxlength:sizeof(keyptr) encoding:nsutf8stringencoding]; nsuinteger datalength = [data length]; size_t buffersize = datalength + kccblocksizeaes128; void *buffer = malloc(buffersize); size_t numbytesdecrypted = 0; cccryptorstatus cryptstatus = cccrypt(kccdecrypt, kccalgorithmaes, kccoptionpkcs7padding | kccoptionecbmode, keyptr, kcckeysizeaes256, null, [data bytes], datalength, buffer, buffersize, &numbytesdecrypted); if (cryptstatus == kccsuccess) { nsdata* result = [nsdata datawithbytesnocopy:buffer length:numbytesdecrypted]; return [[nsstring alloc] initwithdata:result encoding:nsutf8stringencoding]; }else { return nil; } }
1.3 接口调用示例
int main(int argc, const char * argv[]) { @autoreleasepool { nsstring *plaintext = @"o57w05xn-eq2hcd3v-lpjj4h0n-zfo2whrr-9havxr2j-ytyxdqpk-sjxzxali-faihjv"; nsstring *key = @"12345678901234561234567890123456"; nsstring *crypttext = [plaintext aes256_encrypt:key]; nslog(@"crypttext:\n%@",crypttext); nsstring *newplaintext = [crypttext aes256_decrypt:key]; nslog(@"newplaintext:%@",newplaintext); nsstring *newcryptext3 = @"u7cked8fscz6czs5eu7emxnm6/5awkzwbufk+d1jqdzim5junkgqnzi/vmiwfpvy5qd5vifh7qajzjdszxnkspg/b4if5bskdffp/3aysbw="; nsstring *newplaintext3 = [newcryptext3 aes256_decrypt:key]; nslog(@"newplaintext3:%@",newplaintext3); } return 0; }
1.4 关键参数的意义
要熟练掌握aes算法的使用,必须要了解其几种工作模式、初始化向量、填充模式等概念,通常情况还需要多平台保持一致的加解密结果,使用时务必多做确认。(可以使用在线网站加解密进行自我验证。)
kcckeysizeaes256
密钥长度,枚举类型,还有128,192两种。
kccblocksizeaes128
块长度,固定值 16(字节,128位),由aes算法内部加密细节决定,不过哪种方式、模式,均为此。
kccalgorithmaes
算法名称,不区分是128、192还是258。kccalgorithmaes128只是历史原因,与kccalgorithmaes值相同。
kccoptionpkcs7padding
填充模式,aes算法内部加密细节决定aes的明文必须为64位的整数倍,如果位数不足,则需要补齐。kccoptionpkcs7padding表示,缺几位就补几个几。比如缺少3位,则在明文后补3个3。ios种只有这一种补齐方式,其它平台方式更多,如kccoptionpkcs5padding,kccoptionzeropadding。如果要实现一致性,则此处其它平台也要使用kccoptionpkcs7padding。
kccoptionecbmode
工作模式,电子密码本模式。此模式不需要初始化向量。ios种只有两种方式,默认是cbc模式,即块加密模式。标准的aes除此外还有其它如ctr,cfb等方式。kccoptionecbmode模式下多平台的要求不高,推荐使用。cbc模式,要求提供相同的初始化向量,多个平台都要保持一致,工作量加大,安全性更高,适合更高要求的场景使用。
base64
一种unicode到asci码的映射,由于明文和密文标准加密前后都可能是汉字或者特殊字符,故为了直观的显示,通常会对明文和密文进行base64编码。
2 摘要算法
摘要算法,具有单向不可逆的基本性质,速度快。
2.1 消息摘要算法md5
md5算法将任意明文(不为空)映射位32位字符串。数字签名和复杂的加密系统中都有使用,单独使用由于撞库原因安全性较低。
- (nsstring *)md5hexdigest { const char *cstr = [self cstringusingencoding:nsutf8stringencoding]; unsigned char result[cc_md5_digest_length]; cc_md5(cstr, (unsigned int)strlen(cstr), result); nsmutablestring *output = [nsmutablestring stringwithcapacity:cc_md5_digest_length * 2]; for(int i = 0; i < cc_md5_digest_length; i++) [output appendformat:@"%02x", result[i]]; return output; }
这里将结果以16进制字符串形式保存,也可以进行base64等其它处理。
2.2 安全散列算法sha
sha按结果的位数分为256、484、512三种基本方式,根据对结果的要求而选择即可。通过cc_sha256_digest_length等枚举类型进行设置。
- (nsstring *)sha256hexdigest { const char *cstr = [self cstringusingencoding:nsutf8stringencoding]; nsdata *data = [nsdata datawithbytes:cstr length:self.length]; uint8_t digest[cc_sha256_digest_length]; cc_sha256(data.bytes, (unsigned int)data.length, digest); nsmutablestring* output = [nsmutablestring stringwithcapacity:cc_sha256_digest_length * 2]; for(int i = 0; i < cc_sha256_digest_length; i++) [output appendformat:@"%02x", digest[i]]; return output; }
3 未完待续,后期介绍rsa非对称密码的使用。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。