iOS - 常用的加密方式

1.Base64 加密

1.1 Base64 简单说明

描述:Base64可以成为密码学的基石,非常重要。
特点:可以将任意的二进制数据进行Base64编码
结果:所有的数据都能被编码为并只用65个字符就能表示的文本文件。
65字符:A~Z a~z 0~9 + / =
对文件进行base64编码后文件数据的变化:编码后的数据~=编码前数据的4/3,会大1/3左右。

1.2编码原理
  1. 将所有字符转化为ASCII码;
  2. 将ASCII码转化为8位二进制;
  3. 将二进制3个归成一组(不足3个在后边补0)共24位,再拆分成4组,每组6位;
  4. 统一在6位二进制前补两个0凑足8位;
  5. 将补0后的二进制转为十进制;
  6. 从Base64编码表获取十进制对应的Base64编码;
1.3实现
  • 从iOS7.0 以后,苹果就提供了Base64的编码和解码支持

编码:

-(NSString *)base64EncodeString:(NSString *)string{
  //1.先把字符串转换为二进制数据
  NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  //2.对二进制数据进行base64编码,返回编码后的字符串
  return [data base64EncodedStringWithOptions:0];
 } 

解码:

-(NSString *)base64DecodeString:(NSString *)string{
  //1.将base64编码后的字符串『解码』为二进制数据
  NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:0];
  //2.把二进制数据转换为字符串返回
  return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
 }
  • iOS7.0 以前,根据原理自己写个方法来实现编码解码(目前来说,大多数APP已经不支持iOS7.0了)

编码

+ (NSString *)base64EncodedStringFrom:(NSString *)string{
    NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
    if ([data length] == 0)
        return @"";
    
    char *characters = malloc((([data length] + 2) / 3) * 4);
    if (characters == NULL)
        return nil;
    NSUInteger length = 0;
    
    NSUInteger i = 0;
    while (i < [data length])
    {
        char buffer[3] = {0,0,0};
        short bufferLength = 0;
        while (bufferLength < 3 && i < [data length])
            buffer[bufferLength++] = ((char *)[data bytes])[i++];
        
        //  Encode the bytes in the buffer to four characters, including padding "=" characters if necessary.
        characters[length++] = encodingTable[(buffer[0] & 0xFC) >> 2];
        characters[length++] = encodingTable[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
        if (bufferLength > 1)
            characters[length++] = encodingTable[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
        else characters[length++] = '=';
        if (bufferLength > 2)
            characters[length++] = encodingTable[buffer[2] & 0x3F];
        else characters[length++] = '=';
    }
    
    return [[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES];
}

解码

+ (NSString *)stringWithBase64EncodedString:(NSString *)string{
    if ([string length] == 0)
        return [NSData data];
    
    static char *decodingTable = NULL;
    if (decodingTable == NULL)
    {
        decodingTable = malloc(256);
        if (decodingTable == NULL)
            return nil;
        memset(decodingTable, CHAR_MAX, 256);
        NSUInteger i;
        for (i = 0; i < 64; i++)
            decodingTable[(short)encodingTable[i]] = i;
    }
    
    const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
    if (characters == NULL)     //  Not an ASCII string!
        return nil;
    char *bytes = malloc((([string length] + 3) / 4) * 3);
    if (bytes == NULL)
        return nil;
    NSUInteger length = 0;
    
    NSUInteger i = 0;
    while (YES)
    {
        char buffer[4];
        short bufferLength;
        for (bufferLength = 0; bufferLength < 4; i++)
        {
            if (characters[i] == '\0')
                break;
            if (isspace(characters[i]) || characters[i] == '=')
                continue;
            buffer[bufferLength] = decodingTable[(short)characters[i]];
            if (buffer[bufferLength++] == CHAR_MAX)      //  Illegal character!
            {
                free(bytes);
                return nil;
            }
        }
        
        if (bufferLength == 0)
            break;
        if (bufferLength == 1)      //  At least two characters are needed to produce one byte!
        {
            free(bytes);
            return nil;
        }
        
        //  Decode the characters in the buffer to bytes.
        bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
        if (bufferLength > 2)
            bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
        if (bufferLength > 3)
            bytes[length++] = (buffer[2] << 6) | buffer[3];
    }
    
    bytes = realloc(bytes, length);
    NSData *data = [NSData dataWithBytesNoCopy:bytes length:length];
    return [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

}

2.MD5 加密

1.1 MD5加密简单说明

描述:MD5加密是最常用的加密方法之一,是从一段字符串中通过相应特征生成一段32位的数字字母混合码。对输入信息生成唯一的128位散列值(32个字符)

结果:MD5生成的是固定的128bit,即128个0和1的二进制位,而在实际应用开发中,通常是以16进制输出的,所以正好就是32位的16进制,说白了也就是32个16进制的数字。

1.2 MD5加密的优点:

易计算:原数据计算出MD5值很容易。
压缩性:任意长度的元数据,计算出的MD5值长度固定
抗修改:原数据只修改一个字节,计算出的MD5值也有很大差别。也就说明,跟原数据和MD5值,想伪造一个类似的数据十分困难.想得到两个原数据不同,但MD5值接近的值也是很难.
其他: MD5加密是不可解密的,但是网上有一些解析MD5的,那个相当于一个大型的数据库,通过匹配MD5去找到原密码。所以,只要在要加密的假眼或者多次MD5加密来提高加密效果,这样出来的结果一般是解析不出来的.

1.3 使用

需要导入 #import

+ (NSString *)md5:(NSString *)string{
    const char *cStr = [string UTF8String];
    unsigned char digest[CC_MD5_DIGEST_LENGTH];
    CC_MD5(cStr, (CC_LONG)strlen(cStr), digest);   
    NSMutableString *result = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [result appendFormat:@"%02X", digest[i]];
    }
    return result;
}

//使用
+ (NSString *)md5ForString:(NSString *)string{
    NSString *md5String;
    md5String = [self md5:string]; // 第一次加密
    md5String = [md5String substringToIndex:18]; // 截取长度
    md5String = [md5String stringByAppendingString:@"Test"]; // 加盐(加盐的字符串没有要求)
    md5String = [self md5:md5String]; // 第二次加密
    // 多次加密只是为了加强加密效果
    return md5String;
}

3.AES 加密

  • AES256
- (NSData *)AES256Encrypt:(NSString *)key   //加密
{
    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 | kCCOptionECBMode,
                                          keyPtr, kCCBlockSizeAES128,
                                          NULL,
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }
    free(buffer);
    return nil;
}


- (NSData *)AES256Decrypt:(NSString *)key   //解密
{
    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 | kCCOptionECBMode,
                                          keyPtr, kCCBlockSizeAES128,
                                          NULL,
                                          [self bytes], dataLength,
                                          buffer, bufferSize,
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        
    }
    free(buffer);
    return nil;
}
  • AES128
 + (NSString *)AES128Encrypt:(NSString *)plainText{  //加密
      char keyPtr[kCCKeySizeAES128+1];
      memset(keyPtr, 0, sizeof(keyPtr));
      [AESKEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
      
      char ivPtr[kCCBlockSizeAES128+1];
      memset(ivPtr, 0, sizeof(ivPtr));
      [AESIV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
      
      NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
      NSUInteger dataLength = [data length];
      
      int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
      int newSize = 0;
      
      if(diff > 0)
      {
          newSize = dataLength + diff;
      }
      
      char dataPtr[newSize];
      memcpy(dataPtr, [data bytes], [data length]);
      for(int i = 0; i < diff; i++)
      {
          dataPtr[i + dataLength] = 0x00;
      }
      
      size_t bufferSize = newSize + kCCBlockSizeAES128;
      void *buffer = malloc(bufferSize);
      memset(buffer, 0, bufferSize);
      
      size_t numBytesCrypted = 0;
      
      CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                            kCCAlgorithmAES128,
                                            0x0000,   //这里用的 NoPadding的填充方式 除此以外还有 kCCOptionPKCS7Padding 和 kCCOptionECBMode
                                            keyPtr,
                                            kCCKeySizeAES128,
                                            ivPtr,
                                            dataPtr,
                                           sizeof(dataPtr),
                                            buffer,
                                            bufferSize,
                                            &numBytesCrypted);
      
      if (cryptStatus == kCCSuccess) {
          NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
          return [GTMBase64 stringByEncodingData:resultData];
      }
      free(buffer);
      return nil;
  }
  
  + (NSString *)AES128Decrypt:(NSString *)encryptText{  //解密
      char keyPtr[kCCKeySizeAES128 + 1];
      memset(keyPtr, 0, sizeof(keyPtr));
      [AESKEY getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
      
      char ivPtr[kCCBlockSizeAES128 + 1];
      memset(ivPtr, 0, sizeof(ivPtr));
      [AESIV getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
      
      NSData *data = [GTMBase64 decodeData:[encryptText dataUsingEncoding:NSUTF8StringEncoding]];
      NSUInteger dataLength = [data length];
      size_t bufferSize = dataLength + kCCBlockSizeAES128;
      void *buffer = malloc(bufferSize);
      
      size_t numBytesCrypted = 0;
      CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                            kCCAlgorithmAES128,
                                            0x0000,
                                            keyPtr,
                                            kCCBlockSizeAES128,
                                            ivPtr,
                                            [data bytes],
                                            dataLength,
                                            buffer,
                                            bufferSize,
                                            &numBytesCrypted);
      if (cryptStatus == kCCSuccess) {
          NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
          return [[[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding] autorelease];
     }
     free(buffer);
     return nil;
 }

4.SHA1(哈希) 加密

需要导入头文件
#import

- (NSString *) sha1:(NSString *)string{
    const char *cstr = [string cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:string.length];
    
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1(data.bytes, (unsigned int)data.length, digest);
    NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
    
    for(int i=0; i

你可能感兴趣的:(iOS - 常用的加密方式)