用户登录
用户注册

分享至

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

  • 作者: 爱上你是我的错134
  • 来源: 51数据库
  • 2021-10-25

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

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

软件
前端设计
程序设计
Java相关