首页 > 编程语言 >AES_GCM_256加密算法

AES_GCM_256加密算法

时间:2022-10-31 10:55:17浏览次数:62  
标签:AES plaintext ctx gcm char length EVP 256 加密算法

中文手册:21.2.4EVP_CIPHER_CTX_OpenSSL 中文手册

原理:AES加密算法原理(C++实现)_算法小艾的博客-CSDN博客_aes c++

根据openssl来写的话 参考这个文章

大坑的aes GCM解密算法_C/C++代码_BlackFeather'S Blog (fenlog.com)

对称加密算法AES之GCM模式简介及在OpenSSL中使用举例_fengbingchun的博客-CSDN博客_gcm模式

AES(Advanced Encryption Standard)即高级加密标准,由美国国家标准和技术协会(NIST)于2000年公布,它是一种对称加密算法。关于AES的更多介绍可以参考:https://blog.csdn.net/fengbingchun/article/details/100139524

AES的GCM(Galois/Counter Mode)模式本质上是AES的CTR模式(计数器模式)加上GMAC(Galois Message Authentication Code, 伽罗华消息认证码)进行哈希计算的一种组合模式。GCM可以提供对消息的加密和完整性校验,另外,它还可以提供附加消息的完整性校验。

OpenSSL中的EVP接口支持执行经过身份验证的加密和解密的功能,以及将未加密的关联数据附加到消息的选项。这种带有关联数据的身份验证加密(AEAD, Authenticated-Encryption with Associated-Data)方案通过对数据进行加密来提供机密性,并通过在加密数据上创建MAC标签来提供真实性保证。

Key:对称密钥,它的长度可以为128、192、256bits,用来加密明文的密码。

IV(Initialisation Vector):初始向量,它的选取必须随机。通常以明文的形式和密文一起传送。它的作用和MD5的”加盐”有些类似,目的是防止同样的明文块,始终加密成同样的密文块。

AAD(Additional Authenticated Data):附加身份验证数据。AAD数据不需要加密,通常以明文形式与密文一起传递给接收者。

Mac tag(MAC标签):将确保数据在传输和存储过程中不会被意外更改或恶意篡改。该标签随后在解密操作期间使用,以确保密文和AAD未被篡改。在加密时,Mac tag由明文、密钥Key、IV、AAD共同产生。

以下为测试代码:

namespace {
 
static const unsigned char gcm_key[] = { // 32 bytes, Key
    0xee, 0xbc, 0x1f, 0x57, 0x48, 0x7f, 0x51, 0x92, 0x1c, 0x04, 0x65, 0x66,
    0x5f, 0x8a, 0xe6, 0xd1, 0x65, 0x8b, 0xb2, 0x6d, 0xe6, 0xf8, 0xa0, 0x69,
    0xa3, 0x52, 0x02, 0x93, 0xa5, 0x72, 0x07, 0x8f
};
 
static const unsigned char gcm_iv[] = { // 12 bytes, IV(Initialisation Vector)
    0x99, 0xaa, 0x3e, 0x68, 0xed, 0x81, 0x73, 0xa0, 0xee, 0xd0, 0x66, 0x84
};
 
// Additional Authenticated Data(AAD): it is not encrypted, and is typically passed to the recipient in plaintext along with the ciphertext
static const unsigned char gcm_aad[] = { // 16 bytes
    0x4d, 0x23, 0xc3, 0xce, 0xc3, 0x34, 0xb4, 0x9b, 0xdb, 0x37, 0x0c, 0x43,
    0x7f, 0xec, 0x78, 0xde
};
 
std::unique_ptr<unsigned char[]> aes_gcm_encrypt(const char* plaintext, int& length, unsigned char* tag)
{
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    // Set cipher type and mode
    EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr);
    // Set IV length if default 96 bits is not appropriate
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gcm_iv), nullptr);
    // Initialise key and IV
    EVP_EncryptInit_ex(ctx, nullptr, nullptr, gcm_key, gcm_iv);
    // Zero or more calls to specify any AAD
    int outlen;
    EVP_EncryptUpdate(ctx, nullptr, &outlen, gcm_aad, sizeof(gcm_aad));
    unsigned char outbuf[1024];
    // Encrypt plaintext
    EVP_EncryptUpdate(ctx, outbuf, &outlen, (const unsigned char*)plaintext, strlen(plaintext));
    length = outlen;
    std::unique_ptr<unsigned char[]> ciphertext(new unsigned char[length]);
    memcpy(ciphertext.get(), outbuf, length);
    // Finalise: note get no output for GCM
    EVP_EncryptFinal_ex(ctx, outbuf, &outlen);
    // Get tag
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, outbuf);
    memcpy(tag, outbuf, 16);
    // Clean up
    EVP_CIPHER_CTX_free(ctx);
    return ciphertext;
}
 
std::unique_ptr<unsigned char[]> aes_gcm_decrypt(const unsigned char* ciphertext, int& length, const unsigned char* tag)
{
    EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
    // Select cipher
    EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr);
    // Set IV length, omit for 96 bits
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, sizeof(gcm_iv), nullptr);
    // Specify key and IV
    EVP_DecryptInit_ex(ctx, nullptr, nullptr, gcm_key, gcm_iv);
    int outlen;
    // Zero or more calls to specify any AAD
    EVP_DecryptUpdate(ctx, nullptr, &outlen, gcm_aad, sizeof(gcm_aad));
    unsigned char outbuf[1024];
    // Decrypt plaintext
    EVP_DecryptUpdate(ctx, outbuf, &outlen, ciphertext, length);
    // Output decrypted block
    length = outlen;
    std::unique_ptr<unsigned char[]> plaintext(new unsigned char[length]);
    memcpy(plaintext.get(), outbuf, length);
    // Set expected tag value
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, 16, (void*)tag);
    // Finalise: note get no output for GCM
    int rv = EVP_DecryptFinal_ex(ctx, outbuf, &outlen);
    // Print out return value. If this is not successful authentication failed and plaintext is not trustworthy.
    fprintf(stdout, "Tag Verify %s\n", rv > 0 ? "Successful!" : "Failed!");
    EVP_CIPHER_CTX_free(ctx);
    return plaintext;
}
 
} // namespace
 
int test_openssl_aes_gcm()
{
    /* reference:
        https://github.com/openssl/openssl/blob/master/demos/evp/aesgcm.c
        https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
    */
    fprintf(stdout, "Start AES GCM 256 Encrypt:\n");
    const char* plaintext = "1234567890ABCDEFG!@#$%^&*()_+[]{};':,.<>/?|";
    fprintf(stdout, "src plaintext: %s, length: %d\n", plaintext, strlen(plaintext));
    int length = 0;
    std::unique_ptr<unsigned char[]> tag(new unsigned char[16]);
    std::unique_ptr<unsigned char[]> ciphertext = aes_gcm_encrypt(plaintext, length, tag.get());
    fprintf(stdout, "length: %d, ciphertext: ", length);
    for (int i = 0; i < length; ++i)
        fprintf(stdout, "%02x ", ciphertext.get()[i]);
    fprintf(stdout, "\nTag: ");
    for (int i = 0; i < 16; ++i)
        fprintf(stdout, "%02x ", tag.get()[i]);
    fprintf(stdout, "\n");
 
    fprintf(stdout, "\nStart AES GCM 256 Decrypt:\n");
    std::unique_ptr<unsigned char[]> result = aes_gcm_decrypt(ciphertext.get(), length, tag.get());
    fprintf(stdout, "length: %d, decrypted plaintext: ", length);
    for (int i = 0; i < length; ++i)
        fprintf(stdout, "%c", result.get()[i]);
    fprintf(stdout, "\n");
 
    if (strncmp(plaintext, (const char*)result.get(), length) == 0) {
        fprintf(stdout, "decrypt success\n");
        return 0;
    } else {
        fprintf(stderr, "decrypt fail\n");
        return -1;
    }
}

 

在Windows上执行结果如下:

 

以上是在OpenSSL较老的版本1.0.1g上执行的,在最新版1.1.1g上以上代码也同样可以执行。

在Windows上编译1.1.1g版本源码执行命令如下:no-asm选项为不开启汇编模式,编译release则将debug-VC-WIN64A改为VC-WIN64即可。

perl Configure debug-VC-WIN64A no-asm --prefix=D:\DownLoad\openssl\win64_debug
nmake
nmake install
在Linux上编译1.1.1g版本源码执行命令如下:

./config --prefix=/home/sensetime/Downloads/openssl/install
make
make insall
在1.1.1g源码的demos/evp目录下给出了gcm的示例aesgcm.c,这里将以上测试代码新加为aesgcm2.cpp,编译脚本如下:

#! /bin/bash

g++ -o test_aesgcm aesgcm.c -L ../../ -lcrypto -lssl -I../../include
g++ -o test_aesgcm2 aesgcm2.cpp -std=c++11 -L ../../ -lcrypto -lssl -I../../include

g++ -o test_aesccm aesccm.c -L ../../ -lcrypto -lssl -I../../include
执行结果如下:注意如果在Windows上执行aesgcm2.cpp,需要额外的 #include <openssl/applink.c>

 

GitHub:https://github.com//fengbingchun/OpenSSL_Test

 

标签:AES,plaintext,ctx,gcm,char,length,EVP,256,加密算法
From: https://www.cnblogs.com/Galesaur-wcy/p/16843564.html

相关文章

  • 1. 凯撒加密算法 (对称算法)
    1.凯撒加密算法1.1算法逻辑根据一个固定偏移值(offset),将字母向一个方向偏移,进行加密.1.2初步思路获取明文(plaintext)获取明文字符串的单独字符进行字符值......
  • DES、3DES、AES、RSA、MD5、sha1 加密算法总结
    DES、3DES、AES、RSA、MD5、sha1加密算法总结一、简介DES:全称为DataEncryptionStandard,即数据加密标准,是一种使用密钥加密的块算法;3DES:(即T......
  • tensorflow:OOM when allocating tensor with shape[225,256,256,36] and type float
    运行TensorFlow(GPU)报错如下:OOMwhenallocatingtensorwithshape[225,256,256,36]andtypefloaton/job:localhost/replica:0/tas原因是GPUOOM内存不够,因此可尝试改成......
  • 找回消失的密钥 --- DFA分析白盒AES算法
    一、目标李老板:什么叫白盒AES算法?奋飞:将密钥进行白盒化处理,融入到整个加密过程中,使密钥无法跟踪还原,保障密钥安全。简单的说,就是你可以明明白白的调试整个算法过程,怎么看都......
  • openssl 全面支持国密SM2/SM3/SM4加密算法
    sm4展示代码/**文件名:https://github.com/liuqun/openssl-sm4-demo/blob/cmake/src/main.c*/#include<stddef.h>#include<stdio.h>#include<stdlib.h>#inclu......
  • 接口测试加密算法理解【多测师】
    问题:1.接口中有数据要进行加密,如何处理?答:(1)写个函数或者方法,把要加密的参数使用这个函数过滤一遍,等于就是说把数据丢进去,加密了之后,再通过这个加密好的数据传输过去就可以......
  • AES 加解密
    依赖<dependency><groupId>commons-codec</groupId><artifactId>commons-codec</artifactId></dependency>代码importorg.apa......
  • POJ 3256(SPFA)
    这题只能对每一个点查一遍……有向图的话能用floyd,可是迫于时限用了SPFA。Programaa;constmaxk=10000;maxn=10000;maxm=10000;vark,n,m,i,j,l:longint;a:ar......
  • 牛客SQL-牛客题:256-288(不干了)
    256.写一个sql查询,积分表里面出现三次以及三次以上的积分。若有多个符合条件的number,则按number升序排序输出SELECT`number`FROMgradeGROUPBY`number`HAVINGCOUN......
  • MD5 哈希加密算法 - C++ 实现
    MD5加密算法-C++实现写在前头:还在学习中!整个文档写的很匆忙,肯定还有很多不周到的地方.欢迎在评论中提出你的宝贵意见!!算法背景BackgroundMD5消息摘要算法......