分享源码,让苦逼的开发生活见鬼去。
数据的加解密。后续补充用户数据的加密存储以及数据存储管理。
1.AES加密(对称加密)
特点:
优点:简单、可并行计算、误差不传递
缺点:不能隐藏明文模式(比如图像加密轮廓仍在)、主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
用途:需要并行加密的应用
AES加密算法是密码学中的高级加密标准,该加密算法采用对称分组密码体制,密钥长度的最少支持为128、192、256,分组长度128位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的区块加密标准,这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。AES加密算法被设计为支持128/192/256位(/32=nb)数据块大小(即分组长度);支持128/192/256位(/32=nk)密码长度,,在10进制里,对应34×1038、62×1057、1.1×1077个密钥
AES加密的原理可以百度,这里就不详细说明了,下面进入开发正题
NSData+AES.m 文件
//
// NSData+AES.m
// Encryption
//
// Created by llyouss on 16/10/16.
// Copyright © 2016年 llyouss. All rights reserved.
//
#import "NSData+AES.h"
#import <CommonCrypto/CommonCryptor.h>
@implementation NSData (AES)
- (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;
}
#import <CommonCrypto/CommonCryptor.h>
@end
由于字符集冲突,我们先nsdata
或base64位编码的形式存下来,否则会出现乱码。
调用事例
导入#import "SecurityUtil.h"
-(void)AESEncryption{
NSString *testString = @"AESllyouss";
NSLog(@"BASE64:%@", [SecurityUtil encodeBase64String:testString]);
NSLog(@"MD5:%@", [SecurityUtil encryptMD5String:testString]);
NSData *aesData = [SecurityUtil encryptAESData:testString];
NSLog(@"AES加密:%@", aesData);
NSLog(@"AES解密:%@", [SecurityUtil decryptAESData:aesData]);
}
2.DES加密(对称加密)
//des解密
+ (NSData *)DESDecrypt:(NSData *)data WithKey:(NSString *)key
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[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, kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeDES,
NULL,
[data bytes], dataLength,
buffer, bufferSize,
&numBytesDecrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer);
return nil;
}
//des加密
+ (NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key
{
char keyPtr[kCCKeySizeAES256+1];
bzero(keyPtr, sizeof(keyPtr));
[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, kCCAlgorithmDES,
kCCOptionPKCS7Padding | kCCOptionECBMode,
keyPtr, kCCBlockSizeDES,
NULL,
[data bytes], dataLength,
buffer, bufferSize,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free(buffer);
return nil;
}
3.BASE64编码
其实base64编解码方式使用系统的api已经很方便,但是还是喜欢现成的。
下载GTMBase64文件,在工程中加入三个文件
GTMDefines.h
GTMBase64.h
GTMBase64.m
下载地址:点击打开链接
封装一下
//
// SecurityUtil.m
// Encryption
//
// Created by llyouss on 16/10/16.
// Copyright © 2016年 llyouss. All rights reserved.
//
#import "SecurityUtil.h"
#import "GTMBase64.h"
#import "NSData+AES.h"
#import "NSString+MD5.h"
#define APP_PUBLIC_PASSWORD @"boundary"
@implementation SecurityUtil
#pragma mark - base64
+ (NSString*)encodeBase64String:(NSString * )input {
NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
data = [GTMBase64 encodeData:data];
NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ;
return base64String;
}
+ (NSString*)decodeBase64String:(NSString * )input {
NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
data = [GTMBase64 decodeData:data];
NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return base64String;
}
+ (NSString*)encodeBase64Data:(NSData *)data {
data = [GTMBase64 encodeData:data];
NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return base64String;
}
+ (NSString*)decodeBase64Data:(NSData *)data {
data = [GTMBase64 decodeData:data];
NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return base64String;
}
<span style="font-family:SimSun;"> </span>
4.MD5
MD5是哈希算法,作用大家都应该知道,加密非常简单直接上方法
- (NSString *)md5Encrypt {
const char *cStr = [self UTF8String];
unsigned char result[16];
CC_MD5( cStr, (int)strlen(cStr), result );
NSMutableString *hash = [NSMutableString string];
for (int i = 0; i < 16; i++)
[hash appendFormat:@"%02X", result[i]];
return [hash lowercaseString];
}
5.sha1&sha256加密
MD5目前发现了重复,目前最新的是sha256,具体作用大家都应该知道。
//sha256加密方式
- (NSString *)Sha256String:(NSString *)srcString {
const char *cstr = [srcString cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:srcString.length];
uint8_t digest[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(data.bytes, data.length, digest);
NSMutableString* result = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
[result appendFormat:@"%02x", digest[i]];
}
return result;
}
- (NSString *)sha1Encrypt{
const char *cstr = [self UTF8String];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (int)data.length, digest);
NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x", digest[i]];
return output;
}
6.RSA加密(非对称加密)
特点
RSA加密算法是目前最有影响力的公钥加密算法,并且被普遍认为是目前最优秀的公钥方案之一。RSA是第一个能同时用于加密和数宇签名的算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推荐为公钥数据加密标准。RSA加密算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
使用openssl实现,可以在这下载:点击打开链接
1.生成RSA密钥
* 生成RSA私钥
openssl genrsa -out rsa_private_key.pem 1024
* 生成RSA公钥
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
pem文件可以直接文本编辑器打开
将RSA私钥转换成PKCS8格式
openssl pkcs8 -topk8 -inform PEM -in private_rsa.pem -outform PEM -nocrypt -out private_key.pem (后边一定要加-out private_key.pem将转换后的私钥保存在private_key.pem,不然得到的结果要设置密码且显示在终端中,这个和得到pem中的私钥有差异。)
2.导入OpenSSL,导入HBRSAHandler裤文件
小技巧:记得在headSearchpath设置路径,不然编译报错。
HBRSAHandler.m 文件
//
// HBRSAHandler.m
// iOSRSAHandlerDemo
//
// Created by wangfeng on 15/10/19.
// Copyright (c) 2015年 HustBroventure. All rights reserved.
//
#import "HBRSAHandler.h"
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/md5.h>
typedef enum {
RSA_PADDING_TYPE_NONE = RSA_NO_PADDING,
RSA_PADDING_TYPE_PKCS1 = RSA_PKCS1_PADDING,
RSA_PADDING_TYPE_SSLV23 = RSA_SSLV23_PADDING
}RSA_PADDING_TYPE;
#define PADDING RSA_PADDING_TYPE_PKCS1
@implementation HBRSAHandler
{
RSA* _rsa_pub;
RSA* _rsa_pri;
}
#pragma mark - public methord
-(BOOL)importKeyWithType:(KeyType)type andPath:(NSString *)path
{
BOOL status = NO;
const char* cPath = [path cStringUsingEncoding:NSUTF8StringEncoding];
FILE* file = fopen(cPath, "rb");
if (!file) {
return status;
}
if (type == KeyTypePublic) {
_rsa_pub = NULL;
if((_rsa_pub = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL))){
status = YES;
}
}else if(type == KeyTypePrivate){
_rsa_pri = NULL;
if ((_rsa_pri = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL))) {
status = YES;
}
}
fclose(file);
return status;
}
- (BOOL)importKeyWithType:(KeyType)type andkeyString:(NSString *)keyString
{
if (!keyString) {
return NO;
}
BOOL status = NO;
BIO *bio = NULL;
RSA *rsa = NULL;
bio = BIO_new(BIO_s_file());
NSString* temPath = NSTemporaryDirectory();
NSString* rsaFilePath = [temPath stringByAppendingPathComponent:@"RSAKEY"];
NSString* formatRSAKeyString = [self formatRSAKeyWithKeyString:keyString andKeytype:type];
BOOL writeSuccess = [formatRSAKeyString writeToFile:rsaFilePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
if (!writeSuccess) {
return NO;
}
const char* cPath = [rsaFilePath cStringUsingEncoding:NSUTF8StringEncoding];
BIO_read_filename(bio, cPath);
if (type == KeyTypePrivate) {
rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, "");
_rsa_pri = rsa;
if (rsa != NULL && 1 == RSA_check_key(rsa)) {
status = YES;
} else {
status = NO;
}
}
else{
rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
_rsa_pub = rsa;
if (rsa != NULL) {
status = YES;
} else {
status = NO;
}
}
BIO_free_all(bio);
[[NSFileManager defaultManager] removeItemAtPath:rsaFilePath error:nil];
return status;
}
#pragma mark RSA sha1验证签名
//signString为base64字符串
- (BOOL)verifyString:(NSString *)string withSign:(NSString *)signString
{
if (!_rsa_pub) {
NSLog(@"please import public key first");
return NO;
}
const char *message = [string cStringUsingEncoding:NSUTF8StringEncoding];
int messageLength = (int)[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSData *signatureData = [[NSData alloc]initWithBase64EncodedString:signString options:0];
unsigned char *sig = (unsigned char *)[signatureData bytes];
unsigned int sig_len = (int)[signatureData length];
unsigned char sha1[20];
SHA1((unsigned char *)message, messageLength, sha1);
int verify_ok = RSA_verify(NID_sha1
, sha1, 20
, sig, sig_len
, _rsa_pub);
if (1 == verify_ok){
return YES;
}
return NO;
}
#pragma mark RSA MD5 验证签名
- (BOOL)verifyMD5String:(NSString *)string withSign:(NSString *)signString
{
if (!_rsa_pub) {
NSLog(@"please import public key first");
return NO;
}
const char *message = [string cStringUsingEncoding:NSUTF8StringEncoding];
// int messageLength = (int)[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSData *signatureData = [[NSData alloc]initWithBase64EncodedString:signString options:0];
unsigned char *sig = (unsigned char *)[signatureData bytes];
unsigned int sig_len = (int)[signatureData length];
unsigned char digest[MD5_DIGEST_LENGTH];
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, message, strlen(message));
MD5_Final(digest, &ctx);
int verify_ok = RSA_verify(NID_md5
, digest, MD5_DIGEST_LENGTH
, sig, sig_len
, _rsa_pub);
if (1 == verify_ok){
return YES;
}
return NO;
}
- (NSString *)signString:(NSString *)string
{
if (!_rsa_pri) {
NSLog(@"please import private key first");
return nil;
}
const char *message = [string cStringUsingEncoding:NSUTF8StringEncoding];
int messageLength = (int)strlen(message);
unsigned char *sig = (unsigned char *)malloc(256);
unsigned int sig_len;
unsigned char sha1[20];
SHA1((unsigned char *)message, messageLength, sha1);
int rsa_sign_valid = RSA_sign(NID_sha1
, sha1, 20
, sig, &sig_len
, _rsa_pri);
if (rsa_sign_valid == 1) {
NSData* data = [NSData dataWithBytes:sig length:sig_len];
NSString * base64String = [data base64EncodedStringWithOptions:0];
free(sig);
return base64String;
}
free(sig);
return nil;
}
- (NSString *)signMD5String:(NSString *)string
{
if (!_rsa_pri) {
NSLog(@"please import private key first");
return nil;
}
const char *message = [string cStringUsingEncoding:NSUTF8StringEncoding];
//int messageLength = (int)strlen(message);
unsigned char *sig = (unsigned char *)malloc(256);
unsigned int sig_len;
unsigned char digest[MD5_DIGEST_LENGTH];
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, message, strlen(message));
MD5_Final(digest, &ctx);
int rsa_sign_valid = RSA_sign(NID_md5
, digest, MD5_DIGEST_LENGTH
, sig, &sig_len
, _rsa_pri);
if (rsa_sign_valid == 1) {
NSData* data = [NSData dataWithBytes:sig length:sig_len];
NSString * base64String = [data base64EncodedStringWithOptions:0];
free(sig);
return base64String;
}
free(sig);
return nil;
}
- (NSString *) encryptWithPublicKey:(NSString*)content
{
if (!_rsa_pub) {
NSLog(@"please import public key first");
return nil;
}
int status;
int length = (int)[content length];
unsigned char input[length + 1];
bzero(input, length + 1);
int i = 0;
for (; i < length; i++)
{
input[i] = [content characterAtIndex:i];
}
NSInteger flen = [self getBlockSizeWithRSA_PADDING_TYPE:PADDING andRSA:_rsa_pub];
char *encData = (char*)malloc(flen);
bzero(encData, flen);
status = RSA_public_encrypt(length, (unsigned char*)input, (unsigned char*)encData, _rsa_pub, PADDING);
if (status){
NSData *returnData = [NSData dataWithBytes:encData length:status];
free(encData);
encData = NULL;
//NSString *ret = [returnData base64EncodedString];
NSString *ret = [returnData base64EncodedStringWithOptions: NSDataBase64Encoding64CharacterLineLength];
return ret;
}
free(encData);
encData = NULL;
return nil;
}
- (NSString *) decryptWithPrivatecKey:(NSString*)content
{
if (!_rsa_pri) {
NSLog(@"please import private key first");
return nil;
} int status;
//NSData *data = [content base64DecodedData];
NSData *data = [[NSData alloc]initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];
int length = (int)[data length];
NSInteger flen = [self getBlockSizeWithRSA_PADDING_TYPE:PADDING andRSA:_rsa_pri];
char *decData = (char*)malloc(flen);
bzero(decData, flen);
status = RSA_private_decrypt(length, (unsigned char*)[data bytes], (unsigned char*)decData, _rsa_pri, PADDING);
if (status)
{
NSMutableString *decryptString = [[NSMutableString alloc] initWithBytes:decData length:strlen(decData) encoding:NSASCIIStringEncoding];
free(decData);
decData = NULL;
return decryptString;
}
free(decData);
decData = NULL;
return nil;
}
- (int)getBlockSizeWithRSA_PADDING_TYPE:(RSA_PADDING_TYPE)padding_type andRSA:(RSA*)rsa
{
int len = RSA_size(rsa);
if (padding_type == RSA_PADDING_TYPE_PKCS1 || padding_type == RSA_PADDING_TYPE_SSLV23) {
len -= 11;
}
return len;
}
-(NSString*)formatRSAKeyWithKeyString:(NSString*)keyString andKeytype:(KeyType)type
{
NSInteger lineNum = -1;
NSMutableString *result = [NSMutableString string];
if (type == KeyTypePrivate) {
[result appendString:@"-----BEGIN PRIVATE KEY-----\n"];
lineNum = 79;
}else if(type == KeyTypePublic){
[result appendString:@"-----BEGIN PUBLIC KEY-----\n"];
lineNum = 76;
}
int count = 0;
for (int i = 0; i < [keyString length]; ++i) {
unichar c = [keyString characterAtIndex:i];
if (c == '\n' || c == '\r') {
continue;
}
[result appendFormat:@"%c", c];
if (++count == lineNum) {
[result appendString:@"\n"];
count = 0;
}
}
if (type == KeyTypePrivate) {
[result appendString:@"\n-----END PRIVATE KEY-----"];
}else if(type == KeyTypePublic){
[result appendString:@"\n-----END PUBLIC KEY-----"];
}
return result;
}
@end
调用事例
导入#import "HBRSAHandler.h"
@implementation ViewController
{
HBRSAHandler* _handler;
}
NSString* private_key_string = @"MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAOn0Mx9WBXbQYr55JsLKHdai1kO/iyA89YqUY3K0PK/YcCqsDNJ8y1VZQ4MBA4er6yr1LR3kSe6z6uux4oP2N4FHuV/BKM/MEkb0oyEKnuOXspOumOZ3Hn/CzpYSZSIAr5BgfADEUU9yfr+nTNIxW5sXh4bZmy3lRsSAKqeinmA9AgMBAAECgYEAxB/va2mVkxEGdl7h25HMic5giNLeMtxnixDyfYoTBecPwPYSmbH8U0RNkFkdOHMq5gw7Ej/6qp0xZvzsw2t5AtFmuAXjt1LS64ofsnbjxgKVYdMsLIn0jFSRt/riyvZLNEpNEwpbGb2Y1M9gCPHmBPU2CMgbKWvkiYquNCIVmoECQQD1wqXLRHY475AL/2AwAIUxGYeVdccL4qsDbsoUZNfaVC5iCvfgzArIg+xX4+XtKnuyuFFrRQWCVbgrsKGSn+6ZAkEA87OfAaKuRmPwMtyd4EY5GBhiOWQinWKIV9PkwozL+wyylHAdfKnMnCzglHFm5hdB+MkHs2R70R+U9DW82Vs5RQJAf+obH0x3+DSAli4Ko5FxwdeW4W0W+BG3jybYGXtPejz8k11AHYo2Rp2bozdkUmgdUC1te1bGgksZe+wIfOevaQJAU838KyrPdYNekY8Od5aOgbu443WM9cRxkIpci46xgsauDp+zdDBMHZTNMh8BPLTYyf4PuOAgOBz9MzHbnH9jZQJBAJKvVlrN3tehLIjBjzK1gfgqzIXDMZM/XkBVz8SIbz5SbeouGKCvGcSjLqD+CCFSdr8fP1EjQ0SiEwfpCpUHBcs=";
NSString* public_key_string = @"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDp9DMfVgV20GK+eSbCyh3WotZDv4sgPPWKlGNytDyv2HAqrAzSfMtVWUODAQOHq+sq9S0d5Enus+rrseKD9jeBR7lfwSjPzBJG9KMhCp7jl7KTrpjmdx5/ws6WEmUiAK+QYHwAxFFPcn6/p0zSMVubF4eG2Zst5UbEgCqnop5gPQIDAQAB";
//RSA加密/签名
-(void)RSAEncryptionAndDigest{
HBRSAHandler* handler = [HBRSAHandler new];
[handler importKeyWithType:KeyTypePrivate andkeyString:private_key_string];
[handler importKeyWithType:KeyTypePublic andkeyString:public_key_string];
_handler = handler;
// 加密
NSString*str=@"RSAllyouss";
NSData *nsdata = [str dataUsingEncoding:NSUTF8StringEncoding];
// Get NSString from NSData object in Base64
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
NSString* enString = [handler encryptWithPublicKey:base64Encoded];
NSLog(@"RSA加密:%@", enString);
// 解密
NSString* deString = [handler decryptWithPrivatecKey:enString];
NSData *nsdataFromBase64String = [[NSData alloc]
initWithBase64EncodedString:deString options:0];
NSLog(@"RSA解密:%@", deString);
// Decoded NSString from the NSData
NSString *base64Decoded = [[NSString alloc]
initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding];
NSLog(@"%@",base64Decoded);
// MD5签名
NSString* sigMd5 = [handler signMD5String:enString];
NSLog(@"%@ ",sigMd5);
// MD5验签
BOOL isMatchMd5 = [handler verifyMD5String:enString withSign:sigMd5];
NSLog(@"%d ",isMatchMd5);
}
可能写得不够详细,弄个demo大家一目了然了。加解密demo