1. 程式人生 > >基於Crypto++密碼庫的ECIES和ECDSA算法的聯合使用

基於Crypto++密碼庫的ECIES和ECDSA算法的聯合使用

roc cbo out CP b2b 數字 lan 3.4 should

基於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;

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:www.thd178.com/: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(www.meiwanyule.cn ));
    decoder.MessageEnd();

    CryptoPP::Integer x;
    x.Decode(decoder, decoder.MaxRetrievable(www.huachengj1980.com/));

    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 www.536611.cn  *)&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 /www.wanmeiyuele.cn  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(www.636591.cn);

    signature = signe (message);

    result = VerifierSignature(signature,message);
    cout << "****** tester la bon*****" www.douniu157.com<< endl;
    cout << result << endl;

    result = VerifierSignature(signature,"1234567890");
    cout << "****** tester www.dejiaylsmile.cn  la mauvais*****" www.wmyl11.com<< endl;
    cout << result <www.leyouzaixian2.com< endl;

基於Crypto++密碼庫的ECIES和ECDSA算法的聯合使用