C++ Crypto++

Da Andreabont's Wiki.

Crypto++ è una libreria crittografica per il C++. La documentazione ufficiale è consultabile qui.

Compilare

g++ <file.cpp> -lcryptopp

Gestione della pipeline

Crypto++ fornisce un sistema di pipeline per eseguire efficacemente gli algoritmi su dati il più possibile generici. (per maggiori informazioni consultare qui) Si dividono in:

Source

Sorgenti dei dati da immettere della pipeline.

Sink

Destinazione dei dati provenienti dalla pipeline.

Filter

Gestiscono una trasformazione dei dati nella pipeline.

StreamTransformation

I cifrari a blocchi possono lavorare in differenti modalità che in Crypto++ prendono il nome di StreamTransformation, per maggiori informazioni teoriche consultare qui.

  • CFB: La cifratura avviene sul flusso di dati, non è necessario preoccuparsi dei blocchi. (La più usata)
  • OFB
  • CTR
  • ECB: La cifratura avviene indipendentemente per ogni blocco di 64 bit, non è consigliabile per testi troppo lunghi
  • CBC: La cifratura avviene concatenando i blocchi da 64 bit. Rende sicuro cifrare testi più lunghi
  • CCM: Cifratura che garantisce la autenticità del messaggio
  • GCM: Cifratura che garantisce la autenticità del messaggio

Hash

Chiamata diretta all'algoritmo

#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include "cryptopp/md5.h"
#include "cryptopp/hex.h"
#include <iostream>

int main () {
    
    byte digest[CryptoPP::Weak::MD5::DIGESTSIZE];
    std::string message = "abcdefghijklmnopqrstuvwxyz";

    CryptoPP::Weak::MD5().CalculateDigest( digest, (const byte*)message.c_str(), message.length() );

    CryptoPP::HexEncoder encoder;
    std::string output;

    encoder.Attach( new CryptoPP::StringSink( output ) );
    encoder.Put( digest, sizeof(digest) );
    encoder.MessageEnd();

    std::cout << output << std::endl;
}

Uso di HashFilter

#include <iostream>
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
#include <cryptopp/filters.h> 

int main () {

    CryptoPP::SHA256 hash;
    std::string message = "abcdefghijklmnopqrstuvwxyz";
    std::string digest;
 
    CryptoPP::StringSource ss(message, true, 
        new CryptoPP::HashFilter(
            hash,
            new CryptoPP::HexEncoder(new CryptoPP::StringSink(digest))
        )
     );

    std::cout << digest << std::endl;
    
}

Uso di ChannelSwitch per combinare più algoritmi

#include <iostream>
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
#include <cryptopp/channels.h> 
#include <cryptopp/filters.h> 

int main () {

    std::string message = "abcdefghijklmnopqrstuvwxyz";
    std::string sha1_string, sha224_string, sha256_string, sha512_string;

    CryptoPP::SHA1 sha1;
    CryptoPP::SHA224 sha224;
    CryptoPP::SHA256 sha256;
    CryptoPP::SHA512 sha512;

    CryptoPP::HashFilter sha1_filter(sha1, new CryptoPP::HexEncoder(new CryptoPP::StringSink(sha1_string)));
    CryptoPP::HashFilter sha224_filter(sha224, new CryptoPP::HexEncoder(new CryptoPP::StringSink(sha224_string)));
    CryptoPP::HashFilter sha256_filter(sha256, new CryptoPP::HexEncoder(new CryptoPP::StringSink(sha256_string)));
    CryptoPP::HashFilter sha512_filter(sha512, new CryptoPP::HexEncoder(new CryptoPP::StringSink(sha512_string)));

    CryptoPP::ChannelSwitch cs;
    cs.AddDefaultRoute(sha1_filter);
    cs.AddDefaultRoute(sha224_filter);
    cs.AddDefaultRoute(sha256_filter);
    cs.AddDefaultRoute(sha512_filter);

    CryptoPP::StringSource ss(message, true, new CryptoPP::Redirector(cs));

    std::cout << "Message: " << message << std::endl;
    std::cout << "SHA-1: " << sha1_string << std::endl;
    std::cout << "SHA-224: " << sha224_string << std::endl;
    std::cout << "SHA-256: " << sha256_string << std::endl;
    std::cout << "SHA-512: " << sha512_string << std::endl;

}

Cifrare e decifrare

Cifratura simmetrica

Per questo esempio useremo la modalità CFB e il cifrario AES.

#include <iostream>
#include <string>
#include <cryptopp/modes.h> 
#include <cryptopp/osrng.h> 

int main () {

    std::string chiaro = "Ciao mondo!";
    std::string codificato, decodificato;

    // Random generator
    CryptoPP::AutoSeededRandomPool random;

    // Generazione della chiave casuale (Può essere di 16, 24, o 32 byte)
    CryptoPP::SecByteBlock key(0x00, CryptoPP::AES::DEFAULT_KEYLENGTH);
    random.GenerateBlock(key, key.size());

    // Generazione del vettore di inizializzazione casuale
    byte iv[CryptoPP::AES::BLOCKSIZE];
    random.GenerateBlock(iv, CryptoPP::AES::BLOCKSIZE);

    // Cifrare
    CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption encoder(key, key.size(), iv);

    CryptoPP::StringSource ss1(chiaro, true, 
        new CryptoPP::StreamTransformationFilter(
            encoder,
            new CryptoPP::StringSink(codificato)
        )      
    );

    std::cout << "Codificato:   " << codificato << std::endl;
    
    // Decfrare
    CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption decoder(key, key.size(), iv);

    CryptoPP::StringSource ss2(codificato, true, 
        new CryptoPP::StreamTransformationFilter(
            decoder,
            new CryptoPP::StringSink(decodificato)
        )      
    );

    std::cout << "Decodificato: " << decodificato << std::endl;

}

Cifratura asimmetrica

L'esempio utilizza l'algoritmo RSA in modalità OAEP con SHA.

#include <iostream>
#include <string>
#include <cryptopp/osrng.h> 
#include <cryptopp/hex.h>
#include <cryptopp/rsa.h>

int main () {

    std::string chiaro = "Ciao mondo!";
    std::string codificato, decodificato;

    // Random generator
    CryptoPP::AutoSeededRandomPool random;

    // Generazione della coppia di chiavi
    CryptoPP::InvertibleRSAFunction params;
    params.GenerateRandomWithKeySize(random, 3072);

    CryptoPP::RSA::PrivateKey privateKey(params);
    CryptoPP::RSA::PublicKey publicKey(params);

    // Cifrare
    CryptoPP::RSAES<CryptoPP::OAEP<CryptoPP::SHA>>::Encryptor encoder(publicKey);

    CryptoPP::StringSource ss1(chiaro, true, 
        new CryptoPP::PK_EncryptorFilter(
            random,
            encoder,
            new CryptoPP::StringSink(codificato)
        )      
    );

    std::cout << "Codificato:   " << codificato << std::endl;
    
    // Decfrare
    CryptoPP::RSAES<CryptoPP::OAEP<CryptoPP::SHA>>::Decryptor decoder(privateKey);

    CryptoPP::StringSource ss2(codificato, true, 
        new CryptoPP::PK_DecryptorFilter(
            random,
            decoder,
            new CryptoPP::StringSink(decodificato)
        )      
    );

    std::cout << "Decodificato: " << decodificato << std::endl;

}