简介

AES是加密的算法,使用128、192 和 256 位密钥,将被加密数据划分为128位(16字节)一块,然后使用某种加密模式进行加密

关键词:
块大小:16字节
密钥长度:AES算法下,key的长度有三种:128、192和256 bits。
加密模式:AES属于块加密(Block Cipher),块加密中有CBC、ECB、CTR、OFB、CFB等几种工作模式。
填充模式:
NoPadding,数据长度不对齐时使用"\0"填充,否则不填充
PKCS7Padding,假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是n;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小
PKCS5Padding,PKCS7Padding的子集,块大小固定为8字节。 AES加密,如果输入是16*n字节,NoPadding填充的情况下,输出和输入相同;有填充的情况下,输出是16*(n+1)。
如果输入不是16字节整数倍,而是大于16*n小于16*(n+1),NoPadding填充情况下(只能是CFB和OFB模式),输出和输入长度相同;其他情况下,输出长度是16*(n+1)

iOS系统库实现AES-CBC-PKCS7Padding 和 AES-ECB-PKCS7Padding

#import <CommonCrypto/CommonCrypto.h>
#import <CommonCrypto/CommonDigest.h>
//加密
+ (NSData *)encryptAES:(NSString *)content key:(NSString *)key {
NSData *contentData = [content dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger dataLength = contentData.length;
// 为结束符'\\0' +1
char keyPtr[kCCKeySizeAES128 + 1];
memset(keyPtr, 0, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
// 密文长度 <= 明文长度 + BlockSize
size_t encryptSize = dataLength + kCCBlockSizeAES128;
void *encryptedBytes = malloc(encryptSize);
size_t actualOutSize = 0;
NSString *const kInitVector = @"1234567890123456"; //16位偏移,CBC模式才有
NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding];
CCCryptorStatus cryptStatus = CCCrypt(
kCCEncrypt,//kCCEncrypt 代表加密 kCCDecrypt代表解密
kCCAlgorithmAES,//加密算法
kCCOptionPKCS7Padding, // 系统默认使用 CBC,然后指明使用 PKCS7Padding,iOS只有CBC和ECB模式,如果想使用ECB模式,可以这样编写 kCCOptionPKCS7Padding | kCCOptionECBMode
keyPtr,//公钥
kCCKeySizeAES128,//密钥长度128
initVector.bytes,//偏移字符串
contentData.bytes,//编码内容
dataLength,//数据长度
encryptedBytes,//加密输出缓冲区
encryptSize,//加密输出缓冲区大小
&actualOutSize);//实际输出大小
if (cryptStatus == kCCSuccess) {
// 返回编码后的数据
return [NSData dataWithBytesNoCopy:encryptedBytes length:actualOutSize];
}
free(encryptedBytes);
return nil;
}
// 解密
+ (NSData *)decryptAESWithData:(NSData *)data key:(NSString *)key{
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 *const kInitVector = @"1234567890123456"; //16位偏移,CBC模式才有
NSData *initVector = [kInitVector dataUsingEncoding:NSUTF8StringEncoding];
//字段含义在上面加密已经解释过了,这里不做赘述
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, keyPtr, kCCBlockSizeAES128, initVector.bytes, [data bytes], dataLength, buffer, bufferSize, &numBytesDecrypted); if(cryptStatus == kCCSuccess){
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
} free(buffer); return nil; }

OpenSSL库AES-CBC-PKCS7Padding 和 AES-ECB-PKCS7Padding

//pod引入openssl库
pod 'OpenSSL-Universal'
#import "crypto.h"
#import "evp.h"
#import "aes.h"
+ (NSData *)encryptStringWithString:(NSString *)string key:(NSString *)key{
const char *p_str = [string cStringUsingEncoding:NSUTF8StringEncoding];
const char *p_key = [key cStringUsingEncoding:NSUTF8StringEncoding]; unsigned char *p_out = malloc(string.length + 16);
memset(p_out, 0, string.length * 2);
int result = aes_encrypt(p_str, (char *)p_key, (unsigned char *)p_out); // NSLog(@"result = %d enOut = %s",result,p_out); NSInteger len = getlen(p_out);
NSData *data = [NSData dataWithBytes:p_out length:len];
return data;
}
+ (NSData *)decryptDataWithData:(NSData *)data andKey:(NSString *)key{
const char *p_key = [key cStringUsingEncoding:NSUTF8StringEncoding];
unsigned char *p_out = malloc(data.length*2);
memset(p_out, 0, data.length * 2); int result = aes_decrypt((const char *)data.bytes, (char *)p_key, p_out);
// NSLog(@"result = %d deOut = %s",result,p_out); NSInteger len = getlen(p_out);
NSData *dataOut = [NSData dataWithBytes:p_out length:len];
return dataOut;
}
/**********************************************************
函数名:PKCS7Padding
参数:unsigned char *str --字符串地址
返回值:int --正向测试填充后的字符串长度
说明:对初始数据进行PKCS7Padding填充
***********************************************************/
int PKCS7Padding(unsigned char *str){
int remain, i;
int len=getlen(str);
remain = 16 - len%16;
//printf("remain = %d\n",remain);
for(i=0; i<remain; i++)
{
str[len+i] = remain;
//printf("str[len+i]= %d\n",str[len+i]);
}
str[len+i] = '\0'; return len + remain;
}
/**********************************************************
函数名:DePKCS7Padding
参数:unsigned char *p --字符串地址
返回值:int --反填充个数
说明:对明文进行PKCS7Padding填充反填充(去除后面的填充乱码)
***********************************************************/
int DePKCS7Padding(unsigned char *str)
{
int remain,i;
while (*str != '\0'){str++;} //定位到\0
str--;
remain = *str;//读取填充的个数
//printf("remain = %d\n",remain);
//定位到最前面的填充数
for(i=0;i<remain;i++){str--;}
str++;
*str = '\0';//截断
return remain;
}
/**********************************************************
函数名:getlen
参数:char *result --字符串地址
返回值:int --字符串长度
说明: --获取字符串长度
***********************************************************/
int getlen(unsigned char *result){
int i = 0;
while (result[i] != '\0'){
i++;
}
return i;
} /**********************************************************
函数名:aes_encrypt
参数:const char* str_in --输入字符
参数:unsigned char* key --key
参数:unsigned char* out --输出字符
返回值:int --0失败 1成功
说明:加密
***********************************************************/
int aes_encrypt(const char* str_in, char* key, unsigned char* out)
{
OPENSSL_cleanse(NULL, 0);
if (!str_in || !key || !out) return 0; //加密的初始化向量
unsigned char iv[AES_BLOCK_SIZE]; //16位密码
char tmpIV[] = "1234567890123456";
for (int i = 0; i < 16; ++i)
iv[i] = tmpIV[i]; AES_KEY aes;
if (AES_set_encrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return 0;
} //
size_t len = strlen(str_in);
unsigned char *aes_encode_temp = malloc(len + 16);
memset(aes_encode_temp,'\0', len + 16);
memcpy(aes_encode_temp, str_in, len); len = PKCS7Padding(aes_encode_temp);
AES_cbc_encrypt((unsigned char*)aes_encode_temp, (unsigned char*)out, len, &aes, iv, AES_ENCRYPT); // for (int nIndex = 0; nIndex < getlen((char *)str_in); nIndex += 16) {
// AES_ecb_encrypt((unsigned char*)str_in + nIndex, (unsigned char*)out + nIndex,&aes,AES_ENCRYPT);
//    } return 1;
} /**********************************************************
函数名:aes_decrypt
参数:const char* str_in --输入
参数:unsigned char* key --key
参数:unsigned char* out --输出
返回值:int       --0失败 1成功
说明:                --解密
***********************************************************/
int aes_decrypt(const char* str_in, char* key,unsigned char* out)
{
OPENSSL_cleanse(NULL, 0);
if (!str_in || !key || !out) return 0;
unsigned char iv[AES_BLOCK_SIZE];//加密的初始化向量
char tmpIV[] = "1234567890123456";
for (int i = 0; i < 16; ++i)
iv[i] = tmpIV[i]; AES_KEY aes;
if (AES_set_decrypt_key((unsigned char*)key, 128, &aes) < 0)
{
return 0;
} size_t len = strlen(str_in); // for (int nIndex = 0; nIndex < getlen((char *)str_in); nIndex += 16) {
// AES_ecb_encrypt((unsigned char*)str_in + nIndex, (unsigned char*)out + nIndex,&aes,AES_DECRYPT);
// }
AES_cbc_encrypt((unsigned char*)str_in, (unsigned char*)out, len, &aes, iv, AES_DECRYPT);
DePKCS7Padding(out); return 1;
}

上述代码中,把AES-CBC-PKCS7的代码注释了。可自行解开注释得到此模式的加解密代码。

iOS AES-CBC、AES-ECB 加解密的更多相关文章

  1. 【iOS】FMDB/SQLCipher数据库加解密,迁移

    2016-04-19更新:本文代码可能有些问题,请移步 http://zhengbomo.github.io/2016-04-18/sqlcipher-start/ 查看 sqlite应用几乎在所有的 ...

  2. AES与RAS结合加解密方案

    import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyFactor ...

  3. 使用aespython进行ECB加解密示例

    CBC示例: from aespython import cbc_mode, key_expander, aes_cipher key = 'MluJMEZegVmrnWDaBiG1j7lqpkxNH ...

  4. iOS AES128 CBC No Padding加密解密

    最近的项目中数据传输用到加密,项目选择了AES128 CBC No Padding加密方式,PHP和Android方面的代码网上太多了.但是唯独没有iOS的,但是也有别的写法,但不是是AES128 C ...

  5. C# AESCBC256 与 java AESCBC256 加解密

    和某上市公司对接接口,他们试用 java AES CBC PKCS5 256 加解密.网上C# 基本不合适. 注意:C# PKCS7 对应 java PKCS5 /// <summary> ...

  6. Java中的AES加解密工具类:AESUtils

    本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.constants.SysConsta ...

  7. Aes加解密,php

    Aes类库 <?php namespace Aes; class Aes { /** * var string $method 加解密方法,可通过openssl_get_cipher_metho ...

  8. React中的AES加解密请求

    引言 在我们使用React开发Web前端的时候,如果是比较大的项目和正常的项目的话,我们必然会用到加解密,之前的文章中提到.NET的一些加解密,那么,这里我就模拟一个例子: 1.后台开发API接口,但 ...

  9. php实现AES/CBC/PKCS5Padding加密解密(又叫:对称加密)

    今天在做一个和java程序接口的架接,java那边需要我这边(PHP)对传过去的值进行AES对称加密,接口返回的结果也是加密过的(就要用到解密),然后试了很多办法,也一一对应了AES的key密钥值,偏 ...

随机推荐

  1. npm学习(七)之如何发布包、更新发布包、删除发布包

    前言 我们经常使用npm来下载别人的模块或者说包,那么我们如何将自己写的模块上传到npm呢? 了解npm政策 在开始之前,最好回顾一下npm的政策,以防您对站点礼仪.命名.许可或其他指导原则有疑问. ...

  2. volatile关键字?MESI协议?指令重排?内存屏障?这都是啥玩意

    一.摘要 三级缓存,MESI缓存一致性协议,指令重排,内存屏障,JMM,volatile.单拿一个出来,想必大家对这些概念应该有一定了解.但是这些东西有什么必然的联系,或者他们之间究竟有什么前世今生想 ...

  3. 优雅的swiper实例

    swiper实例 <!DOCTYPE html> <html lang="en"> <head> <meta name="vie ...

  4. php强大的filter过滤用户输入

    <?php $filters = array //定义过滤的数组 ( "name" => array ( "filter"=>FILTER_S ...

  5. 人工智能AI从入门到精通所有视频教程(140G)以及数据资料免费拿

    包含了人工智能AI从入门到精通所有视频教程(140G). 资料获取方式,关注公总号RaoRao1994,查看往期精彩-所有文章,即可获取资源下载链接 更多资源获取,请关注公总号RaoRao1994

  6. java面试题全集(下)

      这部分主要是开源Java EE框架方面的内容,包括Hibernate.MyBatis.Spring.Spring MVC等,由于Struts 2已经是明日黄花,在这里就不讨论Struts 2的面试 ...

  7. 苹果预热 WWDC 2019

    Erika Hairston 是一位来自旧金山的 23 岁耶鲁大学毕业生,她的首款 app Zimela 刚刚上线.这款应用主要为了宣传科技行业的多样性.Hairston 设计的 Zimela 通过建 ...

  8. 三、Vue CLI-单页面

    一.单页面 代码如下: <template> <div class="header">{{title}}</div> </template ...

  9. windows pip使用国内源

    在这里我使用清华源来做示范 win+R 打开用户目录%HOMEPATH%,在此目录下创建 pip 文件夹,在 pip 目录下创建 pip.ini 文件, 内容如下, 在pip文件夹里新建的pip.in ...

  10. Jsoup抓取网页数据完成一个简易的Android新闻APP

    前言:作为一个篮球迷,每天必刷NBA新闻.用了那么多新闻APP,就想自己能不能也做个简易的新闻APP.于是便使用Jsoup抓取了虎扑NBA新闻的数据,完成了一个简易的新闻APP.虽然没什么技术含量,但 ...