Crypto++安装与使用

一、简介

Crypto++ 是一个免费开源的 C++ 密码学库,由 Wei Dai(美籍华裔)首次开发,当前由 Crypto++ 项目团队维护,源代码在 github 上进行托管。

二、安裝 Crypto++ 庫

1)套件安裝

# ubutnu安裝 Crypto++ 函式庫
sudo apt install libcrypto++-dev

2)自行编译安装

官网下载码源,或者从github clone。

wget https://cryptopp.com/cryptopp870.zip
unzip -a cryptopp870.zip -d cryptopp

cd cryptopp
#静态库编译【推荐】
make -j4  # 或者 make static  -j4 
#动态库编译
make shared  -j4 

# 測試 Crypto++ 函式庫
./cryptest.exe v

# 安装
sudo make install
# 或
make install PREFIX=./install_x86_64

安装pem包到cryptopp

  • 以 PEM 格式读取和写入密钥和参数。
git clone https://github.com/noloader/cryptopp-pem/* .git
cp cryptopp-pem/*  cryptopp
# 重新编译安装cryptopp

交叉编译

# 安装依赖,以aarch64为例
sudo apt install binutils-aarch64-linux-gnu-dbg binutils-aarch64-linux-gnu cpp-aarch64-linux-gnu \
g++-10-aarch64-linux-gnu g++-9-aarch64-linux-gnu g++-aarch64-linux-gnu g++ \
gcc-10-aarch64-linux-gnu-base gcc-9-aarch64-linux-gnu-base gcc-aarch64-linux-gnu \
pkg-config-aarch64-linux-gnu qemu-efi-aarch64 gcc arch-test

# 需指定编译器
make CXX=aarch64-linux-gnu-g++ CXXFLAGS="-O2 -fPIC -pipe -Wall -shared" -f GNUmakefile-cross  -j4

三、程序开发

c++ 使用Crypto++开发文章

1.示例1

ECB 模式、16字节长度的 key、PKCS7填充方式的场景下,使用 AES 算法进行加解密。

#include <iostream>
#include <string>
#include "cryptlib.h"
#include "aes.h"
#include "modes.h"
#include "files.h"
#include "osrng.h"
#include "hex.h"

using namespace CryptoPP;
using namespace std;

int main(int argc, char* argv[]) {
    // 建立隨機亂數產生器
    // AutoSeededRandomPool prng;
    // 將金鑰與 IV 放置於安全的記憶體空間
    // SecByteBlock key(AES::DEFAULT_KEYLENGTH); // 採用預設的金鑰長度(128 位元)
    // SecByteBlock key(AES::MAX_KEYLENGTH);  // 採用最長的金鑰長度(256 位元)
    // SecByteBlock key(24);                  // 自行指定金鑰長度(192 位元)
    // 產生隨機金鑰與 IV
    // prng.GenerateBlock(key, key.size());
    
    byte key[AES::DEFAULT_KEYLENGTH] = "abcd1234";

    // 原始資料
    std::string plain = "Crypto++ is a free C++ library for cryptography";

    // 用來儲存密文與明文的變數
    std::string cipher, encoded, recovered;

    std::cout << "key:" << key << std::endl;
    std::cout << "原始資料:" << plain << std::endl;

    try {
        // 採用 AES-ECB 加密
        ECB_Mode<AES>::Encryption e;

        // 設定金鑰
        e.SetKey(key, sizeof(key));

        // 進行加密
        StringSource s(plain, true,
            new StreamTransformationFilter(e,
                new StringSink(cipher)
            ) // StreamTransformationFilter
        ); // StringSource

    } catch(const Exception& e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    // Pretty print cipher text
    StringSource ss2( cipher, true,
        new HexEncoder(
            new StringSink( encoded )
        ) // HexEncoder
    ); // StringSource
    std::cout << "cipher text: " << encoded << std::endl;

    try {
        // 採用 AES-ECB 解密
        ECB_Mode<AES>::Decryption d;

        // 設定金鑰與 IV
        d.SetKey(key, sizeof(key));

        // 進行解密
        StringSource s(cipher, true,
            new StreamTransformationFilter(d,
                new StringSink(recovered)
            ) // StreamTransformationFilter
        ); // StringSource

    } catch(const Exception& e) {
        std::cerr << e.what() << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "解開的明文:" << recovered << std::endl;

    return EXIT_SUCCESS;
}

2.示例2

通过RSA对数据进行签署和验签。

#include <string>
#include <iostream>
#include <cstdlib>
#include "rsa.h"
#include "pssr.h"
#include "sha.h"
#include "osrng.h"
#include "secblock.h"

#include "files.h"
#include "hex.h"
#include <pem.h>

using namespace CryptoPP;
using namespace std;

void SaveKey( const RSA::PublicKey& PublicKey, const string& filename, const string format)
{
    if (format == "pem") {
        FileSink file( filename.c_str(), true /*binary*/ );
        CryptoPP::PEM_Save(file, PublicKey);
    } else if (format == "binary") {
        // DER Encode Key - X.509 key format
        PublicKey.Save(
            FileSink( filename.c_str(), true /*binary*/ ).Ref()
        );
    }
}

void SaveKey( const RSA::PrivateKey& PrivateKey, const string& filename, const string format)
{
    if (format == "pem") {
        FileSink file( filename.c_str(), true /*binary*/ );
        CryptoPP::PEM_Save(file, PrivateKey);
    } else if (format == "binary") {
        // DER Encode Key - PKCS #8 key format
        PrivateKey.Save(
            FileSink( filename.c_str(), true /*binary*/ ).Ref()
        );
    }
}

void LoadKey( const string& filename, RSA::PublicKey& PublicKey, const string format)
{
    if (format == "pem") {
        FileSource file(filename.c_str(), true, NULL, true /*binary*/ );
        PEM_Load(file, PublicKey);
    } else  if (format == "binary") {
        // DER Encode Key - X.509 key format
        PublicKey.Load(
            FileSource(filename.c_str(), true, NULL, true /*binary*/ ).Ref()
        );
    }
}

void LoadKey( const string& filename, RSA::PrivateKey& PrivateKey, const string format)
{
    if (format == "pem") {
        FileSource file(filename.c_str(), true, NULL, true /*binary*/ );
        PEM_Load(file, PrivateKey);
    } else  if (format == "binary") {
        // DER Encode Key - PKCS #8 key format
        PrivateKey.Load(
            FileSource(filename.c_str(), true, NULL, true /*binary*/ ).Ref()
        );
    }
}

int main(int argc, char* argv[]) {

    // 建立隨機亂數產生器
    AutoSeededRandomPool prng;

    try {
        // 產生 RSA 私鑰
        RSA::PrivateKey rsaPrivKey;
        rsaPrivKey.GenerateRandomWithKeySize(prng, 1024);
        // 產生對應的 RSA 公鑰
        RSA::PublicKey rsaPubKey(rsaPrivKey);
        SaveKey(rsaPrivKey, "rsaPrivKey.pem", "pem");
        SaveKey(rsaPubKey, "rsaPubkey.pem", "binary");

        // RSA::PrivateKey rsaPrivKey;
        // RSA::PublicKey rsaPubKey;
        // LoadKey("rsaPrivKey.pem", rsaPrivKey);
        // LoadKey("rsaPubkey.pem", rsaPubKey);

        // 資料內容
        std::string message = "Yoda said, Do or Do Not. There is not try.";

        // 數位簽章
        std::string signature;

        // 簽署器
        RSASS<PSS, SHA256>::Signer signer(rsaPrivKey);

        // 對資料進行簽署
        StringSource(message, true,
            new SignerFilter(prng, signer,
                new StringSink(signature)
            ) // SignerFilter
        ); // StringSource

        std::string encoded;
        StringSource ss2( signature, true,
            new HexEncoder(
                new StringSink( encoded )
            ) // HexEncoder
        ); // StringSource
        std::cout << "簽署: " << encoded << std::endl;

        // 簽章驗證器
        RSASS<PSS, SHA256>::Verifier verifier(rsaPubKey);

        // 驗證數位簽章
        StringSource(message+signature, true,
            new SignatureVerificationFilter(
                verifier, NULL,
                SignatureVerificationFilter::THROW_EXCEPTION
                | SignatureVerificationFilter::SIGNATURE_AT_END
            ) // SignatureVerificationFilter
        ); // StringSource

        std::cout << "簽章驗證成功" << std::endl;

    } catch(CryptoPP::Exception& e) {
        std::cerr << e.what() << std::endl;
    }
    return EXIT_SUCCESS;
}

参考

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

推荐阅读更多精彩内容