转:https://blog.csdn.net/GuoXuan_CHN/article/details/80532258
基于Crypto++密码库的ECIES和ECDSA算法的联合使用
转载请注明出处
Auteur:GX
CSDN:GuoXuan_CHN
使用背景
毕设要求使用ECC椭圆曲线加密算法为用户信息加密,并数字签名。鉴于设计要求,ECIES的公私钥同样为ECDSA的公私钥。数字签名是后加部分。在已完成的设计部分中,ECIES的公私钥已将转化为std::string类型,在最小改动前提下,做出程序。
软件平台
Crypto++ - 7.0.0
MacBook pro - 10.13.4
GCC - Configured with: –prefix=/Applications/Xcode.app/Contents/Developer/usr –with-gxx-include-dir=/usr/include/c++/4.2.1;Apple LLVM version 9.1.0 (clang-902.0.39.1)
设计语言 - C++
用前必读
在中文程序员网站上,有关Crypto++的ECDSA的使用Demo很少。我是查看Crypto++官网上的维基百科中的使用介绍来写出的。本文章并非旨在教学,而是旨在记录,其中我所提供的Demo根据我自身需求有所更改。如果本文章不能帮助你,请查看Crypto++官网中您所需求的函数的使用方法。本文的使用方法是我偶然发现,并尝试出可用,但我并不知道原理,如果您放在您的程序中,出现任何问题,我不负任何责任
发现过程
ECC公钥(第一组) - 3059301306072A8648CE3D020106082A8648CE3D0301070342000432AAB20C1C02D8844834D5AAC7E12814A53266AA5F0350190A9C1A9C43AA4178FFDC04D0785EE52676D061B5D836FEB34D766E710CE2196B5ADAF7876E805C01
ECC私钥(第一组)- 3041020100301306072A8648CE3D020106082A8648CE3D030107042730250201010420C044B0620BAC02DA779426C1292A6398AA7EB99D9F624E9921186211AFFB6117
ECC公钥(第二组)- 3059301306072A8648CE3D020106082A8648CE3D030107034200045EF50890EDC7FAAA2420533FA500AC897236DDE114A4FE7215B48F908585208E3DD9F1CEB1D923EEDB3C95027D82FE6AF64F82CB61631DEB7B68028899D7328C
ECC私钥(第二组)- 3041020100301306072A8648CE3D020106082A8648CE3D030107042730250201010420FD9BB947E95A503645CAD68DC70E21E3D04AF2C52206B9057ED52D94299E93BE
ECC公钥(第三组)- 3059301306072A8648CE3D020106082A8648CE3D0301070342000419514747D4D4F91C484DC529D1695E05D8383D04EB6D84A0BF40C4641CB3490FF17BF5ECA97A7C0F325D62C5EE2180D9C5ABC977CBEE1A40B45F5B32EB1F61F3
ECC私钥(第三组)- 3041020100301306072A8648CE3D020106082A8648CE3D0301070427302502010104203DB7FB2335C3368485C1A51AD9F36FA3FF4B2BC187D0D3FAE40977066EE74116
是的,你可能发现了。ECC公钥的前54个字符是相通的,每次变化的只是后面的。同理,ECC私钥每次变化的也只是前70个字符,我猜想,是不是后面变化的才是公私钥。经过尝试,可以使用充当ECDSA的公私钥。
ECIES加解密Demo
该Demo是我从网上找到的,网上有很多Demo,但是有些我发现用不了,在可用的Demo中最符合我需求的是这个,同时,我稍微进行了更改。如有侵权,告知必删。
#include
#include "eccrypto.h"
#include "osrng.h"
#include "oids.h"
#include "hex.h"
#include "filters.h"
#ifndef ECC_ENCRYPTION_ALGORITHM_H_
#define ECC_ENCRYPTION_ALGORITHM_H_
#include
class EccEncryption
{
public:
/// This method is used to generate keys for ECC encryption algorithm
///
/// \param[in] uiKeySize, length of key
/// \param[out] sPrivateKey, private key
/// \param[out] sPublicKey, public key
void GenerateEccKeys(unsigned int uiKeySize, std::string& sPrivateKey, std::string& sPublicKey);
/// This method is used to encrypt the input message using public key
///
/// \param[in] sPublicKey, public key generated by the first method
/// \param[out] sMsgToEncrypt, message to encryppt
/// \return the message encrypted using the input public key
std::string Encrypt(const std::string& sPublicKey, const std::string& sMsgToEncrypt);
/// This method is used to decrypt the input message using private key
///
/// \param[in] sPrivateKey, private key used to decrypt the cipher text
/// \param[in] sMsgToDecrypt, cipher text used to decrypt to get the plain text
/// \return decrypted plain text
std::string Decrypt(const std::string& sPrivateKey, const std::string& sMsgToDecrytp);
};
#endif
void EccEncryption::GenerateEccKeys(unsigned int uiKeySize, std::string& sPrivateKey, std::string& sPublicKey)
{
using namespace CryptoPP;
// Random pool, the second parameter is the length of key
// 随机数池,第二个参数是生成密钥的长
AutoSeededRandomPool rnd(false, 256);
ECIES
ECIES
// Generate private key
privateKey.Initialize(rnd, ASN1::secp256r1());
// Generate public key using private key
privateKey.MakePublicKey(publicKey);
ECIES
HexEncoder pubEncoder(new StringSink(sPublicKey));
publicKey.DEREncode(pubEncoder);
pubEncoder.MessageEnd();
ECIES
HexEncoder prvEncoder(new StringSink(sPrivateKey));
privateKey.DEREncode(prvEncoder);
prvEncoder.MessageEnd();
}
std::string EccEncryption::Encrypt(const std::string& sPublicKey, const std::string& sMsgToEncrypt)
{
using namespace CryptoPP;
// If to save the keys into a file, FileSource should be replace StringSource
StringSource pubString(sPublicKey, true, new HexDecoder);
ECIES
// Calculate the length of cipher text
size_t uiCipherTextSize = encryptor.CiphertextLength(sMsgToEncrypt.size());
std::string sCipherText;
sCipherText.resize(uiCipherTextSize);
RandomPool rnd;
encryptor.Encrypt(rnd, (byte*)(sMsgToEncrypt.c_str()), sMsgToEncrypt.size(), (byte*)(sCipherText.data()));
return sCipherText;
}
std::string EccEncryption::Decrypt(const std::string& sPrivateKey, const std::string& sMsgToDecrytp)
{
using namespace CryptoPP;
StringSource privString(sPrivateKey, true, new HexDecoder);
ECIES
auto sPlainTextLen = decryptor.MaxPlaintextLength(sMsgToDecrytp.size());
std::string sDecryText;
sDecryText.resize(sPlainTextLen);
RandomPool rnd;
decryptor.Decrypt(rnd, (byte*)sMsgToDecrytp.c_str(), sMsgToDecrytp.size(), (byte*)sDecryText.data());
return sDecryText;
}
int main()
{
std::string sStrToTest = std::string("Hello world. This is an example of Ecc encryption algorithm of Crypto++ open source library.");
EccEncryption ecc;
std::string sPrivateKey, sPublicKey;
ecc.GenerateEccKeys(1024, sPrivateKey, sPublicKey);
std::cout << "Generated private key is : "<< std::endl;
std::cout << sPrivateKey << std::endl;
std::cout << "***********************************************************" << std::endl;
std::cout << "Generated public key is : "<< std::endl;
std::cout << sPublicKey << std::endl;
std::cout << "***********************************************************" << std::endl;
std::cout << "The message to be encrypted is : " << std::endl;
std::cout << sStrToTest << std::endl;
std::cout << "***********************************************************" << std::endl;
std::string sEncryptResult = ecc.Encrypt(sPublicKey, sStrToTest);
std::cout << "The result of encrypt is : " << std::endl;
std::cout << sEncryptResult << std::endl;
std::cout << "***********************************************************" << std::endl;
std::string sDecryptResult = ecc.Decrypt(sPrivateKey, sEncryptResult);
std::cout << "The result of decrypt is : " << std::endl;
std::cout << sDecryptResult << std::endl;
std::cout << "***********************************************************" << std::endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
ECIES-ECSDSA联合使用Demo
/*
auteur:GX
CSDN:GuoXuan_CHN
*/
#include
#include
#include
#include "eccrypto.h"
#include "osrng.h"
#include "oids.h"
#include "hex.h"
#include "filters.h"
#include "des.h"
using namespace std;
CryptoPP::ECIES
CryptoPP::ECIES
string sPrivateKey, sPublicKey;
void GenerateEccKeys()
{
using namespace CryptoPP;
// Random pool, the second parameter is the length of key
// 随机数池,第二个参数是生成密钥的长
AutoSeededRandomPool rnd(false, 256);
// Generate private key
// 生成私钥
ePrivateKey.Initialize(rnd, ASN1::secp256r1());
// Generate public key using private key
// 用私钥生成密钥
ePrivateKey.MakePublicKey(ePublicKey);
HexEncoder pubEncoder(new StringSink(sPublicKey));
ePublicKey.DEREncode(pubEncoder);
pubEncoder.MessageEnd();
HexEncoder prvEncoder(new StringSink(sPrivateKey));
ePrivateKey.DEREncode(prvEncoder);
prvEncoder.MessageEnd();
}
string signe (string message)
{
std::string signature="";
//数字签名过程
CryptoPP::ECDSA
std::string exp = sPrivateKey.substr(70);
CryptoPP::HexDecoder decoder;
decoder.Put((CryptoPP::byte *)&exp[0], exp.size());
decoder.MessageEnd();
CryptoPP::Integer x;
x.Decode(decoder, decoder.MaxRetrievable());
privateKey.Initialize(CryptoPP::ASN1::secp256r1(), x);
CryptoPP::ECDSA
CryptoPP::AutoSeededRandomPool prng;
//签名结果
signature = "";
CryptoPP::StringSource s( message, true /*pump all*/,
new CryptoPP::SignerFilter( prng,
signer,
new CryptoPP::StringSink( signature )
) // SignerFilter
); // StringSource
return signature;
//签名过程结束
}
bool VerifierSignature(string signature,string message)
{
std::string pt="";
//验签过程
CryptoPP::ECDSA
pt = sPublicKey.substr(54);
CryptoPP::HexDecoder decoder;
decoder.Put((CryptoPP::byte *)&pt[0], pt.size());
decoder.MessageEnd();
CryptoPP::ECP::Point q;
size_t len = decoder.MaxRetrievable();
q.identity = false;
q.x.Decode(decoder, len/2);
q.y.Decode(decoder, len/2);
publicKey.Initialize( CryptoPP::ASN1::secp256r1(), q );
CryptoPP::ECDSA
// Result of the verification process
bool result = false;
CryptoPP::StringSource ss( signature+message, true /*pump all*/,
new CryptoPP::SignatureVerificationFilter(
verifier,
new CryptoPP::ArraySink((CryptoPP::byte *)&result, sizeof(result) )
)
);
return result;
}
int main()
{
std::string message = "Yoda said, Do or do not. There is no try.";
std::string signature="";
bool result = false;
GenerateEccKeys();
signature = signe (message);
result = VerifierSignature(signature,message);
cout << "****** tester la bon*****" << endl;
cout << result << endl;
result = VerifierSignature(signature,"1234567890");
cout << "****** tester la mauvais*****" << endl;
cout << result << endl;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
编译指令
该指令为在我本机上使用的指令,请合理更改
g++ Demo_ECDSA.cpp -g -o prog -I /usr/local/include/cryptopp -lcryptopp
---------------------
作者:GuoXuan_CHN
来源:CSDN
原文:https://blog.csdn.net/GuoXuan_CHN/article/details/80532258?utm_source=copy
版权声明:本文为博主原创文章,转载请附上博文链接!