zoukankan      html  css  js  c++  java
  • iOS常用加密算法介绍和代码实践

     

     

      iOS系统库中定义了软件开发中常用的加解密算法,接口为C语言形式。具体包括了以下几个大类:

    1 #include <CommonCrypto/CommonCryptor.h>  //常用加解密算法
    2 #include <CommonCrypto/CommonDigest.h>  //摘要算法
    3 #include <CommonCrypto/CommonHMAC.h>
    4 #include <CommonCrypto/CommonKeyDerivation.h>
    5 #include <CommonCrypto/CommonSymmetricKeywrap.h>

      其中第一类常用加解密算法就包含了AES,DES,和已经废弃的RC4,第二类摘要算法,包括如MD5,SHA等。本文主要介绍AES,MD5,SHA三种最常用算法的实现。

      1 对称密码算法--AES

      AES主要应用在关键数据和文件的的保密同时又需要解密的情形,其加密密钥和解密密钥相同,根据密钥长度分为128、192和256三种级别,密钥长度越大安全性也就越大,但性能也就越低,根据实际业务的安全要求来决定就好。通常情况,对一些关键数据进行加密的对象都是字符串,加密结果也以字符串进行保存,所以在设计接口的时候参数和返回值均为字符串。(关于关键参数的意义放在代码后讲解。)

      1.1 加密过程

    复制代码
     1 -(NSString *)aes256_encrypt:(NSString *)key
     2 {
     3     const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
     4     NSData *data = [NSData dataWithBytes:cstr length:self.length];
     5     
     6     //对数据进行加密
     7     char keyPtr[kCCKeySizeAES256+1];
     8     bzero(keyPtr, sizeof(keyPtr));
     9     [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
    10     NSUInteger dataLength = [data length];
    11     size_t bufferSize = dataLength + kCCBlockSizeAES128;
    12     void *buffer = malloc(bufferSize);
    13     size_t numBytesEncrypted = 0;
    14     CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES,
    15                                           kCCOptionPKCS7Padding | kCCOptionECBMode,
    16                                           keyPtr, kCCKeySizeAES256,
    17                                           NULL,
    18                                           [data bytes], dataLength,
    19                                           buffer, bufferSize,
    20                                           &numBytesEncrypted);
    21     if (cryptStatus == kCCSuccess)
    22     {
    23         NSData *result = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    24         //base64
    25         return [result base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    26     }else
    27     {
    28         return nil;
    29     }
    30     
    31 }
    复制代码

      1.2 解密过程

    复制代码
     1 -(NSString *)aes256_decrypt:(NSString *)key
     2 {
     3     NSData *data = [[NSData alloc] initWithBase64EncodedData:[self dataUsingEncoding:NSASCIIStringEncoding] options:NSDataBase64DecodingIgnoreUnknownCharacters];
     4     
     5     //对数据进行解密
     6     char keyPtr[kCCKeySizeAES256+1];
     7     bzero(keyPtr, sizeof(keyPtr));
     8     [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
     9     NSUInteger dataLength = [data length];
    10     size_t bufferSize = dataLength + kCCBlockSizeAES128;
    11     void *buffer = malloc(bufferSize);
    12     size_t numBytesDecrypted = 0;
    13     CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES,
    14                                           kCCOptionPKCS7Padding | kCCOptionECBMode,
    15                                           keyPtr, kCCKeySizeAES256,
    16                                           NULL,
    17                                           [data bytes], dataLength,
    18                                           buffer, bufferSize,
    19                                           &numBytesDecrypted);
    20     if (cryptStatus == kCCSuccess)
    21     {
    22         NSData* result = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    23         
    24         return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
    25         
    26     }else
    27     {
    28         return nil;
    29     }
    30     
    31 }
    复制代码

      1.3 接口调用示例

    复制代码
     1 int main(int argc, const char * argv[]) {
     2     @autoreleasepool
     3     {
     4         
     5         NSString *plainText = @"O57W05XN-EQ2HCD3V-LPJJ4H0N-ZFO2WHRR-9HAVXR2J-YTYXDQPK-SJXZXALI-FAIHJV";
     6         NSString *key = @"12345678901234561234567890123456";
     7         
     8         NSString *cryptText = [plainText aes256_encrypt:key];
     9         NSLog(@"cryptText:
    %@",cryptText);
    10         
    11         NSString *newPlainText = [cryptText aes256_decrypt:key];
    12         NSLog(@"newPlainText:%@",newPlainText);
    13         
    14         NSString *newCrypText3 = @"u7cKED8fscZ6Czs5eU7eMXnm6/5awKzWbUFk+D1jQdZIm5JUnKgqNzI/vmiwFPvY5qD5VIfH7qAJzjDSZXNkspG/b4if5bSkdfFp/3Aysbw=";
    15         NSString *newPlainText3 = [newCrypText3 aes256_decrypt:key];
    16         NSLog(@"newPlainText3:%@",newPlainText3);
    17 
    18     }
    19     return 0;
    20 }
    复制代码

      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位字符串。数字签名和复杂的加密系统中都有使用,单独使用由于撞库原因安全性较低。

    复制代码
     1 - (NSString *)md5HexDigest
     2 {
     3     const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
     4     
     5     unsigned char result[CC_MD5_DIGEST_LENGTH];
     6     
     7     CC_MD5(cstr, (unsigned int)strlen(cstr), result);
     8     
     9     NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    10     
    11     for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
    12         [output appendFormat:@"%02x", result[i]];
    13     
    14     return output;
    15 
    16 }
    复制代码

      这里将结果以16进制字符串形式保存,也可以进行base64等其它处理。

      2.2 安全散列算法SHA

      SHA按结果的位数分为256、484、512三种基本方式,根据对结果的要求而选择即可。通过CC_SHA256_DIGEST_LENGTH等枚举类型进行设置。

    复制代码
     1 - (NSString *)sha256HexDigest
     2 {
     3     const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
     4     NSData *data = [NSData dataWithBytes:cstr length:self.length];
     5     
     6     uint8_t digest[CC_SHA256_DIGEST_LENGTH];
     7     
     8     CC_SHA256(data.bytes, (unsigned int)data.length, digest);
     9     
    10     NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
    11     
    12     for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++)
    13         [output appendFormat:@"%02x", digest[i]];
    14     
    15     return output;
    16 }
  • 相关阅读:
    Windows Server 2003 SP2(32位) 中文版 下载地址 光盘整合方法
    用Recycle()方法对Java对象的重要性
    Lotus中千奇百怪的 $$
    Developing a simple application using steps "User Decision" and "Mail"(1) 沧海
    沟通中的情绪管理(演讲稿) 沧海
    人只有在压力之下,才可能成功,没做一件事,都必须成功,不许言败 沧海
    什么是IDOC,以及IDOC的步骤 沧海
    VS2008 Professional Edition CHS中的deffactory.dat读取错误 沧海
    Including custom text in the step "User Decision" 沧海
    SAP Upgrade Strategy 沧海
  • 原文地址:https://www.cnblogs.com/jinguanzhang/p/5809932.html
Copyright © 2011-2022 走看看