基于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

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

推荐阅读更多精彩内容