在前面的文章中我有说过 AES 和 RSA 这两种加密方式, 正好在前段时间再项目中有使用到, 在这里再把这两种加密方式综合在一起写一下, 具体到他们的使用, 以及 RSA 各种加密文件的生成.
一: RSA 各种加密相关文件生成
1, 首先生成私钥 (1024)
$ openssl genrsa -out private_key.pem 1024
上面是生成了一个名为 private_key 的 pem 文件, 也就是我们的私钥文件, 他其实就是一个简单的 txt 文本文件而已.
2, 生成证书请求文件
$ openssl req -new -key private_key.pem -out rsacert.csr
上面命令中的 private_key.pem 就是我们的私钥文件, 你会根据它生成一份名为 rsacert 的 csr 文件, 当然这个名字是由你定义的. 回车之后他会提示你输入国家, 省份, mail 等信息, 当然你也可以什么都不填全部回车. 大致是下面图的信息:
通过上面的命令你有了一份 rsacert.csr 文件.
3, 生成证书并且签名, 我们设置有效期为 10 年, 当然这个时间也是你自己定义的
$ openssl x509 -req -days 3650 -in rsacert.csr -signkey private_key.pem -out rsacert.crt
4, 生成 iOS 要是用的公钥文件, 文件格式为 der 格式, 文件为 public_key.der (名字自己定义)
$ openssl x509 -outform der -in rsacert.crt -out public_key.der
5, 生成 iOS 要使用的私钥, 为 p12 格式 (名字写了 p.p12 这个自己定义)
$ openssl pkcs12 -export -out p.p12 -inkey private_key.pem -in rsacert.crt
这里我们需要自己注意的点: 这一步会提示给私钥文件设置密码, 直接输入想要设置密码即可, 然后敲回车, 然后再验证刚才设置的密码, 再次输入密码, 然后敲回车, 就可以验证了, 设置密码是因为在解密时, private_key.p12 文件需要和这里设置的密码配合使用, 因此需要牢记此密码. 具体的使用砸下面的代码中我们会展示出来怎么使用.
6, 要是单单的 iOS 加密所需要的文件我们在这里也就已经设置 OK 了, 但安卓一般在使用公钥的使用会用 pem 格式的公钥, 所以这里我们还是需要再处理一下, 在前面我们生成的公钥是 der 格式的, 我们在生成一份 pem 格式的:
$ openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout
7, 安卓或者 Java 的同学肯定也需要私钥验证配合我们退耳机数据的, 但他们需要的私钥都是 PKCS8 格式的, 所以我们还需要把我们 pem 格式的私钥转成 PKCS8 格式的:
$ openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt
通过上面的这么多步, 我们需要的各种格式的文件我们就都创建完成了. 大概如下图所示:
二: 准备完成, 解释一下为什么要配合使用
说说为什么要他们配合使用:
要是我们单纯的使用 AES,AES 都知道是对称性加密, 对称性的意思就是说加密和解密用的是同一个 KEY, 当我们移动端把数据加密完的时候我们把数据传给后端, 这时候后端要想解开这个加密的数据就需要知道你是用什么 KEY 加密的, 这时候可能有同学会想, 那我们和后端定义相同的 KEY 不就 OK 了吗, 嗯.... 那后端的 KEY 就保存在哎服务器, 移动端的呢? 写在本地还是去服务端请求? 都不可以. 因为用过这两种方式那安全性就没办法保证了. 你写在本地的可以反编译你的代码, 要是去服务端请求那就能被人劫持, 只要知道了这个 KEY 那你的加密就变得毫无意义! 但至少我们知道了一点, 这个 KEY 很重要!
很重要那我们该怎么处理呢, 这时候就回到我们前面说的正题, AES 和 RSA 配合使用, 这个 KEY 的安全性就通过我们的 RSA 非对对称性加密保证, 对称性就是加密解密要使用同一个 KEY, 非对称性可肯定就是加密和解密不能使用同一个 KEY 了, 那就是我们的公钥和私钥, 公钥加密私钥解密, 把我们的 KEY 通过公钥加密之后上传服务器, 服务端拿到之后通过私钥解密就拿到了 KEY, 再去解密我们的 AES 数据, 有同学会想, 前面说我们的 AES 的 KEY 可能会被劫持, 那加了密被劫持呢, 放心被劫持到的也是我们通过公钥加密的, 想要得知真正的 KEY 就得知道我们的私钥, 可私钥在我们服务端要想拿到除非有了间谍, 不然是没法解开真正的 KEY 的, 还有人可能会想, 我们使用公钥加密的 KEY 我们的公钥就要保存在我们移动端的本地了, 那别人拿到公钥之后会不会解开劫持得到的数据呢, 不会的, 因为公钥加密的只能用私钥解开.
三: 解释完成, 该上代码了
我们先看 RSA 加密的代码, 代码具体的都有注释, 使用时候需要我们注意的我们在下面说, 下面是这个. m 文件的代码:
- #import "RSAEncryptor.h"
- #import <Security/Security.h>
- @implementation RSAEncryptor
- static NSString *base64_encode_data(NSData *data){
- data = [data base64EncodedDataWithOptions:0];
- NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- return ret;
- }
- static NSData *base64_decode(NSString *str){
- NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
- return data;
- }
- #pragma mark - 使用'.der'公钥文件加密
- // 加密
- + (NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path{
- if (!str || !path) return nil;
- return [self encryptString:str publicKeyRef:[self getPublicKeyRefWithContentsOfFile:path]];
- }
- // 获取公钥
- + (SecKeyRef)getPublicKeyRefWithContentsOfFile:(NSString *)filePath{
- NSData *certData = [NSData dataWithContentsOfFile:filePath];
- if (!certData) {
- return nil;
- }
- SecCertificateRef cert = SecCertificateCreateWithData(NULL, (CFDataRef)certData);
- SecKeyRef key = NULL;
- SecTrustRef trust = NULL;
- SecPolicyRef policy = NULL;
- if (cert != NULL) {
- policy = SecPolicyCreateBasicX509();
- if (policy) {
- if (SecTrustCreateWithCertificates((CFTypeRef)cert, policy, &trust) == noErr) {
- SecTrustResultType result;
- if (SecTrustEvaluate(trust, &result) == noErr) {
- key = SecTrustCopyPublicKey(trust);
- }
- }
- }
- }
- if (policy) CFRelease(policy);
- if (trust) CFRelease(trust);
- if (cert) CFRelease(cert);
- return key;
- }
- + (NSString *)encryptString:(NSString *)str publicKeyRef:(SecKeyRef)publicKeyRef{
- if(![str dataUsingEncoding:NSUTF8StringEncoding]){
- return nil;
- }
- if(!publicKeyRef){
- return nil;
- }
- NSData *data = [self encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] withKeyRef:publicKeyRef];
- NSString *ret = base64_encode_data(data);
- return ret;
- }
- #pragma mark - 使用'.12'私钥文件解密
- // 解密
- + (NSString *)decryptString:(NSString *)str privateKeyWithContentsOfFile:(NSString *)path password:(NSString *)password{
- if (!str || !path) return nil;
- if (!password) password = @"";
- return [self decryptString:str privateKeyRef:[self getPrivateKeyRefWithContentsOfFile:path password:password]];
- }
- // 获取私钥
- + (SecKeyRef)getPrivateKeyRefWithContentsOfFile:(NSString *)filePath password:(NSString*)password{
- NSData *p12Data = [NSData dataWithContentsOfFile:filePath];
- if (!p12Data) {
- return nil;
- }
- SecKeyRef privateKeyRef = NULL;
- NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
- [options setObject: password forKey:(__bridge id)kSecImportExportPassphrase];
- CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
- OSStatus securityError = SecPKCS12Import((__bridge CFDataRef) p12Data, (__bridge CFDictionaryRef)options, &items);
- if (securityError == noErr && CFArrayGetCount(items)> 0) {
- CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
- SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
- securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
- if (securityError != noErr) {
- privateKeyRef = NULL;
- }
- }
- CFRelease(items);
- return privateKeyRef;
- }
- + (NSString *)decryptString:(NSString *)str privateKeyRef:(SecKeyRef)privKeyRef{
- NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
- if (!privKeyRef) {
- return nil;
- }
- data = [self decryptData:data withKeyRef:privKeyRef];
- NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- return ret;
- }
- #pragma mark - 使用公钥字符串加密
- /* START: Encryption with RSA public key */
- // 使用公钥字符串加密
- + (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{
- NSData *data = [self encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
- NSString *ret = base64_encode_data(data);
- return ret;
- }
- + (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
- if(!data || !pubKey){
- return nil;
- }
- SecKeyRef keyRef = [self addPublicKey:pubKey];
- if(!keyRef){
- return nil;
- }
- return [self encryptData:data withKeyRef:keyRef];
- }
- + (SecKeyRef)addPublicKey:(NSString *)key{
- NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
- NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];
- if(spos.location != NSNotFound && epos.location != NSNotFound){
- NSUInteger s = spos.location + spos.length;
- NSUInteger e = epos.location;
- NSRange range = NSMakeRange(s, e-s);
- key = [key substringWithRange:range];
- }
- key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
- key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
- key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
- key = [key stringByReplacingOccurrencesOfString:@"" withString:@""];
- // This will be base64 encoded, decode it.
- NSData *data = base64_decode(key);
- data = [self stripPublicKeyHeader:data];
- if(!data){
- return nil;
- }
- //a tag to read/write keychain storage
- NSString *tag = @"RSAUtil_PubKey";
- NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
- // Delete any old lingering key with the same tag
- NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
- [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
- [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
- [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
- SecItemDelete((__bridge CFDictionaryRef)publicKey);
- // Add persistent version of the key to system keychain
- [publicKey setObject:data forKey:(__bridge id)kSecValueData];
- [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)
- kSecAttrKeyClass];
- [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
- kSecReturnPersistentRef];
- CFTypeRef persistKey = nil;
- OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
- if (persistKey != nil){
- CFRelease(persistKey);
- }
- if ((status != noErr) && (status != errSecDuplicateItem)) {
- return nil;
- }
- [publicKey removeObjectForKey:(__bridge id)kSecValueData];
- [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
- [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
- [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
- // Now fetch the SecKeyRef version of the key
- SecKeyRef keyRef = nil;
- status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
- if(status != noErr){
- return nil;
- }
- return keyRef;
- }
- + (NSData *)stripPublicKeyHeader:(NSData *)d_key{
- // Skip ASN.1 public key header
- if (d_key == nil) return(nil);
- unsigned long len = [d_key length];
- if (!len) return(nil);
- unsigned char *c_key = (unsigned char *)[d_key bytes];
- unsigned int idx = 0;
- if (c_key[idx++] != 0x30) return(nil);
- if (c_key[idx]> 0x80) idx += c_key[idx] - 0x80 + 1;
- else idx++;
- // PKCS #1 rsaEncryption szOID_RSA_RSA
- static unsigned char seqiod[] =
- { 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
- 0x01, 0x05, 0x00 };
- if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
- idx += 15;
- if (c_key[idx++] != 0x03) return(nil);
- if (c_key[idx]> 0x80) idx += c_key[idx] - 0x80 + 1;
- else idx++;
- if (c_key[idx++] != '\0') return(nil);
- // Now make a new NSData from this buffer
- return ([NSData dataWithBytes:&c_key[idx] length:len - idx]);
- }
- + (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
- const uint8_t *srcbuf = (const uint8_t *)[data bytes];
- size_t srclen = (size_t)data.length;
- size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
- void *outbuf = malloc(block_size);
- size_t src_block_size = block_size - 11;
- NSMutableData *ret = [[NSMutableData alloc] init];
- for(int idx=0; idx<srclen; idx+=src_block_size){
- //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
- size_t data_len = srclen - idx;
- if(data_len> src_block_size){
- data_len = src_block_size;
- }
- size_t outlen = block_size;
- OSStatus status = noErr;
- status = SecKeyEncrypt(keyRef,
- kSecPaddingPKCS1,
- srcbuf + idx,
- data_len,
- outbuf,
- &outlen
- );
- if (status != 0) {
- NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
- ret = nil;
- break;
- }else{
- [ret appendBytes:outbuf length:outlen];
- }
- }
- free(outbuf);
- CFRelease(keyRef);
- return ret;
- }
- /* END: Encryption with RSA public key */
- #pragma mark - 使用私钥字符串解密
- /* START: Decryption with RSA private key */
- // 使用私钥字符串解密
- + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{
- if (!str) return nil;
- NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
- data = [self decryptData:data privateKey:privKey];
- NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
- return ret;
- }
- + (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{
- if(!data || !privKey){
- return nil;
- }
- SecKeyRef keyRef = [self addPrivateKey:privKey];
- if(!keyRef){
- return nil;
- }
- return [self decryptData:data withKeyRef:keyRef];
- }
- + (SecKeyRef)addPrivateKey:(NSString *)key{
- NSRange spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
- NSRange epos = [key rangeOfString:@"-----END RSA PRIVATE KEY-----"];
- if(spos.location != NSNotFound && epos.location != NSNotFound){
- NSUInteger s = spos.location + spos.length;
- NSUInteger e = epos.location;
- NSRange range = NSMakeRange(s, e-s);
- key = [key substringWithRange:range];
- }
- key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
- key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
- key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
- key = [key stringByReplacingOccurrencesOfString:@"" withString:@""];
- // This will be base64 encoded, decode it.
- NSData *data = base64_decode(key);
- data = [self stripPrivateKeyHeader:data];
- if(!data){
- return nil;
- }
- //a tag to read/write keychain storage
- NSString *tag = @"RSAUtil_PrivKey";
- NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
- // Delete any old lingering key with the same tag
- NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
- [privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
- [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
- [privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
- SecItemDelete((__bridge CFDictionaryRef)privateKey);
- // Add persistent version of the key to system keychain
- [privateKey setObject:data forKey:(__bridge id)kSecValueData];
- [privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
- kSecAttrKeyClass];
- [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
- kSecReturnPersistentRef];
- CFTypeRef persistKey = nil;
- OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
- if (persistKey != nil){
- CFRelease(persistKey);
- }
- if ((status != noErr) && (status != errSecDuplicateItem)) {
- return nil;
- }
- [privateKey removeObjectForKey:(__bridge id)kSecValueData];
- [privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
- [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
- [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
- // Now fetch the SecKeyRef version of the key
- SecKeyRef keyRef = nil;
- status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
- if(status != noErr){
- return nil;
- }
- return keyRef;
- }
- + (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
- // Skip ASN.1 private key header
- if (d_key == nil) return(nil);
- unsigned long len = [d_key length];
- if (!len) return(nil);
- unsigned char *c_key = (unsigned char *)[d_key bytes];
- unsigned int idx = 22; //magic byte at offset 22
- if (0x04 != c_key[idx++]) return nil;
- //calculate length of the key
- unsigned int c_len = c_key[idx++];
- int det = c_len & 0x80;
- if (!det) {
- c_len = c_len & 0x7f;
- } else {
- int byteCount = c_len & 0x7f;
- if (byteCount + idx> len) {
- //rsa length field longer than buffer
- return nil;
- }
- unsigned int accum = 0;
- unsigned char *ptr = &c_key[idx];
- idx += byteCount;
- while (byteCount) {
- accum = (accum <<8) + *ptr;
- ptr++;
- byteCount--;
- }
- c_len = accum;
- }
- // Now make a new NSData from this buffer
- return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
- }
- + (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
- const uint8_t *srcbuf = (const uint8_t *)[data bytes];
- size_t srclen = (size_t)data.length;
- size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
- UInt8 *outbuf = malloc(block_size);
- size_t src_block_size = block_size;
- NSMutableData *ret = [[NSMutableData alloc] init];
- for(int idx=0; idx<srclen; idx+=src_block_size){
- //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
- size_t data_len = srclen - idx;
- if(data_len> src_block_size){
- data_len = src_block_size;
- }
- size_t outlen = block_size;
- OSStatus status = noErr;
- status = SecKeyDecrypt(keyRef,
- kSecPaddingNone,
- srcbuf + idx,
- data_len,
- outbuf,
- &outlen
- );
- if (status != 0) {
- NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
- ret = nil;
- break;
- }else{
- //the actual decrypted data is in the middle, locate it!
- int idxFirstZero = -1;
- int idxNextZero = (int)outlen;
- for ( int i = 0; i <outlen; i++ ) {
- if ( outbuf[i] == 0 ) {
- if ( idxFirstZero < 0 ) {
- idxFirstZero = i;
- } else {
- idxNextZero = i;
- break;
- }
- }
- }
- [ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];
- }
- }
- free(outbuf);
- CFRelease(keyRef);
- return ret;
- }
- /* END: Decryption with RSA private key */
- @end
注意: 在我们使用 RSA 的 p12 文件解密的时候 也就是使用下面这个方法的时候:
+ (NSString *)decryptString:(NSString *)str privateKeyWithContentsOfFile:(NSString *)path password:(NSString *)password
使用到的 password 的这个参数就是我们给 p12 文件设置的密码. 这也是为什么前面我们说的你的记住这个密码的原因, 不然你只能重新生成了. 当然服务端解密的时候是不需要的.
path 这个参数就是你的 p12 文件在你本地的路径, 这个就自己写了.
四: AES 呢
首先的说说 AES 我们需要注意的几个点:
1, 加密位数 128 还是 256 的这个得几个端统一不能说你用 256 的服务端解的时候用 128 的.
2,IV 初始向量 这个也得统一, 一般 128 的加密位数使用 16 位的初始向量
3, 具体的 AES 加密代码的注释我在前面的博客中有写, 它里面参数的含义是什么都有说明, 这里就简单的看一下 128 加密代码, 要是想看这个加密方法的具体说明, 找一下以前的博客.
4,string 的加密解密还是归结到 data 的加密解密了, 先看 data 的加密解密:
- #import "NSData+AES.h"
- static NSString * const AES_IV = @"自己定义";
- @implementation NSData (AES)
- - (NSData *)aes128_encrypt:(NSString *)key // 加密
- {
- // kCCKeySizeAES256 是加密位数
- /*
- enum {
- kCCKeySizeAES128 = 16,
- kCCKeySizeAES192 = 24,
- kCCKeySizeAES256 = 32,
- kCCKeySizeDES = 8,
- kCCKeySize3DES = 24,
- kCCKeySizeMinCAST = 5,
- kCCKeySizeMaxCAST = 16,
- kCCKeySizeMinRC4 = 1,
- kCCKeySizeMaxRC4 = 512,
- kCCKeySizeMinRC2 = 1,
- kCCKeySizeMaxRC2 = 128,
- kCCKeySizeMinBlowfish = 8,
- kCCKeySizeMaxBlowfish = 56,
- };
- */
- char keyPtr[kCCKeySizeAES128+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,
- keyPtr, kCCBlockSizeAES128,
- [AES_IV UTF8String],
- [self bytes], dataLength,
- buffer, bufferSize,
- &numBytesEncrypted);
- if (cryptStatus == kCCSuccess) {
- return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
- }
- free(buffer);
- return nil;
- }
- - (NSData *)aes128_decrypt:(NSString *)key // 解密
- {
- char keyPtr[kCCKeySizeAES128+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 ,
- keyPtr, kCCBlockSizeAES128,
- [AES_IV UTF8String],
- [self bytes], dataLength,
- buffer, bufferSize,
- &numBytesDecrypted);
- if (cryptStatus == kCCSuccess) {
- return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
- }
- free(buffer);
- return nil;
- }
5,String 的加密解密 128 位的代码如下:
- // 利用 Key 加密字符串
- -(NSString *) aes_encrypt:(NSString *)key{
- const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
- NSData *data = [NSData dataWithBytes:cstr length:self.length];
- // 对数据进行加密
- NSData *result = [data aes128_encrypt:key];
- // 转换为 2 进制字符串
- 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;
- }
- return nil;
- }
- // 利用 Key 解密字符串
- -(NSString *) aes_decrypt:(NSString *)key{
- // 转换为 2 进制 Data
- NSMutableData *data = [NSMutableData dataWithCapacity:self.length / 2];
- unsigned char whole_byte;
- char byte_chars[3] = {'\0','\0','\0'};
- int i;
- for (i=0; i < [self length] / 2; i++) {
- byte_chars[0] = [self characterAtIndex:i*2];
- byte_chars[1] = [self characterAtIndex:i*2+1];
- whole_byte = strtol(byte_chars, NULL, 16);
- [data appendBytes:&whole_byte length:1];
- }
- // 对数据进行解密
- NSData* result = [data aes128_decrypt:key];
- if (result && result.length> 0) {
- return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
- }
- return nil;
- }
来源: https://www.cnblogs.com/zhangxiaoxu/p/10997099.html