本文主要是对称算法的终端演示+代码演示
![0a815c0cd6c5e8294ddb6869b75e5cbc.png]()
OpenSSL终端演示
下面主要采用DES、AES和 ECB、CBC两两组合的方式进行演示,涉及的终端命令主要有以下一些
加密
AES + ECB加密“hello”字符串
echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
AES + CBC加密“hello”字符串
echo -n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
解密
AES + ECB解密
echo -n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt –d
AES + CBC解密
echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt –d
1、DES + ECB
加密
000000000000
111111111111
222222222222
000000000000
111111111111
222222222222
000000000000
111111111111
222222222222
000000000000
111111111111
222222222222
000000000000
111111111111
222222222222
000000000000
111111111111
222222222222
000000000000
111111111111
222222222222
880000000000
111111111111
222222222222
000000000000
......
查看此时的加密后密文二进制,与上面进行对比
![87b01a08698d3631103ba3826d1889bb.webp]()
2、DES + CBC
注:剩余的AES+ECB、AES+CBC请读者自行演练,这里就不在做演示了
代码演示
同样是通过DES、AES和 ECB、CBC两两组合的方式进行演示
1、AES + ECB
- (void)testEnc{
// AES + ECB 加密
NSString *key = @"abc";
NSString *encStr = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:nil];
NSLog(@"AES + ECB : %@", encStr);
}<!--运行结果-->AES + ECB : d1QG4T2tivoi0Kiu3NEmZQ==<!--终端命令-->$ echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
//与程序运行结果是一样的
d1QG4T2tivoi0Kiu3NEmZQ==
$ echo -n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D |openssl enc -aes-128-ecb -K 616263 -nosalt -d
hello%
echo -n hello 输出hello
| :表示输出符
注:des 和 aes对比,加密强度不一样
![584310655ffca52db53ebaefd666a971.webp]()
2、AES + CBC
- (void)testEnc{// 2、AES + CBC 加密
uint8_t iv[8] = {1, 2, 3, 4, 5, 6, 7, 8}; NSData *data = [NSData dataWithBytes:iv length:sizeof(iv)]; NSString *key = @"abc"; NSString *encStr = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:data]; //解密
NSString * decStr = [[EncryptionTools sharedEncryptionTools] decryptString:encStr keyString:key iv:data]; NSLog(@"AES + CBC : %@", encStr); NSLog(@"AES + CBC : %@", decStr);
}//打印结果AES + CBC : u3W/N816uzFpcg6pZ+kbdg==
AES + CBC : hello
<!--终端命令-->
$ echo -n hello | openssl enc -aes-128-cbc -K 616263 -iv 0102030405060708 -nosalt | base64
u3W/N816uzFpcg6pZ+kbdg==
$ echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D |openssl enc -aes-128-cbc -K 616263 -iv 0102030405060708 -nosalt -d
hello%
3、DES + ECB
- (void)testEnc{// 3、DES + ECB
[EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
NSString *key = @"abc";
NSString *encStr = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:nil];
NSLog(@"DES + ECB : %@", encStr);
}//运行结果DES + ECB : HQr0Oij2kbo=<!--终端命令-->$ echo -n hello | openssl enc -des-ecb -K 616263 -nosalt | base64
HQr0Oij2kbo=
$ echo -n HQr0Oij2kbo= | base64 -D | openssl enc -des-ecb -K 616263 -nosalt -d
hello%
4、DES + CBC
- (void)testEnc{// 4、DES + CBC
[EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmDES;
uint8_t iv[8] = {1, 2, 3, 4, 5, 6, 7, 8}; NSData *data = [NSData dataWithBytes:iv length:sizeof(iv)]; NSString *key = @"abc"; NSString *encStr = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:data]; //解密
NSString * decStr = [[EncryptionTools sharedEncryptionTools] decryptString:encStr keyString:key iv:data]; NSLog(@"AES + CBC : %@", encStr); NSLog(@"AES + CBC : %@", decStr);
}//运行结果AES + CBC : alvrvb3Gz88=
AES + CBC : hello
<!--终端命令-->
$ echo -n hello | openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt | base64
alvrvb3Gz88=
$ echo -n alvrvb3Gz88= | base64 -D | openssl enc -des-cbc -K 616263 -iv 0102030405060708 -nosalt -d
hello%
加密解密实现
以下是DES、AES的完整对称加解密的代码封装
<!--h-->#import <Foundation/Foundation.h>#import <CommonCrypto/CommonCrypto.h>/**
* 终端测试指令
*
* DES(ECB)加密
* $ echo -n hello | openssl enc -des-ecb -K 616263 -nosalt | base64
*
* DES(CBC)加密
* $ echo -n hello | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
*
* AES(ECB)加密
* $ echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
*
* AES(CBC)加密
* $ echo -n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
*
* DES(ECB)解密
* $ echo -n HQr0Oij2kbo= | base64 -D | openssl enc -des-ecb -K 616263 -nosalt -d
*
* DES(CBC)解密
* $ echo -n alvrvb3Gz88= | base64 -D | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -d
*
* AES(ECB)解密
* $ echo -n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt -d
*
* AES(CBC)解密
* $ echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -d
*
* 提示:
* 1> 加密过程是先加密,再base64编码
* 2> 解密过程是先base64解码,再解密
*/@interface EncryptionTools : NSObject+ (instancetype)sharedEncryptionTools; /**
@constant kCCAlgorithmAES 高级加密标准,128位(默认)
@constant kCCAlgorithmDES 数据加密标准
*/
@property (nonatomic, assign) uint32_t algorithm; /**
* 加密字符串并返回base64编码字符串
*
* @param string 要加密的字符串
* @param keyString 加密密钥
* @param iv 初始化向量(8个字节)
*
* @return 返回加密后的base64编码字符串
*/- (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv; /**
* 解密字符串
*
* @param string 加密并base64编码后的字符串
* @param keyString 解密密钥
* @param iv 初始化向量(8个字节)
*
* @return 返回解密后的字符串
*/- (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;@end<!--m-->#import "EncryptionTools.h"@interface EncryptionTools()
@property (nonatomic, assign) int keySize; @property (nonatomic, assign) int blockSize; @end@implementation EncryptionTools+ (instancetype)sharedEncryptionTools { static EncryptionTools *instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
instance.algorithm = kCCAlgorithmAES;
}); return instance;
}
- (void)setAlgorithm:(uint32_t)algorithm {
_algorithm = algorithm; switch (algorithm) { case kCCAlgorithmAES: self.keySize = kCCKeySizeAES128; self.blockSize = kCCBlockSizeAES128; break; case kCCAlgorithmDES: self.keySize = kCCKeySizeDES; self.blockSize = kCCBlockSizeDES; break; default: break;
}
}
- (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv { // 设置秘钥
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
uint8_t cKey[self.keySize];
bzero(cKey, sizeof(cKey));
[keyData getBytes:cKey length:self.keySize]; // 设置iv
uint8_t cIv[self.blockSize];
bzero(cIv, self.blockSize); int option = 0; if (iv) {
[iv getBytes:cIv length:self.blockSize];
option = kCCOptionPKCS7Padding;
} else { /*
- kCCOptionPKCS7Padding | kCCOptionECBMode 本模式 - ECB模式
- kCCOptionPKCS7Padding 链的模式 - CBC模式
*/
option = kCCOptionPKCS7Padding | kCCOptionECBMode;
} // 设置输出缓冲区
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
size_t bufferSize = [data length] + self.blockSize; void *buffer = malloc(bufferSize); // 开始加密
size_t encryptedSize = 0; //加密解密都是它 -- CCCrypt
/*
- 参数1:kCCEncrypt 加密 / kCCDeccrypt 解密
- 参数2:加密算法
- 参数3:加密选项 ECB / CBC
- 参数4:KEY的地址
- 参数5:KEY的长度
- 参数6:iv初始化向量
- 参数7:加密的数据
- 参数8:加密数据的长度
- 参数9:密文的内存地址
- 参数10:密文缓冲区的大小
- 参数11:数据的指针(加密结果大小)
*/
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, self.algorithm,
option,
cKey, self.keySize,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&encryptedSize); NSData *result = nil; if (cryptStatus == kCCSuccess) {
result = [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
} else {
free(buffer); NSLog(@"[错误] 加密失败|状态编码: %d", cryptStatus);
} return [result base64EncodedStringWithOptions:0];
}
- (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv { // 设置秘钥
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
uint8_t cKey[self.keySize];
bzero(cKey, sizeof(cKey));
[keyData getBytes:cKey length:self.keySize]; // 设置iv
uint8_t cIv[self.blockSize];
bzero(cIv, self.blockSize); int option = 0; if (iv) {
[iv getBytes:cIv length:self.blockSize];
option = kCCOptionPKCS7Padding;
} else {
option = kCCOptionPKCS7Padding | kCCOptionECBMode;
} // 设置输出缓冲区
NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
size_t bufferSize = [data length] + self.blockSize; void *buffer = malloc(bufferSize); // 开始解密
size_t decryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, self.algorithm,
option,
cKey, self.keySize,
cIv,
[data bytes],
[data length],
buffer,
bufferSize,
&decryptedSize); NSData *result = nil; if (cryptStatus == kCCSuccess) {
result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
} else {
free(buffer); NSLog(@"[错误] 解密失败|状态编码: %d", cryptStatus);
} return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
}@end
主要是通过系统的CCCrypt实现,其中涉及11个参数,分别是
- 参数1:kCCEncrypt 加密 / kCCDeccrypt 解密
- 参数2:加密算法
- 参数3:加密选项 ECB / CBC
- 参数4:KEY的地址
- 参数5:KEY的长度
- 参数6:iv初始化向量
- 参数7:加密的数据
- 参数8:加密数据的长度
- 参数9:密文的内存地址
- 参数10:密文缓冲区的大小
- 参数11:数据的指针(加密结果大小)
安全隐患:使用系统函数同样有数据泄漏的风险
调试CCCrypt
下面我们通过断点调试来说明其安全隐患
作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发交流群:130595548,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!(群内会免费提供一些群主收藏的免费学习书籍资料以及整理好的几百道面试题和答案文档!)
有以下的改进建议
总结