对称加密

对称加密算法

对称加密
(也叫私钥加密)指加密解密使用相同密钥的加密算法。
有时又叫传统密码算法,就是加密密钥能够从解密密钥中推算出来,同时解密密钥也可以从加密密钥中推算出来。
数据发信方将明文(原始数据)和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。
收信方收到密文后,若想解读原文,则需要使用加密用过的密钥相同算法的逆算法对密文进行解密,才能使其恢复成可读明文
即:
明文——>加密——>密文
密文——>解密——>明文

特点

  • 算法公开、计算量小、加密速度快、加密效率高。
  • 加密/解密使用相同的密钥
  • 加密和解密的过程是可逆的

缺点
密钥管理困难,使用成本较高,双方都使用同样的密钥,安全性得不到保证。
经典加密算法

  • DES(Data Encryption Standard):数据加密标准(现在用的比较少,因为它的加密强度不够,能够暴力破解)
  • 3DES:原理和DES几乎是一样的,只是使用3个密钥,对相同的数据执行三次加密,增强加密强度。(缺点:要维护3个密钥,大大增加了维护成本)。
  • AES(Advanced Encryption Standard):高级加密标准,目前美国国家安全局使用的,苹果的钥匙串访问采用的就AES加密。是现在公认的最安全的加密方式,是对称密钥加密中最流行的算法。

加密模式

  • ECB:电子密码本,就是每个块都是独立加密的。
image
  • CBC:密码块链,使用一个密钥和一个初始化向量(IV)对数据执行加密转换。
image

只要是对称加密都有 ECB和 CBC模式,加密模式是加密过程对独立数据块的处理。对于较长的明文进行加密需要进行分块加密,在实际开发中,推荐使用CBC的,ECB的要少用。

下面看一下终端演示ECB和CBC加密。

ECB模式

//加密
$ openssl enc -des-ecb -K 616263 -nosalt -in msg1.txt -out
msg1.bin

//解密
$ openssl enc -des-ecb -K 616263 -nosalt -in msg1.bin -out
msg1.txt -d

//xxd 命令用于以十六进制显示文件的内容
$ xxd msg1.bin

CBC模式

//加密
$ openssl enc -des-cbc -K 616263 -iv000000000000 -nosalt -in
msg1.txt -out msg1.bin

//解密
$ openssl enc -des-cbc -K 616263 -iv000000000000 -nosalt -in
msg1.bin -out msg1.txt -d

//查看加密之后的二进制文件
$ xxd msg1.bin

链接://www.greatytc.com/p/425a82d30f36
链接://www.greatytc.com/p/7a28b6ae7481
对称加密ios代码实现
下面我们就看一下对称加密算法AES在ios代码中的实现。
头文件引用需要注意的地方
首先我们需要注意的就是头文件的引用。
//常用加解密算法

include <CommonCrypto/CommonCryptor.h>

上面这个常用加密算法,包含了AES、DES和已经废弃的RC4。
//摘要算法

include <CommonCrypto/CommonDigest.h>

上面这个常用算法,包括如MD5、SHA等。
AES算法代码实现
AES主要应用在关键数据和文件的的保密同时又需要解密的情形,其加密密钥和解密密钥相同,根据密钥长度分为128、192和256三种级别,密钥长度越大安全性也就越大,但性能也就越低,根据实际业务的安全要求来决定就好。通常情况,对一些关键数据进行加密的对象都是字符串,加密结果也以字符串进行保存,所以在设计接口的时候参数和返回值均为字符串。
下面我们还是直接看代码吧。

  1. JJAESVC.m
#import "JJAESVC.h"
#import <CommonCrypto/CommonCrypto.h>

@interface JJAESVC ()

@property (nonatomic, assign) BOOL isEncode;
@property (nonatomic, copy) NSString *encodeStr;

@end

@implementation JJAESVC

#pragma mark - Override Base Function

static NSString * const key = @"I am a AES key";

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor darkGrayColor];
    
    self.isEncode = YES;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (self.isEncode) {
        NSString *aesEncryptResult = [self AES256Encrypt:key unencryptedStr:@"Celin"];
        NSLog(@"加密后的结果是:%@", aesEncryptResult);
        self.encodeStr = aesEncryptResult;
    }
    else {
        NSString *aesDecryptResult = [self AES256Decrypt:key undecryptedStr:self.encodeStr];
        NSLog(@"解密后的结果是:%@", aesDecryptResult);
    }
}

#pragma mark - Object Private Function

//AES加密

- (NSString *)AES256Encrypt:(NSString*)key unencryptedStr:(NSString *)unencryptedStr
{
    self.isEncode = NO;
    
    const char *cstr = [unencryptedStr cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:unencryptedStr.length];
    
    // 对于AES256,“密钥”应为32字节,否则用0填充
    char keyPtr[kCCKeySizeAES256 + 1];
    bzero(keyPtr, sizeof(keyPtr));
    
    // 获取 key data
    [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, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [data bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesEncrypted);
    
    if (cryptStatus == kCCSuccess)
    {
        ////NSData的结果result强引用buffer, 需要释放
        NSData *result = [NSMutableData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        
        //将result转化为字符串
        if (result && result.length > 0) {
            
            Byte *datas = (Byte*)[result bytes];
            NSMutableString *output = [NSMutableString stringWithCapacity:result.length * 2];
            for(int i = 0; i < result.length; i++){
                [output appendFormat:@"%02x", datas[i]];
            }
            return output;
        }
    }
    
    if (buffer)
        //清空buffer
        free(buffer);
    
    return nil;
}

//AES解密

- (NSString *)AES256Decrypt:(NSString *)key undecryptedStr:(NSString *)undecryptedStr
{
    self.isEncode = NO;
    
    //将undecryptedStr二进制数据字符串为NSData
    NSMutableData *data = [NSMutableData dataWithCapacity:undecryptedStr.length / 2];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i;
    
    for (i=0; i < [undecryptedStr length] / 2; i++) {
        byte_chars[0] = [undecryptedStr characterAtIndex:i*2];
        byte_chars[1] = [undecryptedStr characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [data appendBytes:&whole_byte length:1];
    }
    
    // 对于AES256,“密钥”应为32字节,否则用0填充
    char keyPtr[kCCKeySizeAES256 + 1];
    
    //填0补充位置
    bzero(keyPtr, sizeof(keyPtr));
    
    // 获取key数据
    [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, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [data bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesDecrypted);
    
    if (cryptStatus == kCCSuccess)
    {
        //NSData的结果result强引用buffer, 需要释放
        NSData *result = [NSMutableData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        
        return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
    }
    
    if (buffer)
        free(buffer);
    
    return nil;
}

@end

下面我们看输出结果

2017-08-20 21:28:01.734 JJOC[6952:156807] 加密后的结果是:aff94ed21c0fda887378d01c5f310017
2017-08-20 21:28:04.294 JJOC[6952:156807] 解密后的结果是:Celin

DES算法代码实现
下面我们就看一下DES算法的代码实现。

  1. JJDESVC.m
#import "JJDESVC.h"
#import <CommonCrypto/CommonCrypto.h>

@interface JJDESVC ()

@property (nonatomic, assign) BOOL isEncode;
@property (nonatomic, copy) NSString *encodeStr;

@end

@implementation JJDESVC

#pragma mark - Override Base Function

static NSString * const key = @"I am a DES key";
const Byte DES_IV[] = {1,2,3,4,5,6,7,8};

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor darkGrayColor];
    
    self.isEncode = YES;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (self.isEncode) {
        NSString *desEncryptResult = [self DESEncrypt: key encryptedStr:@"Celin"];
        self.encodeStr = desEncryptResult;
        NSLog(@"加密后的结果:%@", desEncryptResult);
    }
    else {
        NSString *desDecryptResult = [self DESDecrypt:key decryptedStr:self.encodeStr];
        NSLog(@"解密后的结果是:%@", desDecryptResult);
    }
}

#pragma mark - Object Private Function

//加密

- (NSString *)DESEncrypt:(NSString *)key encryptedStr:(NSString *)encryptedStr
{
    self.isEncode = NO;
    
    NSString *ciphertext = nil;
    NSData *textData = [encryptedStr dataUsingEncoding:NSUTF8StringEncoding];
    NSUInteger dataLength = [textData length];
    unsigned char buffer[1024];
    memset(buffer, 0, sizeof(char));
    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
                                          kCCOptionPKCS7Padding|kCCOptionECBMode,
                                          [key UTF8String], kCCKeySizeDES,
                                          DES_IV,
                                          [textData bytes], dataLength,
                                          buffer, 1024,
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted];
        ciphertext = [data base64EncodedStringWithOptions:0];
    }
    return ciphertext;
}

//解密

- (NSString *)DESDecrypt:(NSString *)key decryptedStr:(NSString *)decryptedStr
{
    self.isEncode = YES;
    
    NSString *plaintext = nil;
    NSData* cipherdata = [[NSData alloc] initWithBase64EncodedString:decryptedStr options:NSDataBase64DecodingIgnoreUnknownCharacters];
    unsigned char buffer[1024];
    memset(buffer, 0, sizeof(char));
    size_t numBytesDecrypted = 0;
    
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES,
                                          kCCOptionPKCS7Padding|kCCOptionECBMode,
                                          [key UTF8String], kCCKeySizeDES,
                                          DES_IV,
                                          [cipherdata bytes], [cipherdata length],
                                          buffer, 1024,
                                          &numBytesDecrypted);
    if(cryptStatus == kCCSuccess) {
        NSData *plaindata = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted];
        plaintext = [[NSString alloc] initWithData:plaindata encoding:NSUTF8StringEncoding];
    }
    return plaintext;
}

@end

下面我们看输出结果

2017-08-20 22:02:49.421 JJOC[7853:178560] 加密后的结果:Jjfkti63tIM=
2017-08-20 22:02:50.982 JJOC[7853:178560] 解密后的结果是:Celin

提示:
加密过程是先加密,再base64编码
解密过程是先base64解码,再解密
适用业务场景:
1.网络请求过程中的敏感信息,请求的时候用AES加密请求数据,服务端返回的时候客户端去解密;2.如果有数据库的时候,数据库里面的数据也可以加密好给到客户端,防止被人破解.

DES:Data Encryption Standard,即数据加密算法,它是IBM公司于1975年研究成功并公开发表的。

+ (NSString *)encrypt:(NSString *)sText encryptOrDecrypt:(CCOperation)encryptOperation key:(NSString *)key
{
const void *dataIn;
size_t dataInLength;
if (encryptOperation == kCCDecrypt)//传递过来的是decrypt 解码
{
//解码 base64
NSData *decryptData = [GTMBase64 decodeData:[sText dataUsingEncoding:NSUTF8StringEncoding]];//转成utf-8并decode
dataInLength = [decryptData length];
dataIn = [decryptData bytes];
}
else //encrypt
{
NSData* encryptData = [sText dataUsingEncoding:NSUTF8StringEncoding];
dataInLength = [encryptData length];
dataIn = (const void *)[encryptData bytes];
}
/*
DES加密 :用CCCrypt函数加密一下,然后用base64编码下,传过去
DES解密 :把收到的数据根据base64,decode一下,然后再用CCCrypt函数解密,得到原本的数据
*/
CCCryptorStatus ccStatus;
uint8_t *dataOut = NULL; //可以理解位type/typedef 的缩写(有效的维护了代码,比如:一个人用int,一个人用long。最好用typedef来定义)
size_t dataOutAvailable = 0; //size_t 是操作符sizeof返回的结果类型
size_t dataOutMoved = 0;
dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES – 1);
dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
memset((void *)dataOut, 0x0, dataOutAvailable);//将已开辟内存空间buffer的首 1 个字节的值设为值 0
NSString *initIv = @”12345678″;
const void *vkey = (const void *) [key UTF8String];
const void *iv = (const void *) [initIv UTF8String];
//CCCrypt函数 加密/解密
ccStatus = CCCrypt(encryptOperation,// 加密/解密
kCCAlgorithmDES,// 加密根据哪个标准(des,3des,aes。。。。)
kCCOptionPKCS7Padding,// 选项分组密码算法(des:对每块分组加一次密 3DES:对每块分组加三个不同的密)
vkey, //密钥 加密和解密的密钥必须一致
kCCKeySizeDES,// DES 密钥的大小(kCCKeySizeDES=8)
iv, // 可选的初始矢量
dataIn, // 数据的存储单元
dataInLength,// 数据的大小
(void *)dataOut,// 用于返回数据
dataOutAvailable,
&dataOutMoved);
NSString *result = nil;
if (encryptOperation == kCCDecrypt)//encryptOperation==1 解码
{
//得到解密出来的data数据,改变为utf-8的字符串
result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved] encoding:NSUTF8StringEncoding];
}
else //encryptOperation==0 (加密过程中,把加好密的数据转成base64的)
{
//编码 base64
NSData *data = [NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved];
result = [GTMBase64 stringByEncodingData:data];
}
return result;
}
//加密
+(NSString *) encryptUseDES2:(NSString *)plainText key:(NSString *)key{
    NSString *ciphertext = nil;
    const char *textBytes = [plainText UTF8String];
    size_t dataLength = [plainText length];
    //==================
    
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (dataLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    
    NSString *testString = key;
    NSData *testData = [testString dataUsingEncoding: NSUTF8StringEncoding];
    Byte *iv = (Byte *)[testData bytes];
    
    
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
                                          kCCOptionPKCS7Padding,
                                          [key UTF8String], kCCKeySizeDES,
                                          iv,
                                          textBytes, dataLength,
                                          (void *)bufferPtr, bufferPtrSize,
                                          &movedBytes);
    if (cryptStatus == kCCSuccess) {
        
        ciphertext= [XuDes parseByte2HexString:bufferPtr :(int)movedBytes];

    }
    ciphertext=[ciphertext uppercaseString];//字符变大写
    
    return ciphertext ;
}
//解密
+(NSString *)decryptUseDES:(NSString *)cipherText key:(NSString *)key
{
    
    NSData* cipherData = [XuDes convertHexStrToData:[cipherText lowercaseString]];
    NSLog(@"++++++++///%@",cipherData);
    unsigned char buffer[1024];
    memset(buffer, 0, sizeof(char));
    size_t numBytesDecrypted = 0;
    NSString *testString = key;
    NSData *testData = [testString dataUsingEncoding: NSUTF8StringEncoding];
    Byte *iv = (Byte *)[testData bytes];
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          kCCAlgorithmDES,
                                          kCCOptionPKCS7Padding,
                                          [key UTF8String],
                                          kCCKeySizeDES,
                                          iv,
                                          [cipherData bytes],
                                          [cipherData length],
                                          buffer,
                                          1024,
                                          &numBytesDecrypted);
    NSString* plainText = nil;
    if (cryptStatus == kCCSuccess) {
        NSData* data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted];
        plainText = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    }
    return plainText;

}

加密解密中有两个方法调用,其实是为了16进制与data之间的转换。有些宝宝们的公司并未转换成16进制,而是需要跟base64共同加解密。方法适用,只需要将得出的plainText 的值转成base64即可。

加密时转成16进制
+(NSString *) parseByte2HexString:(Byte *) bytes  :(int)len{
    
    
    NSString *hexStr = @"";
    
    if(bytes)
    {
        for(int i=0;i<len;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];
            }
            
            NSLog(@"%@",hexStr);
        }
    }
    return hexStr;
}
解密时转回data
+ (NSData *)convertHexStrToData:(NSString *)str {
    if (!str || [str length] == 0) {
        return nil;
    }
    
    NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
    NSRange range;
    if ([str length] % 2 == 0) {
        range = NSMakeRange(0, 2);
    } else {
        range = NSMakeRange(0, 1);
    }
    for (NSInteger i = range.location; i < [str length]; i += 2) {
        unsigned int anInt;
        NSString *hexCharStr = [str substringWithRange:range];
        NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
        
        [scanner scanHexInt:&anInt];
        NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
        [hexData appendData:entity];
        
        range.location += range.length;
        range.length = 2;
    }
    
    NSLog(@"hexdata: %@", hexData);
    return hexData;
}

3DES

3DES是三重数据加密算法块密码的通称,听到名字就知道与DES加密有关,简单的理解为用DES加密三次,通过增加DES的密钥长度来避免暴力破解。
3DES算法是指使用双长度(16字节)[密钥](http://baike.baidu.com/view/934.htm)K=(KL||KR)将8字节明文[数据块](http://baike.baidu.com/view/702806.htm)进行3次DES加密/解密。
DES的密钥是8个字节,但实际上只有7个用上,也就是56位。
3DES是用3个或2个des密钥加密一串明文,最少112位最多168位。也就是14~21个字母或数字符号。

设Ek()和Dk()分别代表DES算法的加密和解密过程,k代表DES算法使用的密钥,M代表明文,C代表密文,则3DES算法的过程可表示为:
加密:C = Ek3(Dk2(Ek1(M))) 即对明文数据进行,加密 --> 解密 --> 加密的过程,最后得到密文数据
解密:M = Dk1(Ek2(Dk3(C))) 即对密文数据进行,解密 --> 加密 --> 解密的过程,最后得到明文数据

这里可以K1=K3,但不能K1=K2=K3(如果相等的话就成了DES算法了)
3DES(K1=K3),可以是3DES-CBC,也可以是3DES-ECB,3DES-CBC整个算法的流程和DES-CBC一样,但是在原来的加密或者解密处增加了异或运算的步骤,使用的**密钥是16字节长度的密钥**,将密钥分成左8字节和右8字节的两部分,即k1=左8字节,k2=右8字节,然后进行加密运算和解密运算。

3DES(K1≠K2≠K3),和3DES-CBC的流程完全一样,**只是使用的密钥是24字节的**,但在每个加密解密加密时候用的密钥不一样,将密钥分为3段8字节的密钥分别为密钥1、密钥2、密钥3,在3DES加密时对加密解密加密依次使用密钥1、密钥2、密钥3,在3DES解密时对解密加密解密依次使用密钥3、密钥2、密钥1。
由于DES加解密算法是每8个字节作为一个加解密数据块,因此在实现该算法时,需要对数据进行分块和补位(即最后不足8字节时,要补足8字节)

ECB模式:将待处理的数据分成若干块,每块的长度都为8字节。然后对每块进行加密或解密,最后将他们连接在一起便是最终的结果。每一块的数据互不干扰。
CBC模式:也需要将待处理的数据分块,但是每一块数据在加密或者解密之前都要与前一块的结果做一次异或操作,因此该模式需要定义一个特殊的8字节Key,用于和第一块数据做异或操作。这个特殊的Key就是通常说的初始化向量。在代码中书写时需要配置iv参数,注意iv参数是对应CBC模式的。这样一来,每一块数据都是有联系的,这是与ECB模式不同的一点。
需要注意的是  
iOS 的加密pkcs7padding那块和安卓的不一致

一行代码实现3DES加密解密需要用到写的 JKEncrypt https://github.com/jukai9316/JKEncrypt
下面先解析以下3DES的实现,然后再说,如何使用JKEncrypt。****
注意点:填充方式不一样
在与后台交互的过程中,由于java 里面用的是PKCS5Padding,而iOS只有kCCOptionPKCS7Padding,所以用kCCOptionPKCS7Padding | kCCOptionECBMode 相当于PKCS5Padding。
以下是3DES 256 在iOS开发中的实现:

#import <CommonCrypto/CommonDigest.h>  
#import <CommonCrypto/CommonCryptor.h>
#import <Security/Security.h>
#import "GTMBase64.h"
//密匙 key
#define gkey            @"Kyle_Chu"
//偏移量
#define gIv             @"jukai"
//字符串解密
-(NSString*)doDecEncryptStr:(NSString *)encryptStr{
    
    NSData *encryptData = [GTMBase64 decodeData:[encryptStr dataUsingEncoding:NSUTF8StringEncoding]];
    
    size_t plainTextBufferSize = [encryptData length];
    const void *vplainText = [encryptData bytes];
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    
    bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    const void *vkey = (const void *) [gkey UTF8String];
    
    const void *vinitVec = (const void *) [gIv UTF8String];
    
    ccStatus = CCCrypt(kCCDecrypt,
                       kCCAlgorithm3DES,
                       kCCOptionPKCS7Padding|kCCOptionECBMode,
                       vkey,
                       kCCKeySize3DES,
                       vinitVec,
                       vplainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       &movedBytes);
    
    NSString *result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr
                                                                      length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding];
    
    
    return result;
}

十六进制的实现省略了,可以阅读JKEncrypt.m

JKEncrypt的使用:

//1、设置您需要的密匙、偏移量
//密匙 key
#define gkey            @"Kyle_Chu"
//偏移量
#define gIv             @"jukai"
// @"kyle_jukai" 是测试字符串,换成您需要加密的内容即可

JKEncrypt * en = [[JKEncrypt alloc]init];
//加密
NSString * encryptStr = [en doEncryptStr: @"kyle_jukai"];

NSString * encryptHex = [en doEncryptHex: @"kyle_jukai"];

NSLog(@"字符串加密:%@",encryptStr);
NSLog(@"十六进制加密:%@",encryptHex);
//解密
NSString *decEncryptStr = [en doDecEncryptStr:encryptStr];

NSString *decEncryptHex = [en doEncryptHex:encryptHex];

NSLog(@"字符串解密:%@",decEncryptStr);
NSLog(@"字符串解密:%@",decEncryptHex);

AES:高级加密标准,这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。高级加密标准已然成为对称密钥加密中最流行的算法之一。

+(NSData *)AES256EncryptWithKey:(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 *)AES256DecryptWithKey:(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;
}

Rivest Cipher 4是一种流加密算法,密钥长度可变。它加解密使用相同的密钥,因此也属于对称加密算法。

#ifndef CX_SWAP // swap two value
#define CX_SWAP(_a_, _b_) do {__typeof__(_a_) _tmp_ = (_a_); (_a_) = (_b_); (_b_) = (_tmp_); } while(0)
#endif

@implementation NSString (CX)
- (NSString *)rc4WithKey:(NSString *)key {
    int j = 0;
    unichar res[self.length];
    const unichar *buffer = res;
    unsigned char s[256];
    for (int i = 0; i < 256; i++) {
        s[i] = i;
    }
    for (int i = 0; i < 256; i++) {
        j = (j + s[i] + [key characterAtIndex:(i%key.length)])%256;
        CX_SWAP(s[i], s[j]);
    }
    int i = j = 0;
    for (int y = 0; y < self.length; y++) {
        i = (i + 1) % 256;
        j = (j + 1) % 256;
        CX_SWAP(s[i], s[j]);
        
        unsigned char f = [self characterAtIndex:y] ^ s[ (s[i] + s[j]) % 256 ];
        res[y] = f;
    }
    return [NSString stringWithCharacters:buffer length:self.length];
}
@end
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容

  • 目录一、对称加密 1、对称加密是什么 2、对称加密的优点 3、对称加密的问题 4、对称加密的应用场景 5、对称加密...
    意一ineyee阅读 61,857评论 8 110
  • 加密的原因:保证数据安全 加密必备要素:1、明文/密文 2、秘钥 3、算法 秘钥:在密码学中是一个定长的字符串...
    Winnifred_阅读 13,051评论 0 3
  • 一、散列(哈希) 1.简介 散列函数,又称散列算法、哈希函数,是一种从任何一种数据中创建小的数字“指纹”的方法。散...
    绿叶竹林阅读 3,470评论 3 3
  • 1、简介对称加密算法又称传统加密算法。加密和解密使用同一个 密钥。 1.1对称加密算法示例密钥:X加密算法:每个字...
    6ffd6634d577阅读 2,999评论 0 2
  • 1、原来你是那么的攻于算计,怕我连累到你,扯到你的后腿。 2、你没有义务,你也没得资格管我。 3、归家的意义何在?...
    嬉笑怒骂皆生活阅读 111评论 0 0