美文网首页OC开发网络及安全iOS学习开发
iOS开发_AES加密和解密算法的实现

iOS开发_AES加密和解密算法的实现

作者: CN_HarrySun | 来源:发表于2017-02-23 19:34 被阅读656次

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。
iOS开发之Objective-c的AES加密和解密算法的实现

Rijndael密码的设计力求满足以下3条标准:
1. 抵抗所有已知的攻击。
2. 在多个平台上速度快,编码紧凑。
3. 设计简单。

当前的大多数分组密码,其轮函数是Feistel结构。Rijndael没有这种结构。

1.NSData加密

NSData+AES256.h中
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>

@interface NSData (AES256)


-(NSData *) aes256_encrypt:(NSString *)key;
-(NSData *) aes256_decrypt:(NSString *)key;

@end
NSData+AES256.m中
#import "NSData+AES256.h"

@implementation NSData (AES256)

// 加密
- (NSData *)aes256_encrypt:(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 cryptStatus1 = CCCrypt(<#CCOperation op#>, <#CCAlgorithm alg#>, <#CCOptions options#>, <#const void *key#>, <#size_t keyLength#>, <#const void *iv#>, <#const void *dataIn#>, <#size_t dataInLength#>, <#void *dataOut#>, <#size_t dataOutAvailable#>, <#size_t *dataOutMoved#>)
    
    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 *)aes256_decrypt:(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;
}

@end

2.NSString加密

NSString+AES256.h中
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>

#import "NSData+AES256.h"

@interface NSString (AES256)

-(NSString *) aes256_encrypt:(NSString *)key;
-(NSString *) aes256_decrypt:(NSString *)key;

@end
NSString+AES256.m中
#import "NSString+AES256.h"

@implementation NSString (AES256)


// 加密
- (NSString *) aes256_encrypt:(NSString *)key{
    
    const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
    NSData *data = [NSData dataWithBytes:cstr length:self.length];
    //对数据进行加密
    NSData *result = [data aes256_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;
}


// 解密
-(NSString *) aes256_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 aes256_decrypt:key];
    if (result && result.length > 0) {
        
        return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
    }
    return nil;
}

@end

3.加密、解密的使用

NSString *userName = @"userName:Coder_Sun";
NSLog(@"加密前的字符串:%@",userName);


NSString *string = [userName aes256_encrypt:@"Coder"];
NSLog(@"加密后的字符串:%@",string);
NSLog(@"%lu",(unsigned long)string.length); // 打印加密后的字符串的位数


NSString *string1 = [string aes256_decrypt:@"Coder"];
NSLog(@"解密后的字符串:%@",string1);
上述代码打印结果
代码已经上传至git:
--> 传送门:https://github.com/272095249/AES.git

补充:

加密算法原理:

AES算法基于排列和置换运算。排列是对数据重新进行安排,置换是将一个数据单元替换为另一个。AES 使用几种不同的方法来执行排列和置换运算。
AES是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据的位数与输入数据相同

加密模式:

| 加密模式 | 优点 | 缺点 |
| ------------- |::-------------:|: -------------:|
| ECB模式 | <ol><li>简单</li><li> 有利于并行计算</li><li>误差不会被传送</li></ol>|<ol><li>不能隐藏明文的模式</li><li> 可能对明文进行主动攻击</li></ol>|
| CBC模式 | <ol><li>不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准</li><ol> |<ol><li>不利于并行计算</li><li>误差传递</li><li>需要初始化向量IV</li></ol>|
| CFB模式 | <ol><li>隐藏了明文模式</li><li>分组密码转化为流模式</li><li>可以及时加密传送小于分组的数据</li></ol>|<ol><li>不利于并行计算</li><li>误差传送:一个明文单元损坏影响多个单元</li><li>唯一的IV</li>|
| ofb模式 |<ol><li>隐藏了明文模式</li><li>分组密码转化为流模式</li><li>可以及时加密传送小于分组的数据</li></ol>|<ol><li>不利于并行计算</li><li>对明文的主动攻击是可能的</li><li>误差传送:一个明文单元损坏影响多个单元</li></ol>|

相关文章

网友评论

  • 张囧瑞:请问下,这个代码里写的不是128位的加密么?为啥名字是256位的?
  • 夏日里的夏天:请问一下,字符串过长导致加密过程中数据丢失一部分,怎么解决?
    CN_HarrySun:@夏日里的夏天 :flushed: 解决了就好~
    夏日里的夏天:@Coder_Sun 解决了,中文字节长度的问题。
    CN_HarrySun:你使用的加密方式是什么?

本文标题:iOS开发_AES加密和解密算法的实现

本文链接:https://www.haomeiwen.com/subject/fszvwttx.html