<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>AES &#8211; 编程技术记录</title>
	<atom:link href="https://blog.z6z8.cn/tag/aes/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.z6z8.cn</link>
	<description>世界你好!</description>
	<lastBuildDate>Thu, 21 Nov 2019 02:41:47 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>
	<item>
		<title>SSL EVP框架：AES加密</title>
		<link>https://blog.z6z8.cn/2019/11/21/ssl-evp%e6%a1%86%e6%9e%b6%ef%bc%9aaes%e5%8a%a0%e5%af%86/</link>
					<comments>https://blog.z6z8.cn/2019/11/21/ssl-evp%e6%a1%86%e6%9e%b6%ef%bc%9aaes%e5%8a%a0%e5%af%86/#respond</comments>
		
		<dc:creator><![CDATA[holdsky]]></dc:creator>
		<pubDate>Thu, 21 Nov 2019 02:41:47 +0000</pubDate>
				<category><![CDATA[C++]]></category>
		<category><![CDATA[代码片段]]></category>
		<category><![CDATA[AES]]></category>
		<category><![CDATA[GMSSL]]></category>
		<category><![CDATA[ssl]]></category>
		<guid isPermaLink="false">http://blog.z6z8.cn/?p=581</guid>

					<description><![CDATA[AES加密几个要点 对称加密(Symmetry Crypto) 加密和解密的钥匙是同一把----加密方和解密方 [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>AES加密几个要点</h1>
<ul>
<li>
<p>对称加密(Symmetry Crypto)<br />
加密和解密的钥匙是同一把----加密方和解密方拥有相同的密钥（音yue，四声）。</p>
</li>
<li>
<p>密钥(key)<br />
任意数据（不一定非得字符串），长度常见为128比特、192比特、256比特，也有支持512比特的算法库</p>
</li>
<li>
<p>初始化向量(IV)<br />
这不是AES算法标准强制要求的，是一种增加AES破解难度的手段。IV和密钥共同参与加密和解密运算。IV长度固定为128比特。</p>
</li>
<li>
<p>加密块(block)<br />
每次加密的块长度都是128比特；输入和输出长度相同，考虑补全模式的情况下，输出的最大长度 = 输入长度+128比特</p>
</li>
<li>
<p>加密模式<br />
是指当需要加密的源数据长度大于128比特时，加密块和加密块之间的运算模式。<br />
常见的有 CBC密码分组链接模式、ECB电码本模式（不推荐）、CTR计算器模式、CFB密码反馈模式、OFB输出反馈模式。</p>
</li>
<li>
<p>补全模式模式（padding）<br />
因为AES一个加密块为16字节，当源数据的最后一个块不足16字节时，需要手动补全为16字节。</p>
</li>
</ul>
<p>一般使用PKCS7模式，手动补全N个N，N为不足的字节数。</p>
<pre><code>例如，最后一个块为 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10
需要补6个字节，那么就是6个6
 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x06 0x06 0x06 0x06 0x06 0x06</code></pre>
<h1>EVP AES 加密</h1>
<pre><code class="language-cpp">
#include "openssl/crypto.h"
#include "openssl/aes.h"
#include "openssl/evp.h"

//引入c++的string，作为buffer使用
#include &lt;string&gt;

//std::string 作为返回值其实可以右值优化的。
std::string encrypt(std::string &amp;data , std::string &amp;key ,std::string &amp;iv)
{
     //这里应该做必要的参数校验，如检查key和iv长度
    //指定算法模式
    EVP_CIPHER *ciper = NULL;
    switch (data.size())
    {
        case 128 / 8: ciper =  EVP_aes_128_cbc();break;
        case 192 / 8: ciper =  EVP_aes_192_cbc();break;
        case 256 / 8: ciper =  EVP_aes_256_cbc();break;
        default:return "需要做一些错误处理";
    }

    //初始化ctx
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER_CTX_init(ctx);

    //指定加密算法及key和iv
    int ret = EVP_EncryptInit_ex(ctx, ciper, NULL, (unsigned char *)key.c_str(),  (unsigned char *)iv.c_str());
    if(ret != 1)
    {//EVP_EncryptInit_ex failed
        EVP_CIPHER_CTX_free(ctx);
        return "需要做一些错误处理";
    }

    // 设置padding EVP框架默认使用的就是PKCS7
    EVP_CIPHER_CTX_set_padding(ctx, 1);

   std::string buffer;
   buffer.append(0,AES_BLOCK_SIZE + data.size());

    int mlen = 0;
    //进行加密操作
    ret = EVP_EncryptUpdate(ctx, (unsigned char *)buffer.c_str(), &amp;mlen, (unsigned char *)data.c_str(),(int)buffer.size());
    if(ret != 1)
    {
        EVP_CIPHER_CTX_free(ctx);
        return "需要做一些错误处理";
    }

    int flen = 0;
    //结束加密操作
    ret = EVP_EncryptFinal_ex(ctx, (unsigned char *)buffer.c_str()+mlen, &amp;flen);
    if(ret != 1)
    {
        EVP_CIPHER_CTX_free(ctx);
        return "需要做一些错误处理";
    }
    EVP_CIPHER_CTX_free(ctx);
    buffer.resize(mlen + flen);
    return buffer;
}
</code></pre>
<h1>EVP AES 解密</h1>
<pre><code class="language-cpp">
std::string decrypt(std::string &amp;data , std::string &amp;key ,std::string &amp;iv)
{
   //这里应该做必要的参数校验，如检查key和iv长度
    //指定算法模式
    EVP_CIPHER *ciper = NULL;
    switch (data.size())
    {
        case 128 / 8: ciper =  EVP_aes_128_cbc();break;
        case 192 / 8: ciper =  EVP_aes_192_cbc();break;
        case 256 / 8: ciper =  EVP_aes_256_cbc();break;
        default:return "需要做一些错误处理";
    }

    //初始化ctx
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    EVP_CIPHER_CTX_init(ctx);

    //指定加密算法及key和iv
    int ret = EVP_DecryptInit_ex(ctx, ciper, NULL,  (unsigned char *)key.c_str(),  (unsigned char *)iv.c_str());
    if(ret != 1)
    {//EVP_EncryptInit_ex failed
        EVP_CIPHER_CTX_free(ctx);
        return  "需要做一些错误处理";
    }

    // 设置padding功能 EVP框架默认使用的就是PKCS7
    EVP_CIPHER_CTX_set_padding(ctx, 1);

    std::string buffer;
    buffer.append(0,data.size());

    int mlen = 0;
    //进行解密操作
    ret = EVP_DecryptUpdate(ctx,  (unsigned char *)buffer.c_str(), &amp;mlen,  (unsigned char *)data.c_str(),(int) data.size());
    if(ret != 1)
    {
        EVP_CIPHER_CTX_free(ctx);
        return  "需要做一些错误处理";
    }

    int flen = 0;
    //结束解密操作
    ret = EVP_DecryptFinal_ex(ctx, (unsigned char *)buffer.c_str()+mlen, &amp;flen);
    if(ret != 1)
    {
        EVP_CIPHER_CTX_free(ctx);
        return  "需要做一些错误处理";
    }

    EVP_CIPHER_CTX_free(ctx);
    buffer.resize(mlen + flen);
    return buffer;
}</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.z6z8.cn/2019/11/21/ssl-evp%e6%a1%86%e6%9e%b6%ef%bc%9aaes%e5%8a%a0%e5%af%86/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
