go CBC 加密【AES 和DES的运用】

本文介绍了在Go中使用AES和DES进行CBC模式加密的原理和实践,包括加密模式、填充方式、密码和偏移量的概念。同时提到了DES的密钥长度和初始化向量的作用。文章还提及了加密后的字节可以进行hex或base64编码,并且推荐了一个第三方包用于实现多种加密算法。
摘要由CSDN通过智能技术生成

关于AES cbc的加密 在go AES 加密 和解密已经调到了, 这次主要涉及的内同时cbc 和ecb,刚好网上也有相应的说明, 我就一起整理一下

DES是以64比特的明文为一个单位来进行加密,并生成64比特的密文。由于它每次只能处理特定长度的一块数据,所以DES属于分组密码算法。cypto/des包提供了有关des加密的功能。

模式

由于分组密码算法只能加密固定长度的分组,所以当加密的明文超过分组密码的长度时,就需要对分组密码算法进行迭代,而迭代的方法就称为分组密码的模式。模式主要有ECB(电子密码本)、CBC(密码分组链接模式)、CTR(计数器模式)、OFB(输出反馈模式)、CFB(密码反馈模式)五种。下面简单介绍下前两种:

  1. ECB(electronic code book)是最简单的方式,它将明文分组加密后的结果直接成为密文分组。
    优缺点:模式操作简单;明文中的重复内容将在密文中表现出来,特别对于图像数据和明文变化较少的数据;适于短报文的加密传递。

     

  2. CBC(cipher block chaining)的原理是加密算法的输入是当前的明文分组和前一密文分组的异或,第一个明文分组和一个初始向量进行异或,这样同一个明文分组重复出现时会产生不同的密文分组。
    特点:同一个明文分组重复出现时产生不同的密文分组;加密函数的输入是当前的明文分组和前一个密文分组的异或;每个明文分组的加密函数的输入与明文分组之间不再有固定的关系;适合加密长消息。

     

填充方式

在按8个字节对DES进行加密或解密时,如果最后一段字节不足8位,就需要对数据进行补位。即使加密或解密的数据刚好是8的倍数时,也会再补8位。举个栗子,如果末尾刚好出现1,这时你就无法判断这个1是原来数据,还是经过补位得到的1。因此,可以再补8位进行标识。填充方式主要有以下几种:pkcs7padding、pkcs5padding、zeropadding、iso10126、ansix923。

  1. pkcs7padding和pkcs5padding的填充方式相同,填充字节的值都等于填充字节的个数。例如需要填充4个字节,则填充的值为"4 4 4 4"。
  2. zeropadding填充字节的值都为0。

密码

DES的密钥长度是64比特,但由于每隔7个比特会设置一个用于错误检测的比特,因此其实质密钥长度为56比特。

偏移量

上面模式中,例如CBC,再加密第一个明文分组时,由于不存在“前一个密文分组”,因此需要事先准备一个长度为一个分组的比特序列来代替“前一个密文分组”,这个比特序列成为初始化向量,也称偏移量,通常缩写为IV。一般来说,每次加密时都会随机产生一个不同的比特序列来作为初始化向量。偏移量的长度必须和块的大小相同。

输出

加密后的字节在显示时可以进行hex和base64编码,hex是十六进制编码,base64是一种基于64个可打印字符来标识二进制数据的方

实现文件的AESDES加密需要以下步骤: 1. 读取文件数据 2. 对数据进行填充,使其满足加密算法的要求 3. 设置加密算法的参数,如密钥、加密模式、填充方式等 4. 执行加密操作 5. 将加密后的数据写入文件 下面是一个使用 OpenSSL 库实现文件的 AESDES 加密的示例代码: ```c #include <stdio.h> #include <openssl/evp.h> #define BUFFER_SIZE 1024 void encrypt_file_aes(const char* input_file, const char* output_file, const unsigned char* key, const unsigned char* iv) { // 打开输入文件 FILE* in = fopen(input_file, "rb"); if (in == NULL) { printf("无法打开输入文件 %s\n", input_file); return; } // 打开输出文件 FILE* out = fopen(output_file, "wb"); if (out == NULL) { fclose(in); printf("无法打开输出文件 %s\n", output_file); return; } // 创建 AES 加密上下文 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { fclose(in); fclose(out); printf("无法创建加密上下文\n"); return; } // 初始化 AES 加密上下文 if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法初始化加密上下文\n"); return; } unsigned char inbuf[BUFFER_SIZE]; unsigned char outbuf[BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH]; int inlen, outlen; // 循环读取、加密和写入文件数据 do { inlen = fread(inbuf, 1, BUFFER_SIZE, in); if (EVP_EncryptUpdate(ctx, outbuf, &outlen, inbuf, inlen) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法加密数据\n"); return; } fwrite(outbuf, 1, outlen, out); } while (inlen == BUFFER_SIZE); // 结束加密操作 if (EVP_EncryptFinal_ex(ctx, outbuf, &outlen) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法结束加密操作\n"); return; } fwrite(outbuf, 1, outlen, out); // 释放资源 fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); } void decrypt_file_aes(const char* input_file, const char* output_file, const unsigned char* key, const unsigned char* iv) { // 打开输入文件 FILE* in = fopen(input_file, "rb"); if (in == NULL) { printf("无法打开输入文件 %s\n", input_file); return; } // 打开输出文件 FILE* out = fopen(output_file, "wb"); if (out == NULL) { fclose(in); printf("无法打开输出文件 %s\n", output_file); return; } // 创建 AES 解密上下文 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { fclose(in); fclose(out); printf("无法创建解密上下文\n"); return; } // 初始化 AES 解密上下文 if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法初始化解密上下文\n"); return; } unsigned char inbuf[BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH]; unsigned char outbuf[BUFFER_SIZE]; int inlen, outlen; // 循环读取、解密和写入文件数据 do { inlen = fread(inbuf, 1, BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH, in); if (EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf, inlen) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法解密数据\n"); return; } fwrite(outbuf, 1, outlen, out); } while (inlen == BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH); // 结束解密操作 if (EVP_DecryptFinal_ex(ctx, outbuf, &outlen) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法结束解密操作\n"); return; } fwrite(outbuf, 1, outlen, out); // 释放资源 fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); } void encrypt_file_des(const char* input_file, const char* output_file, const unsigned char* key, const unsigned char* iv) { // 打开输入文件 FILE* in = fopen(input_file, "rb"); if (in == NULL) { printf("无法打开输入文件 %s\n", input_file); return; } // 打开输出文件 FILE* out = fopen(output_file, "wb"); if (out == NULL) { fclose(in); printf("无法打开输出文件 %s\n", output_file); return; } // 创建 DES 加密上下文 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { fclose(in); fclose(out); printf("无法创建加密上下文\n"); return; } // 初始化 DES 加密上下文 if (EVP_EncryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法初始化加密上下文\n"); return; } unsigned char inbuf[BUFFER_SIZE]; unsigned char outbuf[BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH]; int inlen, outlen; // 循环读取、加密和写入文件数据 do { inlen = fread(inbuf, 1, BUFFER_SIZE, in); if (EVP_EncryptUpdate(ctx, outbuf, &outlen, inbuf, inlen) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法加密数据\n"); return; } fwrite(outbuf, 1, outlen, out); } while (inlen == BUFFER_SIZE); // 结束加密操作 if (EVP_EncryptFinal_ex(ctx, outbuf, &outlen) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法结束加密操作\n"); return; } fwrite(outbuf, 1, outlen, out); // 释放资源 fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); } void decrypt_file_des(const char* input_file, const char* output_file, const unsigned char* key, const unsigned char* iv) { // 打开输入文件 FILE* in = fopen(input_file, "rb"); if (in == NULL) { printf("无法打开输入文件 %s\n", input_file); return; } // 打开输出文件 FILE* out = fopen(output_file, "wb"); if (out == NULL) { fclose(in); printf("无法打开输出文件 %s\n", output_file); return; } // 创建 DES 解密上下文 EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { fclose(in); fclose(out); printf("无法创建解密上下文\n"); return; } // 初始化 DES 解密上下文 if (EVP_DecryptInit_ex(ctx, EVP_des_cbc(), NULL, key, iv) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法初始化解密上下文\n"); return; } unsigned char inbuf[BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH]; unsigned char outbuf[BUFFER_SIZE]; int inlen, outlen; // 循环读取、解密和写入文件数据 do { inlen = fread(inbuf, 1, BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH, in); if (EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf, inlen) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法解密数据\n"); return; } fwrite(outbuf, 1, outlen, out); } while (inlen == BUFFER_SIZE + EVP_MAX_BLOCK_LENGTH); // 结束解密操作 if (EVP_DecryptFinal_ex(ctx, outbuf, &outlen) != 1) { fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); printf("无法结束解密操作\n"); return; } fwrite(outbuf, 1, outlen, out); // 释放资源 fclose(in); fclose(out); EVP_CIPHER_CTX_free(ctx); } ``` 使用示例: ```c int main() { // 128 位 AES 密钥和 IV unsigned char aes_key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; unsigned char aes_iv[] = { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; // 64 位 DES 密钥和 IV unsigned char des_key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; unsigned char des_iv[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; // 加密 AES 文件 encrypt_file_aes("input.txt", "output_aes.bin", aes_key, aes_iv); // 解密 AES 文件 decrypt_file_aes("output_aes.bin", "input_aes.txt", aes_key, aes_iv); // 加密 DES 文件 encrypt_file_des("input.txt", "output_des.bin", des_key, des_iv); // 解密 DES 文件 decrypt_file_des("output_des.bin", "input_des.txt", des_key, des_iv); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值