欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS常用加密算法介绍和代码实践

程序员文章站 2023-12-17 14:10:28
ios系统库中定义了软件开发中常用的加解密算法,接口为c语言形式。具体包括了以下几个大类:  #include

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非对称密码的使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: