终端演示
OpenSSL
以DES为例,列举
DES-ecb加密“message.txt”
message.txt内容如下:
helloworld
helloworld
helloworld
helloworld
helloworld
helloworld
$ openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg.bin
-enc 代表对称加密算法
-aes 表示算法;
-ecb 表示模式
-K 616263 表示密钥, 等同于小写的“abc”,为什么等于abc,ASCII码
-nosalt 不加盐
-out 输出
-msg.bin 输出的文件名字
DES加密“message1.txt”
message.txt内容如下:
helloworld
helloworld
helloworld
helloworle
helloworld
helloworld
$ openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg1.bin
利用命令xxd可以查看
$ xxd msg1.bin
观察图2,我们可以看到加密之后有哪些不同的地方。
DES-cbc加密“message.txt”
message.txt ,message1.txt 内容不变
message.txt生成msg3.bin:
$ openssl enc -des-cbc -iv 123456789 -K 616263 -nosalt -in message.txt -out msg3.bin
和ecb相比,多了一个参数iv
-iv 12345678 表示一个向量
现代密码学里面,都会和几何有关,几何里面的变化,都是有规律,结果又是多变的。
message1.txt生成msg4.bin:
$ openssl enc -des-cbc -iv 123456789 -K 616263 -nosalt -in message1.txt -out msg4.bin
观察图3,我们可以看到改变的数据之后,全部发生了变化。
这就是cbc,所有的加密都依赖于前面数据,一个地方改变,后续的所有数据都变了。
代码演示
(注:苹果给我们提供的对称加密算法有很多,在此仅以AES,DES为例)
苹果官方给出的枚举
enum {
/* AES */
kCCBlockSizeAES128 = 16,
/* DES */
kCCBlockSizeDES = 8,
/* 3DES */
kCCBlockSize3DES = 8,
/* CAST */
kCCBlockSizeCAST = 8,
kCCBlockSizeRC2 = 8,
kCCBlockSizeBlowfish = 8,
};
EncryptionTools.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
EncryptionTools.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 {
option = kCCOptionPKCS7Padding | kCCOptionECBMode;
}
// 设置输出缓冲区
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
size_t bufferSize = [data length] + self.blockSize;
void *buffer = malloc(bufferSize);
// 开始加密
size_t encryptedSize = 0;
//加密解密都是它 -- CCCrypt
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
演示例子:
/**
AES-ECB
*/
NSString *key = @"abc";//终端演示的时候,616263
NSString *encStrA = [[EncryptionTools sharedEncryptionTools]encryptString:@"hello" keyString:key iv:nil];//ECB没有向量,所以iv传nil
NSLog(@"AES-ECB加密的结果:%@",encStrA);
NSLog(@"AES-ECB解密的结果:%@",[[EncryptionTools sharedEncryptionTools] decryptString:encStrA keyString:key iv:nil]);
/**
AES-CBC
*/
uint8_t iv[8] = {1,2,3,4,5,6,7,8};
NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
NSString *encStrB = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:@"abc" iv:ivData];
NSLog(@"AES-CBC加密的结果:%@",encStrB);
NSLog(@"AES-CBC解密的结果:%@",[[EncryptionTools sharedEncryptionTools] decryptString:encStrB keyString:@"abc" iv:ivData]);
重点!
最最重要的一点,其中最重要的函数就是CCCrypt函数:
iOS--CCCrypt函数