加密与解密

C语言与CPP编程

共 1609字,需浏览 4分钟

 · 2021-01-19

涉及到安全的领域总离不开数据加密,如通讯、文件保护游戏核心数据等等
加密技术博大高深,涉及深厚的数学原理。加密方式亦有多种,比如飘云阁的一套密码学工具就提供了多种方式:
本文将介绍一些密码学知识(其实是对19年文章的更新),并提供一个方便使用的接口库,这些功能基于cryptopp(见第5节)。
之后,你会发现要编写个类似上面的工具,其实并不难。

1

简单加密

在加密技术中,一个最底层的工具就是mod运算,即按位异或运算。
异或运算的法则是:当两个操作数中只有一个为1的时候,结果为真(1),否则结果为假(0)。如:
   10010011 ^
   00111101
----------------
10101110
除此以外,异或运算还拥有交换律、结合律,即:
A ^ B == B ^ A
A ^ B ^ C == (A ^ B) ^ C == A ^ (B ^ C)
A ^ B = C  -->  A = B ^ C  -->  B = A ^ C
所以,对一串数据进行一次异或运算,就能够对数据进行「加密」,再进行一次异或运算就能够对数据进行「解密」
基于此,我们便可以写一个很简单的用于加密文件的小程序:
1void EncrytFile(const char* plain_file, const char* cipher_file)
2
{
3    if (nullptr == plain_file || nullptr == cipher_file)
4        throw std::runtime_error("名称为空");
5
6    // 打开欲加密文件
7    std::ifstream fsPlainFile(plain_file, 
8        std::ios_base::in | std::ios_base::binary)
;
9    if (!fsPlainFile.is_open())
10        throw std::runtime_error("打开文件失败");
11
12    // 打开输出文件
13    std::ofstream fsCipherFile(cipher_file, std::ios_base::out | std::ios_base::binary);
14    if (!fsCipherFile)
15    {
16        fsPlainFile.close();
17        throw std::runtime_error("打开文件失败");
18    }
19
20    const int key = 0x7F;
21
22    // 加密
23    char temp = fsPlainFile.get() ^ key;
24    while (!fsPlainFile.eof())
25    {
26        fsCipherFile.put(temp);
27        temp = fsPlainFile.get() ^ key;
28    }
29
30    fsPlainFile.close();
31    fsCipherFile.close();
32}
可以使用这个函数来加密任何类型的文件,因为这里是以二进制模式对文件进行操作的。
比如可以对文本类型进行加密:
1try {
2    EncrytFile(".//1.txt"".//encrypted.txt");
3}
4catch (const std::exception& e)
5{
6    std::cerr << e.what() << std::endl;
7}
加密之后文本变成了乱码文件:
只要再对加密文件进行一次加密,那么就可将文件解密:
1try {
2    EncrytFile(".//encrypted.txt"".//decrypted.txt");
3}
4catch (const std::exception& e)
5{
6    std::cerr << e.what() << std::endl;
7}
解密结果:
对数据进行加密后,只有能够完整解密,才能称之为「加密」。若是加密之后,无法进行解密,那么就不叫做加密,纯属是数据破坏。

2

对称密码

在上面的代码中,加密与解密用的是同一个密钥,那么使用这种加密方式的密码就称为「对称密码」

2.1

DES

DES是一种将64bits的明文加密成64bits密文的「对称加密算法」,它的密钥长度为64bits,但是会在每7bits设置一个用于错误检查的位,因此实际上它的密钥长度为56bits。
这种加密方式起初一直被政府与银行机构使用,不过现在已经能够在短时间内被破解,所以已经不推荐使用了。
DES每次只能加密64bits的数据,那么64bits就是它的基本单位,这个单位在密码学中被称为「分组」。
要想加密更长的数据,就得把这些数据按64bits分成一个个的分组,那么这种以分组为单位进行加密的密码算法就被称为「分组密码」
对数据进行分组有许多方式,具体的分组方式称为「模式」,比如ECB、CBC、CFB、OFB、CTR等等。
DES的结构使用了Feistel网络,在这个结构中,加密的一个步骤称为一个「轮」,要全部加密就要进行若干次「轮循」。
图中,左边部分为加密操作,右边部分为解密操作。
每轮的密钥都不能相同,所以Key1只是一个局部变量,仅作为当轮加密使用,所以把这种密钥称为「子密钥」。
在加密操作中,将数据分为左右两部分,DES是一次加密64bits的明文,所以L0就指的是前32bits,R0就将的是后32bits,F就是加密时使用的轮函数,K0、K1…Kn就是每轮加密的「子密钥」,这里进行了N轮的加密操作。
每轮只会将L0,即左半部分的数据与轮函数生成的比特序列进行异或运算,右半部分直接输出。之后进行翻转,左部分变成右部分,右部分变成左部分,如此进行多轮循环加密。

2.2

AES

由于DES不再安全,所以就需要一种新的加密算法来代替其成为标准。美国标准化机构组织了一次公开竞选,能被选中的密码算法将成为美国的加密标准,其实也就相当于世界的加密标准。
参与者必须提供详细的设计和程序代码实现,由于完全公开,所以不同的参与者都能看清别人的设计。这些参与者都是来自各个国家的密码学专家或数学大师,如果连他们也无法找出其他参与者算法中存在的漏洞,那么就能保证加密算法的强度。
这些加密算法不仅需要高强度,还需要有高速度、简易性。最终,Rijndael(即后来的AES标准算法)力压群雄,成为了AES标准。
Rijndael和DES使用了不同的结构,SPN结构:
其中每一轮主要分成四个步骤:
  1. SubBytes(字节替换)

  2. ShiftRow(平移行)

  3. MixColumn(混合列)

  4. AddRoundKey(与轮密钥进行异或运算)

首先,它会以每个字节值,准备一张拥有256个值的替换表,即ASCII码表的中0-255个值,再以替换表中的值来逐字节地替换明文分组中的值。
第二步和第三步,如同扭魔方一样,先对数据的行进行平移操作,再对数据的列进行混合操作,混合中会将上一步得出的数据与替换表中的数据进行矩阵运算。
最后,将得到的结果再与替换表中的数据进行异或运算,所有的数据在一轮操作后都会被加密,所以它比DES所需的轮数就要少。
是不是觉得好深奥?这些算法都有严谨的数学原理支撑,要想真正搞明白的确不易,我们只需了解它的设计思路就可以了。

3

非对称密码

在对称密码中,加密与解密的密钥都是一样的,而「接收者」要解密就必须需要密钥,所以这就产生了一个问题,如何将密钥安全地交到接收者手中呢?这个问题就被称为「密钥配送问题」。
在公钥密码,即非对称密码中,密钥分为「公钥」和「私钥」,一组公钥与私钥称为一个「密钥对」由「公钥」加密的密文,只有使用对应的「私钥」才能完成解密
如此一来,「接收者」只需事先生成好密钥对,将公钥发送给「发送者」,「发送者」使用「公钥」对明文进行加密,然后发送给「接收者」,「接收者」此时可以直接使用「私钥」进行解密。
这样就解决了「密钥配送问题」。

3.1

RSA

RSA属于公钥密码算法,它的名称由三位发明人的名字首字母组成,这三人也因为这项发明获得了图灵奖。
所以,在RSA中,依旧需要「公钥」和「私钥」。可以从这张图来看:
其中主要分为以下几个步骤:
  1. 选择两个很大的质数p和q

  2. 根据p和q,计算出n,再求出p-1和q-1的最小公倍数v

  3. 找出一个数k,这个数要满足:1 < k < v,并且k和v的最大公约数要为1

  4. 找出一个数d,这个数要满足:1 < d < v,并且(d * k) % v要等于1

其中,「公钥」即为(k,n),「私钥」即为(d, n),事实上,由于公钥是可以随意传播的,而n又是公钥的一部分,所以也可以说私钥就是d。
之后,加密可以使用:密文 = 明文 ^ k % n,而解密则使用:明文 = 密文 ^ d % n
这东西实现起来不难,但是比较麻烦,因为需要对很大的数进行运算,这些数long long都不够存储,只能通过字符串来搞,所以依旧明白它的思路就可以了。当然,若是对取两个很小的质数,也可以手动验证上面步骤是否真的可以对数据进行加密和解密。
其实,已经有C++库完美地实现了前面所介绍的加密算法,我们主要就来学习这些库的使用就可以了。
需要注意的是,在同等长度的密钥下,公钥密码处理速度只有对称密码的几百分之一,所以公钥密码不适合加密过长的内容
那么我们什么时候用公钥密码呢?不要忘记了对称密码的缺点,以及公钥密码解决了什么问题。
公钥密码主要针对的是「密钥配送问题」,密钥一般都不会太长,所以它的效率就会很高。
总结一下就是,用对称密码来加密信息,而用公钥密码来解决密钥的配送,同时使用这两种的密码就称为「混合密码」
举个例子,在一个通讯系统中,客户端要发送数据到服务器,那么这些数据就可以使用对称密码来进行加密。使用对称密码时,服务器无法得知客户端的加密密钥,客户端也无法直接将密钥发送给服务器,因为它如果能够直接将密钥安全地发送过去,那么它也就可以安全地将数据传送过去。
这时就可以使用对称密码,通过服务器生成一个密钥对,将公钥发送给客户端,客户端通过公钥来对密钥进行加密,之后再发送给服务器。服务器通过私钥对信息进行解密,从而得到客户端加密的密钥,之后就能解开客户端的传来的数据。

4

单向散列函数

单向散列函数就是平时所说的hash函数,用于验证数据的完整性。
在前面解决了如何将数据安全地传递给接收者,那么若此信息在发送期间被破坏者恶意篡改,你如何确保数据是完整而未被篡写的呢?
这就是单向散列函数的作用,它可以提取出一段信息的特征,输出一段经过严格计算的「散列值」
若是一个算法对于不同的信息所计算的散列值不会重复,那么就说它具有「强抗碰撞性」。若一个算法的强抗碰撞性被攻破,即对于不同的信息,会产生相同的散列值,那么这个算法就不算安全。
通过对比散列值是否一致,就可以验证文件是否完整比如,许多安全软件在提供下载的地址处就给出了软件所对应的散列值,下载者可通过自己计算散列值来和所提供的散列值对比,以确认下载的是正确的软件。
单向散列函数也有许多算法,例如MD5、SHA256、SHA512等等。不过如今MD5的强抗碰撞性已被攻破,已经不推荐使用。现在安全的是SHA-3,这个也和AES一样通过标准竞选所得,经过了安全考验,我们现在就可以使用这个。

5

基于Cryptopp加密库的加密组件

Cryptopp是使用C++开发的一套密码学程序库,其中使用了大量GP技术,可以说是一个非常高深的库,很有参考与使用价值。
其中囊括了几乎所有公开的加密算法,比如上面所说的对称密码DES、AES,以及公钥密码RSA,还有散列函数MD5、SHA3。加密的分组模式也通过GP实现了ECB,CBC,CFB,FOB,CTR这些。总之总结起来就两个字:NB。
我们将常用算法提炼到一个类中,名为okcrypt,以此来简化每次加解密的操作。这里提供代码:https://github.com/gxkey/okcrypt,里面也包含cryptopp库,可以包含项目和lib目录直接使用。
下面简单分述下各个模块。

5.1

MD5

MD5是单向散列函数,可以得出一段信息的散列值,虽说其强抗碰撞性已被攻破,但仍有不少地方在使用。
下面是MD5的使用:

1const std::string okcrypt::EncryptMD5(std::string const& msg)
2{    
3    std::string digest;
4    Weak1::MD5 hash;
5    hash.Update((const byte*)msg.data(), msg.size());
6    digest.resize(hash.DigestSize());
7    hash.Final((byte*)&digest[0]);
8
9    return ToHex(digest);
10}

MD5在namespace Weak1之下,通过Update()设置原始数据,通过Final()获得消息摘要。
要将得到的消息摘要转换成十六进制的才适合查看,不然看起来像是一堆二进制乱码。转换十六进制的函数实现如下:

1static const std::string ToHex(std::string const& digest) {
2    std::stringstream ss;
3    HexEncoder encoder(new FileSink(ss));
4    (void)StringSource(digest, truenew Redirector(encoder));
5    return ss.str();
6}

通过StringSource类可以将加密结果输出到指定流,这里将它输出到HexEncoder的保存的数据流中。

5.2

Base64

Base64是一种编码方式,使用如下:

1const std::string okcrypt::EncryptBase64(std::string const& plainData)
2{
3    std::string encoded;
4
5    StringSource ss((const byte*)plainData.data(), plainData.size()
6        truenew Base64Encoder(new StringSink(encoded))
7    )
;
8
9    return encoded;
10}

同样借助了StringSource,编码结果输出到string中。

5.3

SHA

SHA也是单向散列函数,分为SHA-1、SHA-2,SHA-3。SHA-1的强抗碰撞性在2005年已被攻破,所以只说SHA-2和SHA-3。
SHA-2和SHA-3的散列长度分为224、256、384、512比特,所以各提供4个版本:

1// SHA2
2static const std::string EncryptSHA224(std::string const& msg);
3static const std::string EncryptSHA256(std::string const& msg);
4static const std::string EncryptSHA384(std::string const& msg);
5static const std::string EncryptSHA512(std::string const& msg);
6
7// SHA3
8static const std::string EncryptSHA3_224(std::string const& msg);
9static const std::string EncryptSHA3_256(std::string const& msg);
10static const std::string EncryptSHA3_384(std::string const& msg);
11static const std::string EncryptSHA3_512(std::string const& msg);

由于cryptopp提供的算法接口都相同,只是类型不同,为了可复用性,我们使用函数模板实现:

1template<class SHAType>
2static const std:
:string EncryptSHA(std::string const& msg) {
3    SHAType hash;
4    std::string digest;
5    hash.Update((const byte*)msg.data(), msg.size());
6    digest.resize(hash.DigestSize());
7    hash.Final((byte*)&digest[0]);
8
9    return ToHex(digest);
10}

可以看到和MD5的用法相似,这是因为这些散列函数都派生自HashTransformation,这里提供了Update、Final、Verify这些函数。
现在直接调用EncryptSHA,并传入不同的类型就能实现不同的SHA摘要,如下:

1const std::string okcrypt::EncryptSHA224(std::string const& msg)
2{
3    return EncryptSHA(msg);
4}
5
6const std::string okcrypt::EncryptSHA256(std::string const& msg)
7{
8    return EncryptSHA(msg);
9}
10
11const std::string okcrypt::EncryptSHA384(std::string const& msg)
12{
13    return EncryptSHA(msg);
14}
15
16const std::string okcrypt::EncryptSHA512(std::string const& msg)
17{
18    return EncryptSHA(msg);
19}
20
21const std::string okcrypt::EncryptSHA3_224(std::string const& msg)
22{
23    return EncryptSHA(msg);
24}
25
26const std::string okcrypt::EncryptSHA3_256(std::string const& msg)
27{
28    return EncryptSHA(msg);
29}
30
31const std::string okcrypt::EncryptSHA3_384(std::string const& msg)
32{
33    return EncryptSHA(msg);
34}
35
36const std::string okcrypt::EncryptSHA3_512(std::string const& msg)
37{
38    return EncryptSHA(msg);
39}

5.4

DES

现在来说对称密码,DES分为DES和3DES,后者是三重加强版本。
先定义如下函数:

1// DES
2static void InitalizeDESKey();
3static const std::string GetDESKey();
4static void SetDESKey(std::string const& key);
5static void EncryptDES(std::string const& plainData, std::string& cipherData);
6static void DecryptDES(std::string const& cipherData, std::string& recoveredData);
7
8// 3DES
9static void Initalize3DESKey();
10static const std::string Get3DESKey();
11static void Set3DESKey(std::string const& key);
12static void Encrypt3DES(std::string const& plainData, std::string& cipherData);
13static void Decrypt3DES(std::string const& cipherData, std::string& recoveredData);

还需要变量来保存密钥和一个初始化向量(IV),IV用于用于在分组模式中提供第一次比特数据。

1static SecByteBlock m_desKey;
2static byte m_desIV[DES_EDE2::BLOCKSIZE];
3
4static SecByteBlock m_3desKey;
5static byte m_3desIV[DES_EDE3::BLOCKSIZE];

因为是静态变量,所以还需要在类外定义:

1SecByteBlock        okcrypt::m_desKey(0x00, DES_EDE2::DEFAULT_KEYLENGTH);
2byte                       okcrypt::m_desIV[DES_EDE2::BLOCKSIZE];
3
4SecByteBlock        okcrypt::m_3desKey(0x00, DES_EDE3::DEFAULT_KEYLENGTH);
5byte                       okcrypt::m_3desIV[DES_EDE3::BLOCKSIZE];

下面只说3DES的使用,先初始化密钥:

1void okcrypt::Initalize3DESKey()
2{
3    AutoSeededRandomPool rng;
4
5    rng.GenerateBlock(m_3desKey, m_3desKey.size());
6    rng.GenerateBlock(m_3desIV, sizeof(m_3desIV));
7}

可以通过随机数池AutoSeededRandomPool来生成密钥与IV。也可手动设置和获取密钥:

1const std::string okcrypt::Get3DESKey()
2{
3    std::string key((char *)m_3desKey.data(), m_3desKey.size());
4    return key;
5}
6
7void okcrypt::Set3DESKey(std::string const& key)
8{
9    SecByteBlock s((const byte*)key.data(), key.size());
10    m_3desKey = s;
11}

加解密操作使用的是CBC分组模式,CBC对于每组明文是先异或后加密。实现如下:

1void okcrypt::Encrypt3DES(std::string const& plainData, std::string &cipherData)
2{
3    try {
4        CBC_Mode::Encryption e;
5        e.SetKeyWithIV(m_3desKey, m_3desKey.size(), m_3desIV);
6
7        StringSource ss(plainData, true,
8            new StreamTransformationFilter(e, new StringSink(cipherData)
)
9        )
;
10    }
11    catch (const CryptoPP::Exception& e)
12    {
13        throw e;
14    }
15}
16
17void okcrypt::Decrypt3DES(std::string const& cipherData, std::string &recoveredData)
18{
19    try {
20        CBC_Mode::Decryption d;
21        d.SetKeyWithIV(m_3desKey, m_3desKey.size(), m_3desIV);
22
23        StringSource ss(cipherData, true,
24            new StreamTransformationFilter(d, new StringSink(recoveredData)
)
25        )
;
26    }
27    catch (const CryptoPP::Exception& e)
28    {
29        throw e;
30    }
31}

5.5

AES

AES也是对称密码,所以也声明相同的接口:

1// AES
2static void InitalizeAESKey();
3static const std::string GetAESKey();
4static void SetAESKey(std::string const& key);
5static void EncryptAES(std::string const& plainData, std::string& cipherData);
6static void DecryptAES(std::string const& cipherData, std::string& recoveredData);

声明密钥和IV变量:

1static SecByteBlock m_aesKey;
2static SecByteBlock m_aesIV;

类外定义:

1SecByteBlock        okcrypt::m_aesKey(0x00, AES::DEFAULT_KEYLENGTH);
2SecByteBlock        okcrypt::m_aesIV(AES::BLOCKSIZE);

随机初始化密码和IV:

1void okcrypt::InitalizeAESKey()
2{
3    AutoSeededRandomPool rng;
4
5    // 生成随机密钥
6    rng.GenerateBlock(m_aesKey, m_aesKey.size());
7
8    // 生成随机IV
9    rng.GenerateBlock(m_aesIV, m_aesIV.size());
10}

加密与解密:

1void okcrypt::EncryptAES(std::string const& plainData, std::string &cipherData)
2{
3    // 加密
4    CFB_Mode::Encryption e(m_aesKey, m_aesKey.size(), m_aesIV);
5    cipherData.resize(plainData.size());
6    e.ProcessData((byte*)&cipherData[0], (byte*)plainData.data(), plainData.size());
7}
8
9void okcrypt::DecryptAES(std::string const& cipherData, std::string &recoveredData)
10{
11    // 解密
12    CFB_Mode::Decryption d(m_aesKey, m_aesKey.size(), m_aesIV);
13    recoveredData.resize(cipherData.size());
14    d.ProcessData((byte*)&recoveredData[0], (byte*)cipherData.data(), cipherData.size());
15}

尽管AES的原理非常麻烦,但通过这些接口,可以很方便地使用它们。这里使用的不同的分组模式CFB,这种模式和CBC模式的区别是:CBC对于每组明文是先异或后加密,而CFB对于每组明文是先加密后异或。

5.6

RSA

RSA是非对称密码,拥有公钥和私钥,定义的函数接口尽量也和对称密码一致:

1// RSA
2static void InitalizeRSAKeys(size_t bits = 1024);
3static const std::string GetRSAPublicKey();
4static void SetRSAPublicKey(std::string& key);
5static void EncryptRSA(std::string const& plainData, std::string& cipherData);
6static void DecryptRSA(std::string const& cipherData, std::string& recoveredData);

声明公钥和私钥:

1static RSA::PublicKey m_rsaPublicKey;
2static RSA::PrivateKey m_rsaPrivateKey;

类外定义:

1RSA::PublicKey      okcrypt::m_rsaPublicKey;
2RSA::PrivateKey     okcrypt::m_rsaPrivateKey;

通过伪随机数生成器自动生成密钥对:

1void okcrypt::InitalizeRSAKeys(size_t bits)
2{
3    // 伪随机数生成器
4    AutoSeededRandomPool rng;
5
6    // 生成参数
7    InvertibleRSAFunction params;
8    params.GenerateRandomWithKeySize(rng, bits);
9
10    // 创建密钥对
11    m_rsaPrivateKey = params;
12    m_rsaPublicKey = params;
13}

手动设置和获取公钥:

1const std::string okcrypt::GetRSAPublicKey()
2{
3    std::string pubKey;
4    StringSink ss(pubKey);
5    m_rsaPublicKey.Save(ss);
6
7    return pubKey;
8}
9
10void okcrypt::SetRSAPublicKey(std::string& key)
11{
12    StringSink ss(key);
13    m_rsaPublicKey.Load(ss);
14}

公钥加密,私钥解密:

1void okcrypt::EncryptRSA(std::string const& plainData, std::string &cipherData)
2{
3    // 伪随机数生成器
4    AutoSeededRandomPool rng;
5
6    // 加密器
7    RSAES_OAEP_SHA_Encryptor e(m_rsaPublicKey);
8
9    StringSource ss(plainData, true,
10        new PK_EncryptorFilter(rng, e, new StringSink(cipherData)
)
11    )
;
12}
13
14void okcrypt::DecryptRSA(std::string const& cipherData, std::string &recoveredData)
15{
16    // 伪随机数生成器
17    AutoSeededRandomPool rng;
18
19    // 解密器
20    RSAES_OAEP_SHA_Decryptor d(m_rsaPrivateKey);
21
22    StringSource ss(cipherData, true,
23        new PK_DecryptorFilter(rng, d, new StringSink(recoveredData)
)
24    )
;
25}

6

okcrypt的使用

克隆到本地:

git clone https://github.com/gxkey/okcrypt.git

其中包含已编译好的cryptopp,目标机器msvc2019,包含目录okcrypt,lib目录okcrypt/lib。其它编译器可能要自己重新编译cryptopp。
只需包含okcrypt.h,就能使用,样例代码如下:

1#include 
2#include "okcrypt.h"
3
4void PrintEncrypt(const char* algo, const std::string& hexCipherData) {
5    std::cout << algo << "加密结果:\n" << hexCipherData << std::endl;
6    std::cout << "----------------------------------\n";
7}
8
9void PrintDecrypt(const char* algo, const std::string& hexCipherData) {
10    std::cout << algo << "解密结果:\n" << hexCipherData << std::endl;
11    std::cout << "----------------------------------\n";
12}
13
14int main()
15
{
16    std::string plain{ "plain data" };
17
18    std::cout << "原始数据:" << plain << "\n-----\n";
19
20    PrintEncrypt("MD5", okcrypt::EncryptMD5(plain));
21    PrintEncrypt("Base64", okcrypt::EncryptBase64(plain));
22    PrintEncrypt("SHA256", okcrypt::EncryptSHA256(plain));
23    PrintEncrypt("SHA512", okcrypt::EncryptSHA512(plain));
24    PrintEncrypt("SHA3-256", okcrypt::EncryptSHA3_256(plain));
25    PrintEncrypt("SHA3-512", okcrypt::EncryptSHA3_512(plain));
26
27    try {
28        // DES
29        std::string cipher;
30        std::string recovered;
31        okcrypt::InitalizeDESKey();
32        std::cout << "des key: " << okcrypt::ToHex(okcrypt::GetDESKey()) << std::endl;
33        okcrypt::EncryptDES("text will be encryped with des", cipher);
34        PrintEncrypt("DES", okcrypt::ToHex(cipher));
35        okcrypt::DecryptDES(cipher, recovered);
36        PrintDecrypt("DES", recovered);
37
38        cipher.clear();
39        recovered.clear();
40
41        // 3DES
42        okcrypt::Initalize3DESKey();
43        std::cout << "3des key: " << okcrypt::ToHex(okcrypt::Get3DESKey()) << std::endl;
44        okcrypt::Encrypt3DES("text will be encryped with 3des", cipher);
45        PrintEncrypt("3DES", okcrypt::ToHex(cipher));
46        okcrypt::Decrypt3DES(cipher, recovered);
47        PrintDecrypt("3DES", recovered);
48
49        cipher.clear();
50        recovered.clear();
51
52        // AES
53        okcrypt::InitalizeAESKey();
54        std::cout << "aes key: " << okcrypt::ToHex(okcrypt::GetAESKey()) << std::endl;
55        okcrypt::EncryptAES("text will be encrypted with aes", cipher);
56        PrintEncrypt("AES", okcrypt::ToHex(cipher));
57        okcrypt::DecryptAES(cipher, recovered);
58        PrintDecrypt("AES", recovered);
59
60        cipher.clear();
61        recovered.clear();
62
63        // RSA
64        okcrypt::InitalizeRSAKeys();
65        std::cout << "rsa public key: " << okcrypt::ToHex(okcrypt::GetRSAPublicKey()) << std::endl;
66        okcrypt::EncryptRSA("text will be encrypted with rsa", cipher);
67        PrintEncrypt("RSA", okcrypt::ToHex(cipher));
68        okcrypt::DecryptRSA(cipher, recovered);
69        PrintDecrypt("RSA", recovered);
70    }
71    catch (const CryptoPP::Exception& e)
72    {
73        std::cerr << "Error: " << e.what() << std::endl;
74    }
75
76
77    std::cin.get();
78    return 0;
79}

输出结果:
其它没加的算法,以后会抽时间再加到okcrypt,本篇就到这里吧。

浏览 4
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报