AES CBC和CTR加解密实例

AES(Advanced Encryption Standard,高级加密标准)又叫Rijndael加密法,用来替代DES算法。常见AES加密模式有ECB、CBC、CFB、OFB和CTR等五种, CFB、OFB都带反馈,做流加密用的多,CBC和CTR、ECB多用于独立block加密,由于ECB算法有点小缺点,所以CBC和CTR这两种加解密方式用的较多,也是很多标准规范要求的实现算法,下面看一下这两种算法原理。AES跟Rijndael相比有点小区别,就是使用固定块(block size)为128bits(16字节)(原Rijndael块大小更灵活),密钥长度支持128、192或256位。

一、AES CBC加解密原理

CBC加解密原理如下图所示(图片来源维基百科,参考文末地址):CBC加密原理:明文跟向量异或,再用KEY进行加密,结果作为下个BLOCK的初始化向量。解密原理:使用密钥先对密文解密,解密后再同初始向量异或得到明文。

CBC需要对明文块大小进行Padding(补位),由于前后加密的相关性,只能实施串行化动作,无法并行运算。另外,CBC需要参量:密钥和初始化向量。

二、AES CTR加解密原理

CTR加密原理:用密钥对输入的计数器加密,然后同明文异或得到密文。解密原理:用密钥对输入计数器加密,然后同密文异或得到明文。

CTR不需要Padding,而且采用了流密钥方式加解密,适合于并行运算,CTR涉及参量:Nounce随机数、Counter计数器和密钥。Nounce随机数和Counter计数器整体可看作计数器,因为只要算法约定好,就可以回避掉串行化运算。

三、AES CBC和CTR加解密实例

下文实例使用了第三方开源源码,官方网址:http://www.gladman.me.uk/, 本文测试源码来源:plushost.co.uk - ,测试时,如下源码文件需加入工程:aes_modes.c、aescrypt.c、aeskey.c、aestab.c。

测试源码如下:

#include <iostream>
#include <string>
#include <time.h>
	
#include "aes/aes.h"

typedef unsigned char  uint8;
typedef char           int8;
typedef unsigned short uint16;
typedef short          int16;
typedef unsigned int   uint32;
typedef int            int32;
	
typedef unsigned __int64 uint64;
typedef __int64          int64;
/******************************
For _LINUX
typedef long   long    int64;
typedef unsigned long  long  uint64;
******************************/
	
using namespace std;
	
//same as function rfc3686_inc
void ctr_inc(unsigned char ctr_buf[16])
{
    if(!(++(ctr_buf[15])))
        if(!(++(ctr_buf[14])))
            if(!(++(ctr_buf[13])))
                ++(ctr_buf[12]);
}
	
//same as function rfc3686_init
//4Bytes nounce+8Bytes iv+4Bytes counter
void ctr_init( unsigned char nonce[4], unsigned char iv[8], unsigned char ctr_buf[16])
{
    memcpy(ctr_buf, nonce, 4);
    memcpy(ctr_buf +  4, iv, 8);
    memset(ctr_buf + 12, 0, 4);
    ctr_inc(ctr_buf);
}
	
void print_hex(uint8* buf, uint64 len) {
    //Print results:
    for(int i=0;i<len;i++) {
        printf("%02X",buf[i]);
        if(15 == i%16)
            printf("\n");
    }
    printf("\n");
}
	
void main() {   
    uint8   key[]   = {0x10,0xa5,0x88,0x69,0xd7,0x4b,0xe5,0xa3,0x74,0xcf,   0x86,0x7c,0xfb,0x47,0x38,0x59};//AES::DEFAULT_KEYLENGTH
    uint8   buf[16];//tmp buffer
	
    uint8   msg[]   = "HelloWorld!23456";
    uint64  fsize=strlen((char*)msg);//message size
    uint8*  DataBuf=new uint8[1024];//Data Buffer


    //AES with CBC
    printf("AES with CBC\n");          
	     
    //Copy data
    memset(DataBuf,0,1024);
    strcpy((char*)DataBuf,(char*)msg);
    uint8* pDataBuf = DataBuf;//tmp pointer
    uint8   iv1[]   = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00,0x00,0x00};
	
    uint64  iEncryptTimes = fsize/16+1;
    uint8   iPaddings     = 16-fsize%16;//Padding size
    uint64  newlen = fsize+iPaddings;//New length
     
    //memcpy(DataBuf,iv,16);//Save iv
    memset(pDataBuf+fsize, iPaddings,iPaddings);//Padding
    printf("input   =\n");
    print_hex(DataBuf,newlen);
    aes_encrypt_ctx en_ctx[1];//Init encrypt
	     
    //Encrypt
    for(uint64 i=0;i<iEncryptTimes;i++) {
        aes_encrypt_key128(key,en_ctx);
	        aes_cbc_encrypt(pDataBuf,buf,16,iv1,en_ctx);//iv has been changed, ctx has been changed!!!
        memcpy(pDataBuf,buf,16);
        pDataBuf += 16;
    }
	     
    printf("encrypt =\n");
    print_hex(DataBuf,newlen);
     
    //Decrypt
    pDataBuf = DataBuf;
    uint8   iv2[]       = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00,0x00,0x00};
    uint8   buf3[256]={'\0'};
    aes_decrypt_ctx de_ctx[1];
    aes_decrypt_key128(key,de_ctx);
    aes_cbc_decrypt(pDataBuf,buf3,newlen,iv2,de_ctx);
     
    printf("decrypt =\n");
    print_hex(buf3,newlen);
     
    //================================

    printf("AES with CTR\n");          
    //Copy data
    memset(DataBuf,0,1024);
    strcpy((char*)DataBuf,(char*)msg);
    pDataBuf = DataBuf;//tmp pointer
    uint8   iv3[]   = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00,0x00,0x00};

    iEncryptTimes = fsize/16;
    uint8   iRemain       = fsize%16;
    uint8   ctr_buf[AES_BLOCK_SIZE];
	     
    //Save iv(as ctrl buffer)
    //memcpy(DataBuf,iv,16);
    printf("input   =\n");
    print_hex(DataBuf,fsize);
	     
    //Init encrypt
    //aes_encrypt_ctx en_ctx[1];
	     
    //Encrypt
    for(i=0;i<iEncryptTimes;i++) {
        aes_encrypt_key128(key,en_ctx);
        ctr_init(iv3,iv3+4,ctr_buf);//we set iv as the nouce
        aes_ctr_encrypt(pDataBuf,buf,16,ctr_buf,ctr_inc,en_ctx);//iv has been changed, ctx has been changed!!!
        memcpy(pDataBuf,buf,16);
        pDataBuf += 16;
    }
     
    if(iRemain!=0) {//last times
        pDataBuf += i*16;
        aes_encrypt_key128(key,en_ctx);
        ctr_init(iv3,iv3+4,ctr_buf);//we set iv as the nouce
        aes_ctr_encrypt(pDataBuf,buf,iRemain,ctr_buf,ctr_inc,en_ctx);//iv has been changed, ctx has been changed!!!
        memcpy(pDataBuf,buf,iRemain);
    }
     
    printf("encrypt =\n");
    print_hex(DataBuf,fsize);
	     
    //Decrypt
    pDataBuf = DataBuf;
    uint8   iv4[]       = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,   0x00,0x00,0x00,0x00,0x00,0x00};
    //uint8 buf3[256]={'\0'};
    //aes_decrypt_ctx de_ctx[1];
    //aes_decrypt_key128(key,de_ctx);
    aes_encrypt_key128(key,en_ctx);
    ctr_init(iv4,iv4+4,ctr_buf);//we set iv as the nouce
    aes_ctr_decrypt(pDataBuf,buf3,16,ctr_buf,ctr_inc,en_ctx);
    printf("decrypt =\n");
    print_hex(buf3,fsize);
     
    printf("\n");
}

输出如下(CBC未去掉Padding):

  • AES with CBC
  • input   =
  • 48656C6C6F576F726C64213233343536
  • 10101010101010101010101010101010
  • encrypt =
  • F928E09884AA2BA8CC4B73C09304250C
  • C9A0EEFF2295B5D83BEA0410001BD7C6
  • decrypt =
  • 48656C6C6F576F726C64213233343536
  • 10101010101010101010101010101010
  • AES with CTR
  • input   =
  • 48656C6C6F576F726C64213233343536
  • encrypt =
  • 1CA0978FE499969C769B6346D46B66F9
  • decrypt =
  • 48656C6C6F576F726C64213233343536

参考资料:

http://zh.wikipedia.org/wiki/高级加密标准

http://zh.wikipedia.org/zh/块密码的工作模式

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: AES (高级加密标准) 是一种对称密钥加密算法,而CBC (密码分组链接) 则是其中的一种模式。 AES CBC 128 是指使用128位的密钥长度进行AES加密,采用CBC模式。 在线AES CBC 128加解密通常需要使用一种工具或者平台,这样可以避免自己编写加解密算法的复杂性。以下是通过在线平台进行AES CBC 128加解密的基本步骤: 1. 打开所选择的在线AES CBC 128加解密平台。 2. 在加密选项中,选择AES CBC 128作为加密算法,并填入所需的参数。 3. 输入需加密的明文数据,在线平台上输入文本框中。 4. 提供用于加密的密钥,通常是128位二进制值或者是由用户输入的密码。确保密钥的安全性非常重要。 5. 输入初始化向量 (IV),是CBC模式所必需的。IV是一个固定长度的随机值,主要用于增加加密的强度。 6. 单击加密按钮来执行加密操作。 7. 在加密完成后,加密结果会在屏幕上显示出来。这是使用AES CBC 128算法加密后的密文。 在解密时,按照类似的步骤进行: 1. 打开相同的在线AES CBC 128加解密平台。 2. 选择解密选项中的AES CBC 128算法。 3. 输入需要解密的密文数据。 4. 提供正确的解密密钥 (与加密时使用的密钥一致)。 5. 输入相同的初始化向量 (IV)。 6. 单击解密按钮来执行解密操作。 7. 解密后的明文结果会在屏幕上显示出来。 需要注意的是,使用在线AES CBC 128加解密平台时,务必确保所用的平台是可信赖的,且具备相应的安全措施,以保护所处理的数据的机密性和完整性。同时,不应将加密和解密的密钥暴露给平台或其他人员,以确保数据的安全。 ### 回答2: AES CBC 128是一种对称加密算法,它使用128位的密钥进行加密和解密。CBC代表Cipher Block Chaining,它是一种块密码模式,通过将每个明文块与前一个密文块异或来增加密码的随机性。 AES CBC 128的在线加解密过程如下: 加密: 1. 首先,选择一个128位的密钥作为加密密钥。 2. 将明文分割成16字节(128位)的块。 3. 对第一个块进行加密,使用AES算法将明文与密钥进行异或运算。 4. 对第一个块的加密结果与第二个块进行异或运算,然后再对结果进行加密。 5. 依次对后续块进行异或和加密操作,直到最后一个块。 6. 输出加密后的密文。 解密: 1. 使用相同的密钥对密文进行解密。 2. 对第一个密文块进行解密,使用AES算法将密文与密钥进行异或运算。 3. 对解密的第一个块与下一个密文块进行异或运算,然后再对结果进行解密。 4. 依次对后续块进行异或和解密操作,直到最后一个密文块。 5. 输出解密后的明文。 需要注意的是,在CBC模式下,每个块的加密或解密操作都依赖于前一个块的结果,因此密文块的顺序是非常重要的。如果密文块的顺序发生变化或者丢失了某个块,解密操作将会失败。此外,在使用CBC模式进行加解密时,还需要使用一个随机生成的初始向量(IV)与第一个明文块进行异或操作,以增加密码的随机性和安全性。 综上所述,通过AES CBC 128的在线加解密过程,可以实现对数据的保护和安全传输。 ### 回答3: AES(Advanced Encryption Standard)是一种对称加密算法,CBC(Cipher Block Chaining)是一种分组模式。 AES CBC 128位的加密和解密都是在线进行的。在加密过程中,先将待加密的明文按照指定的分组长度(128位)进行分组。然后采用AES算法对每个分组进行加密处理;在加密过程中,需要引入一个初始向量(IV)来增加密码的随机性。 首先,将IV与第一个分组进行异或操作,然后再使用AES算法对其进行加密。接下来,将第一个分组的密文与第二个分组进行异或操作,再次使用密钥加密,以此类推。这样每个分组的密文都依赖于前一个密文和当前分组的明文。这种依赖关系可以增加加密的强度。 解密过程与加密相反。先对密文进行AES解密,然后再与前一个密文进行异或运算,得到当前分组的明文。最后,将第一个分组的明文与IV进行异或操作,得到最终的明文。同样地,解密过程中需要使用相同的密钥和IV。 总结来说,AES CBC 128位的加密和解密是在线进行的,通过将明文按照指定的分组长度进行分组,使用AES算法和IV进行加密和解密,利用密文和前一个密文的异或运算,增加了加密的强度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值