对称加密算法
对称加密
(也叫私钥加密
)指加密
和解密
使用相同密钥
的加密算法。
有时又叫传统密码算法
,就是加密密钥
能够从解密密钥
中推算出来,同时解密密钥
也可以从加密密钥
中推算出来。
数据发信方将明文(原始数据
)和加密密钥
一起经过特殊加密算法处理后,使其变成复杂的加密密文
发送出去。
收信方收到密文后,若想解读原文,则需要使用加密用过的密钥
及相同算法的逆算法
对密文进行解密,才能使其恢复成可读明文
。
即:
明文——>加密——>密文
密文——>解密——>明文
特点
- 算法公开、计算量小、加密速度快、加密效率高。
- 加密/解密使用相同的密钥
- 加密和解密的过程是可逆的
缺点
密钥管理困难,使用成本较高,双方都使用同样的密钥,安全性得不到保证。
经典加密算法
-
DES(Data Encryption Standard)
:数据加密标准(现在用的比较少,因为它的加密强度不够,能够暴力破解) -
3DES
:原理和DES几乎是一样的,只是使用3个密钥,对相同的数据执行三次加密,增强加密强度。(缺点:要维护3个密钥,大大增加了维护成本)。 -
AES(Advanced Encryption Standard)
:高级加密标准,目前美国国家安全局使用的,苹果的钥匙串访问采用的就AES加密。是现在公认的最安全的加密方式,是对称密钥加密中最流行的算法。
加密模式
-
ECB
:电子密码本,就是每个块都是独立加密的。
-
CBC
:密码块链,使用一个密钥和一个初始化向量(IV)对数据执行加密转换。
只要是对称加密都有 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三种级别,密钥长度越大安全性也就越大,但性能也就越低,根据实际业务的安全要求来决定就好。通常情况,对一些关键数据进行加密的对象都是字符串,加密结果也以字符串进行保存,所以在设计接口的时候参数和返回值均为字符串。
下面我们还是直接看代码吧。
- 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算法的代码实现。
- 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