代码改变世界

crypto++

2017-12-28 17:48  woodzcl  阅读(442)  评论(0编辑  收藏  举报

CryptoPP库是一个C++书写的加密算法库,很棒。

在如今的抛却数字证书体系下,只关注公私钥对的情况下,我认为存粹的加解密算法库很有市场,虽然我以前觉得PolarSSL的加解密算法实现不错,但不影响我对CryptoPP的热情

今天,介绍一下,CryptoPP的椭圆曲线加/解密和签名/延签问题,当然是提供源码来说话了

——————————————————————————————————————————

//ecc-enc-dec.h

#ifndef ECC_ENC_DEC_H

#define ECC_ENC_DEC_H

 

#include <string>

 

void genEccEncKeys(unsigned int uiKeySize, std::string &priKey, std::string &pubKey);

void genEccSignKeys(unsigned int uiKeySize, std::string &priKey, std::string &pubKey);

std::string ecc_pri_signature(const std::string priKey, const std::string msgToSign);

std::string ecc_pub_encrypt(const std::string pubKey, const std::string msgToEncrypt);

std::string ecc_pri_decrypt(const std::string priKey, const std::string msgToDecrypt);

int ecc_pub_verify(const std::string pubKey, const std::string msgToSign, const std::string msgSigned);

 

#endif

 

//ecc-enc-dec.c

#include "ecc-enc-dec.h"

#include "eccrypto.h"

#include "osrng.h"

#include "oids.h"

#include "hex.h"

#include "filters.h"

 

using namespace CryptoPP;

 

void genEccEncKeys(unsigned int uiKeySize, std::string &priKey, std::string &pubKey)

{

    AutoSeededRandomPool rnd(false, uiKeySize);

    ECIES<ECP>::PrivateKey privateKey;

    ECIES<ECP>::PublicKey publicKey;

 

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

    privateKey.MakePublicKey(publicKey);

       

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

    HexEncoder pubEncoder(new StringSink(pubKey));

    encryptor.DEREncode(pubEncoder);

    pubEncoder.MessageEnd();

 

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

    HexEncoder priEncoder(new StringSink(priKey));

    decryptor.DEREncode(priEncoder);

    priEncoder.MessageEnd();

}

 

void genEccSignKeys(unsigned int uiKeySize, std::string &priKey, std::string &pubKey)

{

    AutoSeededRandomPool rnd(false, uiKeySize);

    ECDSA<ECP, SHA256>::PrivateKey privateKey;

    ECDSA<ECP, SHA256>::PublicKey publicKey;

 

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

    privateKey.MakePublicKey(publicKey);

 

    StringSink priSs(priKey);

    privateKey.Save(priSs);

 

    StringSink pubSs(pubKey);

    publicKey.Save(pubSs);

}

 

std::string ecc_pri_signature(const std::string priKey, const std::string msgToSign)

{

    std::string signedText;

    ECDSA<ECP, SHA256>::PrivateKey privateKey;

 

    StringSource Ss(priKey, true);

    privateKey.Load(Ss);

 

    ECDSA<ECP, SHA256>::Signer signer(privateKey);

    size_t siglen = signer.MaxSignatureLength();

    signedText.resize(siglen);

 

    RandomPool rnd;

 

    siglen = signer.SignMessage(rnd, (byte*)msgToSign.data(), msgToSign.size(), (byte*)signedText.data());

    signedText.resize(siglen);

 

    return signedText;

}

 

std::string ecc_pub_encrypt(const std::string pubKey, const std::string msgToEncrypt)

{

    std::string cipherText;

   

    // if to save the key into a file, FileSource should be replace StringSource

    StringSource pubString(pubKey, true, new HexDecoder);

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

    size_t uiCipherTextSize = encryptor.CiphertextLength(msgToEncrypt.size());

    cipherText.resize(uiCipherTextSize);

 

    RandomPool rnd;

   

    encryptor.Encrypt(rnd, (byte*)msgToEncrypt.c_str(), msgToEncrypt.size(), (byte*)cipherText.data());

 

    return cipherText;

}

 

std::string ecc_pri_decrypt(const std::string priKey, const std::string msgToDecrypt)

{

    std::string decryptText;

 

    StringSource priString(priKey, true, new HexDecoder);

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

    size_t uiDecryptTextSize = decryptor.MaxPlaintextLength(msgToDecrypt.size());

    decryptText.resize(uiDecryptTextSize);

 

    RandomPool rnd;

 

    decryptor.Decrypt(rnd, (byte*)msgToDecrypt.c_str(), msgToDecrypt.size(), (byte*)decryptText.data());

 

    return decryptText;

}

 

int ecc_pub_verify(const std::string pubKey, const std::string msgToSign, const std::string msgSigned)

{

    ECDSA<ECP, SHA256>::PublicKey publicKey;

    StringSource Ss(pubKey, true);

    publicKey.Load(Ss);

    RandomPool rnd;

    publicKey.Validate(rnd, 3);

 

    ECDSA<ECP, SHA256>::Verifier verifier(publicKey);

 

    bool result = verifier.VerifyMessage((byte*)msgToSign.data(), msgToSign.size(), (byte*)msgSigned.data(), msgSigned.size());

    if (result)

    {

        return 1;

    }

    else

    {

        return 0;

    }

}

//ecc-test.c

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

 

#include "ecc-enc-dec.h"

 

int main()

{

    std::string srcText = std::string("Hello world.");

    std::string enc_priKey, enc_pubKey;

   

    genEccEncKeys(1024, enc_priKey, enc_pubKey);

 

    std::string encryptResult = ecc_pub_encrypt(enc_pubKey, srcText);

    printf("public key enc result: %s--\nlength: %d\n", encryptResult.c_str(), (int)encryptResult.size());

 

    std::string decryptResult = ecc_pri_decrypt(enc_priKey, encryptResult);

    printf("private key dec result: %s--\nlength: %d\n", decryptResult.c_str(), (int)decryptResult.size());

 

    std::string sign_priKey, sign_pubKey;

 

    genEccSignKeys(1024, sign_priKey, sign_pubKey);

 

    std::string signedResult = ecc_pri_signature(sign_priKey, srcText);

    printf("private key sign result: %s--\nlength: %d\n", signedResult.c_str(), (int)signedResult.size());

 

    int bVerify = ecc_pub_verify(sign_pubKey, srcText, signedResult);

    printf("public key verify result: %d\n", 0==bVerify?false:true);

 

    return 0;

}

//result

# ./ecc-test
public key enc result: 񾒦(YR¨º͂j(&Y펠⥣`풶±ȍ줊\aR;ĬX8ܒ0,(ÿ,5--
length: 165
private key dec result: Hello world.--
length: 12
private key sign result: ¶µZH!ܻpn_ᯕ0R¤H--
length: 132
public key verify result: 1

Finally:

这里是非对称ECC算法,数学理论部分我就没打算搞懂!!

CryptoPP的问题是编译出来的应用至少都在15M左右,也就是太大了。