基于Crypto++密码库的ECIES和ECDSA算法的联合使用

转: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 <iostream>

#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<string>

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<ECP>::PrivateKey  privateKey;

    ECIES<ECP>::PublicKey  publicKey;

    // Generate private key

    privateKey.Initialize(rnd, ASN1::secp256r1());

    // Generate public key using private key

    privateKey.MakePublicKey(publicKey);

    ECIES<ECP>::Encryptor encryptor(publicKey);

    HexEncoder pubEncoder(new StringSink(sPublicKey));

    publicKey.DEREncode(pubEncoder);

    pubEncoder.MessageEnd();

    ECIES<ECP>::Decryptor decryptor(privateKey);

    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<ECP>::Encryptor encryptor(pubString);

    // 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<ECP>::Decryptor decryptor(privString);

    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 <fstream>

#include <string>

#include <iostream>

#include "eccrypto.h"

#include "osrng.h"

#include "oids.h"

#include "hex.h"

#include "filters.h"

#include "des.h"

using namespace std;

CryptoPP::ECIES<CryptoPP::ECP>::PrivateKey  ePrivateKey;

CryptoPP::ECIES<CryptoPP::ECP>::PublicKey  ePublicKey;

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<CryptoPP::ECP, CryptoPP::SHA1>::PrivateKey privateKey;

    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::ECP, CryptoPP::SHA1>::Signer signer( privateKey );

    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<CryptoPP::ECP, CryptoPP::SHA1>::PublicKey publicKey;

    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<CryptoPP::ECP,CryptoPP::SHA1>::Verifier verifier(publicKey);

    // 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

版权声明:本文为博主原创文章,转载请附上博文链接!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容