Skip to content

Crypto++的使用

Crypto++是C++平台的加密库。

官网:https://www.cryptopp.com

本文使用的是Crypto++® Library 8.7.0版本,Release Date: 2022-08-07。

安装过程就不说了,不安装的话会在#include的时候找不到库。

ECDSA

对ECDSA进行了尝试。

生成密钥对

cpp
#include <iostream>
#include <cryptopp/eccrypto.h>
#include <cryptopp/osrng.h>
#include <cryptopp/hex.h>
#include <oids.h>

void printPrivateKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey);

void printPublicKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey);

int main() {
    CryptoPP::AutoSeededRandomPool rng;

    // 生成ECDSA密钥对
    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey privateKey;
    privateKey.Initialize(rng, CryptoPP::ASN1::secp256r1());

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey publicKey;
    privateKey.MakePublicKey(publicKey);

    // 输出密钥对
    printPrivateKey(privateKey);
    printPublicKey(publicKey);

    return 0;
}

void printPrivateKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey) {
    std::string privateKeyStr;

    CryptoPP::HexEncoder privateKeyEncoder(new CryptoPP::StringSink(privateKeyStr));
    privateKey.Save(privateKeyEncoder);
    privateKeyEncoder.MessageEnd();

    std::cout << "Private Key (hex): 0x" << privateKeyStr << std::endl;
}

void printPublicKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey) {
    std::string publicKeyStr;

    CryptoPP::HexEncoder publicKeyEncoder(new CryptoPP::StringSink(publicKeyStr));
    publicKey.Save(publicKeyEncoder);
    publicKeyEncoder.MessageEnd();

    std::cout << "Public Key (hex): 0x" << publicKeyStr << std::endl;
}

程序输出:

bash
Private Key (hex): 0x3041020100301306072A8648CE3D020106082A8648CE3D030107042730250201010420B7A27F63D22AA537DA9B277FB41C28E1986BCBD09AF449394CD9D942824F06C6
Public Key (hex): 0x3059301306072A8648CE3D020106082A8648CE3D030107034200044C2DEFDDC23725CA4A55722F13BD71DC00310426901E0527B5494A1DFAB18486FF35675D93EDB2166F020AE84524E4CDC72446C80E52B29D47E5D0B8D5C09290

Process finished with exit code 0

签名

cpp
#include <iostream>
#include <cryptopp/eccrypto.h>
#include <cryptopp/osrng.h>
#include <cryptopp/hex.h>
#include <oids.h>
#include <cryptopp/cryptlib.h>

void printPrivateKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey);

void printPublicKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey);

std::string fromHex(const std::string &from);

std::string toHex(const std::string &from);

std::string
sign(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &message);

std::string
signToHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &message);


bool verifyFromHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey,
                   const std::string &signatureHex, const std::string &message);

bool verify(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey, const std::string &signature,
            const std::string &message);

int main() {
    CryptoPP::AutoSeededRandomPool rng;

    // 生成ECDSA密钥对
    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey privateKey;
    privateKey.Initialize(rng, CryptoPP::ASN1::secp256r1());

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey publicKey;
    privateKey.MakePublicKey(publicKey);

    // 输出密钥对
    printPrivateKey(privateKey);
    printPublicKey(publicKey);

    /// ECDSA
    // 签名消息
    std::string message = "Hello, Crypto++!";
    std::string signature = sign(privateKey, message);
    std::string signatureHex = signToHex(privateKey, message);

    // 验证签名
    bool valid = verifyFromHex(publicKey, signatureHex, message) && verify(publicKey, signature, message);

    // 输出签名和验证结果
    std::cout << "Message: " << message << std::endl;
    std::cout << "Signature (hex): 0x" << signatureHex << std::endl;
    std::cout << "Signature Valid: " << (valid ? "true" : "false") << std::endl;

    return 0;
}

void printPrivateKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey) {
    std::string privateKeyStr;

    CryptoPP::HexEncoder privateKeyEncoder(new CryptoPP::StringSink(privateKeyStr));
    privateKey.Save(privateKeyEncoder);
    privateKeyEncoder.MessageEnd();

    std::cout << "Private Key (hex): 0x" << privateKeyStr << std::endl;
}

void printPublicKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey) {
    std::string publicKeyStr;

    CryptoPP::HexEncoder publicKeyEncoder(new CryptoPP::StringSink(publicKeyStr));
    publicKey.Save(publicKeyEncoder);
    publicKeyEncoder.MessageEnd();

    std::cout << "Public Key (hex): 0x" << publicKeyStr << std::endl;
}

std::string
sign(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &message) {
    CryptoPP::AutoSeededRandomPool rng;
    std::string signature;

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::Signer signer(privateKey);
    CryptoPP::StringSource signerStringSource(message, true, new CryptoPP::SignerFilter(rng, signer,
                                                                                        new CryptoPP::StringSink(
                                                                                                signature)));

    return signature;
}

std::string
signToHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &message) {
    CryptoPP::AutoSeededRandomPool rng;
    std::string signature;

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::Signer signer(privateKey);
    CryptoPP::StringSource signerStringSource(message, true, new CryptoPP::SignerFilter(rng, signer,
                                                                                        new CryptoPP::StringSink(
                                                                                                signature)));

    return toHex(signature);
}

bool verify(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey, const std::string &signature,
            const std::string &message) {
    bool valid = false;

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::Verifier verifier(publicKey);
    CryptoPP::StringSource verifierStringSource(signature + message, true,
                                                new CryptoPP::SignatureVerificationFilter(verifier,
                                                                                          new CryptoPP::ArraySink(
                                                                                                  reinterpret_cast<CryptoPP::byte *>(&valid),
                                                                                                  sizeof(bool))));
    return valid;
}

bool verifyFromHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey,
                   const std::string &signatureHex, const std::string &message) {
    //TODO:把16进制字符串转化为签名的时候出错
    std::string signature = fromHex(signatureHex);

    return verify(publicKey, signature, message);
}


std::string fromHex(const std::string &from) {
    std::string to;
    CryptoPP::StringSource hexStringSource(from, true,
                                           new CryptoPP::HexDecoder(new CryptoPP::StringSink(to)));

    return to;
}

std::string toHex(const std::string &from) {
    std::string to;
    CryptoPP::StringSource hexStringSource(from, true,
                                           new CryptoPP::HexEncoder(new CryptoPP::StringSink(to)));

    return to;
}

程序输出:

bash
Private Key (hex): 0x3041020100301306072A8648CE3D020106082A8648CE3D030107042730250201010420DF7A3D580D8F2676D852E5930F50468575E9B2526EA14D9A9F06971A8CC10553
Public Key (hex): 0x3059301306072A8648CE3D020106082A8648CE3D03010703420004BFBAD0BF5AEE8841F7CA233C0932CD4A48DF5CC8D591A5DA4EE9BAEB585D87D913179A5724FA1DB04FEB2FFB8083D4676D60EC4C0526026C33DABBFD5ECBD6EA
Message: Hello, Crypto++!
Signature (hex): 0xB8B36223EF4F212ED8B16F4844A7FC3C8046096E2B77D726A0770D8C917CA0943B9CAA2BEBCF6023A77A6A21E4C92F58D71E5A6FF00557C590EA0C458ECDEEBA
Signature Valid: true

Process finished with exit code 0

ECC 与 SHA256

代码是在上面ECDSA的基础上加的,并未删去ECDSA的代码。

cpp
#include <iostream>
#include <cryptopp/eccrypto.h>
#include <cryptopp/osrng.h>
#include <cryptopp/hex.h>
#include <oids.h>
#include <cryptopp/cryptlib.h>

void printPrivateKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey);

void printPublicKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey);

std::string fromHex(const std::string &from);

std::string toHex(const std::string &from);

std::string
sign(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &message);

std::string
signToHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &message);


bool verifyFromHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey,
                   const std::string &signatureHex, const std::string &message);

bool verify(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey, const std::string &signature,
            const std::string &message);

std::string
encrypt(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey, const std::string &message);

std::string
encryptToHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey, const std::string &message);

std::string
decrypt(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &ciphertext);

std::string
decryptFromHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey,
               const std::string &ciphertextHex);

std::string sha256Hex(const std::string &data);

int main() {
    CryptoPP::AutoSeededRandomPool rng;

    // 生成ECDSA密钥对
    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey privateKey;
    privateKey.Initialize(rng, CryptoPP::ASN1::secp256r1());

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey publicKey;
    privateKey.MakePublicKey(publicKey);

    // 输出密钥对
    printPrivateKey(privateKey);
    printPublicKey(publicKey);

    /// ECDSA
    // 签名消息
    std::string message = "Hello, Crypto++!";
    std::string signature = sign(privateKey, message);
    std::string signatureHex = signToHex(privateKey, message);

    // 验证签名
    bool valid = verifyFromHex(publicKey, signatureHex, message) && verify(publicKey, signature, message);

    // 输出签名和验证结果
    std::cout << "Message: " << message << std::endl;
    std::cout << "Signature (hex): 0x" << signatureHex << std::endl;
    std::cout << "Signature Valid: " << (valid ? "true" : "false") << std::endl;

    /// ECC
    // 加密
    std::string ciphertext = encrypt(publicKey, message);

    std::string ciphertextHex = encryptToHex(publicKey, message);

    // 解密
    std::string decryptedMessage = decrypt(privateKey, ciphertext);
    std::string decryptedMessageFromHex = decryptFromHex(privateKey, ciphertextHex);

    // 输出结果
    std::cout << "Original Message: " << message << std::endl;
    std::cout << "Encrypted Message (hex): 0x" << ciphertextHex << std::endl;
    std::cout << "Decrypted Message: " << decryptedMessage << std::endl;
    std::cout << "Decrypted Hex Message: " << decryptedMessageFromHex << std::endl;

    /// SHA256
    std::string hash = sha256Hex(message);
    std::cout << "SHA256 hash: " << hash << std::endl;

    return 0;
}

void printPrivateKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey) {
    std::string privateKeyStr;

    CryptoPP::HexEncoder privateKeyEncoder(new CryptoPP::StringSink(privateKeyStr));
    privateKey.Save(privateKeyEncoder);
    privateKeyEncoder.MessageEnd();

    std::cout << "Private Key (hex): 0x" << privateKeyStr << std::endl;
}

void printPublicKey(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey) {
    std::string publicKeyStr;

    CryptoPP::HexEncoder publicKeyEncoder(new CryptoPP::StringSink(publicKeyStr));
    publicKey.Save(publicKeyEncoder);
    publicKeyEncoder.MessageEnd();

    std::cout << "Public Key (hex): 0x" << publicKeyStr << std::endl;
}

std::string fromHex(const std::string &from) {
    std::string to;
    CryptoPP::StringSource hexStringSource(from, true,
                                           new CryptoPP::HexDecoder(new CryptoPP::StringSink(to)));

    return to;
}

std::string toHex(const std::string &from) {
    std::string to;
    CryptoPP::StringSource hexStringSource(from, true,
                                           new CryptoPP::HexEncoder(new CryptoPP::StringSink(to)));

    return to;
}

std::string
sign(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &message) {
    CryptoPP::AutoSeededRandomPool rng;
    std::string signature;

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::Signer signer(privateKey);
    CryptoPP::StringSource signerStringSource(message, true, new CryptoPP::SignerFilter(rng, signer,
                                                                                        new CryptoPP::StringSink(
                                                                                                signature)));

    return signature;
}

std::string
signToHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &message) {
    CryptoPP::AutoSeededRandomPool rng;
    std::string signature;

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::Signer signer(privateKey);
    CryptoPP::StringSource signerStringSource(message, true, new CryptoPP::SignerFilter(rng, signer,
                                                                                        new CryptoPP::StringSink(
                                                                                                signature)));

    return toHex(signature);
}

bool verify(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey, const std::string &signature,
            const std::string &message) {
    bool valid = false;

    CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::Verifier verifier(publicKey);
    CryptoPP::StringSource verifierStringSource(signature + message, true,
                                                new CryptoPP::SignatureVerificationFilter(verifier,
                                                                                          new CryptoPP::ArraySink(
                                                                                                  reinterpret_cast<CryptoPP::byte *>(&valid),
                                                                                                  sizeof(bool))));
    return valid;
}

bool verifyFromHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey,
                   const std::string &signatureHex, const std::string &message) {
    //TODO:把16进制字符串转化为签名的时候出错
    std::string signature = fromHex(signatureHex);

    return verify(publicKey, signature, message);
}


std::string
encrypt(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey, const std::string &message) {
    CryptoPP::AutoSeededRandomPool rng;
    std::string ciphertext;

    CryptoPP::ECIES<CryptoPP::ECP>::Encryptor encryptor(publicKey);
    CryptoPP::StringSource encryptorStringSource(message, true,
                                                 new CryptoPP::PK_EncryptorFilter(rng, encryptor,
                                                                                  new CryptoPP::StringSink(ciphertext)
                                                 )
    );

    return ciphertext;
}

std::string
encryptToHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PublicKey &publicKey, const std::string &message) {
    std::string ciphertext = encrypt(publicKey, message);

    std::string ciphertextHex = toHex(ciphertext);

    return ciphertextHex;
}


std::string
decrypt(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey, const std::string &ciphertext) {
    CryptoPP::AutoSeededRandomPool rng;
    std::string decryptedMessage;

    CryptoPP::ECIES<CryptoPP::ECP>::Decryptor decryptor(privateKey);
    CryptoPP::StringSource decryptorStringSource(ciphertext, true,
                                                 new CryptoPP::PK_DecryptorFilter(rng, decryptor,
                                                                                  new CryptoPP::StringSink(
                                                                                          decryptedMessage)
                                                 )
    );

    return decryptedMessage;
}

std::string
decryptFromHex(const CryptoPP::ECDSA<CryptoPP::ECP, CryptoPP::SHA256>::PrivateKey &privateKey,
               const std::string &ciphertextHex) {
    CryptoPP::AutoSeededRandomPool rng;
    std::string ciphertext = fromHex(ciphertextHex);

    std::string decryptedMessage;

    CryptoPP::ECIES<CryptoPP::ECP>::Decryptor decryptor(privateKey);
    CryptoPP::StringSource decryptorStringSource(ciphertext, true,
                                                 new CryptoPP::PK_DecryptorFilter(rng, decryptor,
                                                                                  new CryptoPP::StringSink(
                                                                                          decryptedMessage)
                                                 )
    );

    return decryptedMessage;
}

std::string sha256Hex(const std::string &data) {
    std::string hash;
    CryptoPP::SHA256 sha256;
    CryptoPP::StringSource source(data, true, new CryptoPP::HashFilter(sha256, new CryptoPP::HexEncoder(
            new CryptoPP::StringSink(hash))));
    return hash;
}

程序输出:

bash
Private Key (hex): 0x3041020100301306072A8648CE3D020106082A8648CE3D03010704273025020101042013EF286A25DA691FA334778E57854A3B3B5433AA59C1A50A079CCAE2C29E3E7B
Public Key (hex): 0x3059301306072A8648CE3D020106082A8648CE3D030107034200044A728F720A1238318414EFB63A7EC5405333E19918E45BC36C307AC236AC75E45E5B49FDD6DE1C42AA5D3E006CFC9BC11DA25F6FA018EC6A7DABEA348478140C
Message: Hello, Crypto++!
Signature (hex): 0xE69EFC191C9BD475611A3F04BCF26EF948DDB309EFCEEF80474A139546CA8450F58F222CFC6DAD16CA2B8567264D9684DFEB3D7C25660C7628A26ED376F08C2A
Signature Valid: true
Original Message: Hello, Crypto++!
Encrypted Message (hex): 0x04246E7A2B16DF57A93FFFEAAB4E04DC121532B88DFB09D36DAE3B1EEF3D9239D67ECEC3514778A83FB71CA66808AE94BE6CEB29E8BE8B099630FD80040B4283B8CDE2604C568C1BEFF186469CD44C25E01BFF875A502824DCDC437F1234AA20854C949928
Decrypted Message: Hello, Crypto++!
Decrypted Hex Message: Hello, Crypto++!
SHA256 hash: 9009F952CE7B1D25F58C83F59F96FE23C93B57B206EDB664F9162B47AC177AED

Process finished with exit code 0