美文网首页
514 iOS中AES对称加密(CBC模式)实现(面试点:对称加

514 iOS中AES对称加密(CBC模式)实现(面试点:对称加

作者: 枫叶1234 | 来源:发表于2021-02-28 20:24 被阅读0次

    前言:

    在我们开发中免不了和服务器做一些数据交互,在交互过程中走得都是http请求,这类请求不像https那样的安全所以就会在交互过程中做一些数据加密解密的事情,现在主流的加密是AES对称加密和RSA非对称加密下面给大家讲解下AES加密,非对称加密会过几天跟新。

    AES加密介绍:

    • AES加密是一种对称加密方式,他有基本的五种加密模式组成分别是:

    1.电码本模式(Electronic Codebook Book (ECB));
    2.密码分组链接模式(Cipher Block Chaining (CBC));
    3.计算器模式(Counter (CTR));
    4.密码反馈模式(Cipher FeedBack (CFB));
    5.输出反馈模式(Output FeedBack (OFB))

    • 以上所说的这五种加密模式我们讲最常用的CBC模式,下面我说一下实现AES对称加密(CBC)的基本步骤;

    1.要加密的密文转为NSData类型
    2.使用AES对称加密(CBC)加密NSData
    3.之后对加密过后的NSData进行编码(编码在下面我会说到)

    AES加密代码实现:

    新建SecurityUtil继承NSObject
    SecurityUtil.h实现:

      #pragma mark - AES加密
      //将string转成带密码的data
      + (NSString*)encryptAESData:(NSString*)string Withkey:(NSString * )key ivkey:(NSString * )ivkey;
      //将带密码的data转成string
      +(NSString*)decryptAESData:(NSString*)data Withkey:(NSString *)key ivkey:(NSString * )ivkey;
    

    SecurityUtil.m实现(加密部分):

      #pragma mark - AES加密
      //将string转成带密码的data
      +(NSString*)encryptAESData:(NSString*)string Withkey:(NSString *)key ivkey:(NSString *)ivkey
      {
          //将nsstring转化为nsdata
          NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
          //使用密码对nsdata进行加密
          NSData *encryptedData = [data AES128EncryptWithKey:key ivKey:ivkey];
          //加密之后编码
          return [self dataTohexString:encryptedData];;
      }
      #pragma mark - AES解密
      //将带密码的data转成string
      +(NSString*)decryptAESData:(NSString*)string Withkey:(NSString *)key ivkey:(NSString *)ivkey
      {
          //对数据进行解密
          NSData* result = [[self hexStringToData:string] AES128DecryptWithKey:key ivkey:ivkey];
          if (result && result.length > 0) {
              //加密之后进行编码
              return [[NSString alloc] initWithData:result  encoding:NSUTF8StringEncoding];
          }
             return nil;
      }
    

    SecurityUtil.m实现(编码部分):

      #pragma mark - 16位编码 -加密
      + (NSString *)dataTohexString:(NSData*)data
      {
          Byte *bytes = (Byte *)[data bytes];
          NSString *hexStr=@"";
          for(int i=0;i<[data length];i++)
          {
              NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff];//16进制数
              if([newHexStr length]==1)
                  hexStr = [NSString        stringWithFormat:@"%@0%@",hexStr,newHexStr];
              else
                  hexStr = [NSString       stringWithFormat:@"%@%@",hexStr,newHexStr];
          }
          return hexStr;
      }
      #pragma mark - 16位编码 -解密
      + (NSData*)hexStringToData:(NSString*)hexString
      {
          int j=0;
          Byte bytes[hexString.length];  ///3ds key的Byte 数组, 128位
          for(int i=0;i<[hexString length];i++)
          {
              int int_ch;  /// 两位16进制数转化后的10进制数
              unichar hex_char1 = [hexString characterAtIndex:i]; ////两位16进制数中的第一位(高位*16)
              int int_ch1;
              if(hex_char1 >= '0' && hex_char1 <='9')
              int_ch1 = (hex_char1-48)*16;   //// 0 的Ascll - 48
              else if(hex_char1 >= 'A' && hex_char1 <='F')
                  int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65
              else
                  int_ch1 = (hex_char1-87)*16; //// a 的Ascll - 97
              i++;
              unichar hex_char2 = [hexString characterAtIndex:i]; ///两位16进制数中的第二位(低位)
              int int_ch2;
              if(hex_char2 >= '0' && hex_char2 <='9')
                  int_ch2 = (hex_char2-48); //// 0 的Ascll - 48
              else if(hex_char1 >= 'A' && hex_char1 <='F')
                  int_ch2 = hex_char2-55; //// A 的Ascll - 65
              else
                  int_ch2 = hex_char2-87; //// a 的Ascll - 97   
              int_ch = int_ch1+int_ch2;
              //NSLog(@"int_ch=%x",int_ch);
              bytes[j] = int_ch;  ///将转化后的数放入Byte数组里
              j++;
          }
          //    NSData *newData = [[NSData alloc] initWithBytes:bytes length:j];
          NSData *newData = [[NSData alloc] initWithBytes:bytes length:j];
          //NSLog(@"newData=%@",newData);
          return newData;
      }
    

    新建一个NSData的扩展咋们把他命名为AES
    NSData+AES.h实现:

      @class NSString;
      @interface NSData (Encryption)
      - (NSData *)AES128EncryptWithKey:(NSString *) key ivKey:(NSString *)ivkey;//加密
      - (NSData *)AES128DecryptWithKey:(NSString *) key ivkey:(NSString * )ivkey;//解密
    

    NSData+AES.m实现:

      //(key和iv向量这里是16位的) 这里是CBC加密模式,安全性更高
      //加密
      - (NSData *)AES128EncryptWithKey:(NSString *) key ivKey:(NSString *)ivkey{
          char keyPtr[kCCKeySizeAES256+1];
          bzero(keyPtr, sizeof(keyPtr));
          [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
          NSUInteger dataLength = [self length];
          size_t bufferSize = dataLength + kCCBlockSizeAES128;
          void *buffer = malloc(bufferSize);
          size_t numBytesEncrypted = 0;
          CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128,
                                                kCCOptionPKCS7Padding ,
                                                keyPtr, kCCBlockSizeAES128,
                                                [ivkey UTF8String],
                                                [self bytes], dataLength,
                                                buffer, bufferSize,
                                                &numBytesEncrypted);
          if (cryptStatus == kCCSuccess) {
              return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
          }
          free(buffer);
          return nil;
      }
      //解密
      - (NSData *)AES128DecryptWithKey:(NSString *) key ivkey:(NSString *)ivkey {
          char keyPtr[kCCKeySizeAES256+1];
          bzero(keyPtr, sizeof(keyPtr));
          [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
          NSUInteger dataLength = [self length];
          size_t bufferSize = dataLength + kCCBlockSizeAES128;
          void *buffer = malloc(bufferSize);
          size_t numBytesDecrypted = 0;
          CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128,
                                                kCCOptionPKCS7Padding ,
                                                keyPtr, kCCBlockSizeAES128,
                                                [ivkey UTF8String],
                                                [self bytes], dataLength,
                                                buffer, bufferSize,
                                                &numBytesDecrypted);
          if (cryptStatus == kCCSuccess) {
              return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];        
          }
          free(buffer);
          return nil;
      }
    
    • 试验调用一下:
    NSString *originalString = @"加密这个字符串";
    NSString * secretStr = @"秘钥是这个";
    //CBC加密字符串
    NSString * encryptCBC = [SecurityUtil  encryptAESData: originalString Withkey:uuid ivkey: secretStr];
    //CBC解密字符串
    NSString * decryptCBC = [SecurityUtil  decryptAESData: encryptCBC Withkey:uuid ivkey: secretStr];
    
    • AES加密(CBC)全部实现我们已经做好了下面我讲一下编码;
      编码有很多种在我的项目中我们采用了16位编码,为什么说我要采用16位编码这又要讲到Base64编码,首先我先给大家看下这俩种编码后的密文是什么样子的。。

    Base64编码:

    BsDhzys9BkPbfuMUK4SDpSqh47FMMNltY6huj/lMwI77ibB61Wk9eBMMzQRmNgVvmnbTpWKNUdS2XXKgfwuEyGjJC7uUSkoTuV/TFN+BEFv3vlL0UKeY1Jt8plcJzrDKyDxK0oQOiM9THr5ZTFOsdDGfM3cmGWf7KRTQFwYE=

    16位编码:
    06C0E1CF2B3D0643DB7EE3142B8483A52AA1E3B14C33FA21365B58EA1BA3FE533023BEE26C1EB55A4F5E04C33341198D815BE69DB4E958A354752D975CA81FC2E1321A3242EEE5129284EE57F4C537E04416FDEF94BD1429E63526DF2995C273AC32B20F12B4A103A233D4C7AF965314EB1D0C67CCDDC98659FECA453405C181

    大家也看到了俩种编码之后的密文明显的不同之处,Base64的唯一缺点就是其中有很多的特殊符号这种特殊符号在http传送过程中会发生改变导致密文解码解不了,所以我就采用了16位编码避免这种事情的发生。

    相关文章

      网友评论

          本文标题:514 iOS中AES对称加密(CBC模式)实现(面试点:对称加

          本文链接:https://www.haomeiwen.com/subject/enknfltx.html