iOS加密之AES

心急的童鞋直接看这里Demo
运行之后可以去在线加密网站验证

AES(Advanced Encryption Standard)高级加密标准,又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES

AES的五种加密模式

AES有五种加密模式(CBC、ECB、CTR、OCF、CFB)
1.电码本模式(Electronic Code Book (ECB))
2.密码分组链接模式(Cipher Block Chaining (CBC))
3.计算器模式(Counter (CTR))
4.密码反馈模式(Cipher FeedBack (CFB))
5.输出反馈模式(Output FeedBack (OFB))

在iOS用到的一般就是ECB和CBC两种。

ECB-电码本模式

ECB是最简单的块密码加密模式,加密前根据加密块大小(AES加密块固定为128位)分成若干块,之后将每块使用相同的密钥单独加密,所以加密块相同的明文会生成相同的密文。

CBC-密码分组链接模式

CBC模式对于每个待加密的密码块在加密前会先与前一个密码块的密文异或然后再用加密器加密。第一个明文块与一个叫初始化向量的数据块异或。

OK,最简单的理论理解了,就来看iOS最重要的干货:加解密函数CCCrypt

CCCrypt - 加解密函数

CCCryptorStatus CCCrypt(
    CCOperation op,         /* kCCEncrypt, etc. */
    CCAlgorithm alg,        /* kCCAlgorithmAES128, etc. */
    CCOptions options,      /* kCCOptionPKCS7Padding, etc. */
    const void *key,
    size_t keyLength,
    const void *iv,         /* optional initialization vector */
    const void *dataIn,     /* optional per op and alg */
    size_t dataInLength,
    void *dataOut,          /* data RETURNED here */
    size_t dataOutAvailable,
    size_t *dataOutMoved)

重要的参数说明:

  1. CCOperation op:加密kCCEncrypt,解密kCCDecrypt
  2. CCAlgorithm alg:加密算法,这里kCCAlgorithmAES128和kCCAlgorithmAES是一样的,AES加密块固定是128位,咱们常说的AES128、192、256加密只是加密秘钥的长度不同(当然加密处理轮数也不同,这里就不做说明了)
  3. CCOptions options:
    kCCOptionPKCS7Padding:填充模式
    kCCOptionECBMode:ECB模式
  4. size_t keyLength:参数是下面这些,看到很多博客不管是128还是256,这里都写kCCBlockSizeAES128,这是不对的,这样加密出来的其实还是128加密
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,
};
  1. iv:偏移向量,CBC模式下需要,不传默认16位0,ECB不需要
关于CCCrypt中的key和keyLength

AES数据块长度为128位,所以IV长度需要为16个字符(ECB模式不用IV),密钥根据指定密钥位数分别为16、24、32个字符,IV与密钥超过长度则截取,不足则在末尾填充'\0'补足

key和keyLength之间的关系,现在算是搞明白了,key就是咱们传入的密钥,keyLength是决定密钥长度的,也就是aes128,192,256的真正区别了,如果传入的key是32位,也就是256要求的位数,但是keyLength选择了kCCKeySizeAES128,那么真正的key其实是截取前面的16位,如果key传入16位,但是keyLength选择了kCCKeySizeAES256,那就是密钥位数不够,会自动补全到32位
虽然密钥长度不够的话会自动补齐或者截取,不过感觉还是传入正确的密钥比较好,128的keysize=16,192keysize=24,256keysize=32

好了,直接上代码
Demo
需要引入 #import <CommonCrypto/CommonCrypto.h>

AES256 ECB模式加密

+(NSData *)dataByAes256ECB:(NSData *)data key:(NSString *)key mode:(CCOperation)operation {
    char keyPtr[kCCKeySizeAES256 + 1];//选择aes256加密,所以key长度应该是kCCKeySizeAES256,32位
    bzero(keyPtr, sizeof(keyPtr));//清零
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];//秘钥key转成cString
    
    NSUInteger dataLength = data.length;
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    
    void * buffer = malloc(bufferSize);
    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding | kCCOptionECBMode,//ECB模式
                                          keyPtr,
                                          kCCKeySizeAES256,
                                          NULL,//选择ECB模式,不需要向量
                                          data.bytes,
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        NSData * result = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        return result;
    }
    free(buffer);
    return nil;
}

AES128 CBC模式加解密

+(NSData *)dataByAes128CBC:(NSData *)data key:(NSString *)key mode:(CCOperation)operation iv:(NSString *)iv {
    char keyPtr[kCCKeySizeAES128 + 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;
    
    NSString * initIv = iv;
    char ivPtr[kCCBlockSizeAES128+1];
    memset(ivPtr, 0, sizeof(ivPtr));
    [initIv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
    CCCryptorStatus cryptStatus = CCCrypt(operation,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding,
                                          keyPtr,
                                          kCCKeySizeAES128,
                                          ivPtr,
                                          data.bytes,
                                          dataLength,
                                          buffer,
                                          bufferSize,
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        NSData * result = [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        return result;
    }
    free(buffer);
    return nil;
}

在线验证

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 很久没写博客,Markdown牵出来遛遛 AES加密时需要统一的几个参数。 1.本例使用AES-128, 2.AE...
    ZIM东东阅读 1,901评论 0 1
  • 高级加密标准(英语:Advanced EncryptionStandard,缩写:AES),在密码学中又称Rijn...
    黄晓果阅读 11,124评论 0 2
  • AES是开发中常用的加密算法之一。然而由于前后端开发使用的语言不统一,导致经常出现前端加密而后端不能解密的情况出现...
    WelkinXie阅读 27,146评论 35 86
  • 古人云:久病成良医!究其根源,无外乎,别人的不适,自己皆有经历,推己及人,推人及己,一念悲心而已 漫长的求医,学医...
    SunnyGe阅读 193评论 0 0
  • 默认Library是隐藏的,隐藏显示文件夹参考Mac 终端命令 Xcode 代码片段-CodeSnippets 默...
    WeeverLu阅读 4,181评论 0 3