Sosemanuk

From Crypto++ Wiki
Jump to: navigation, search

Sosemanuk is a stream cipher developed by Come Berbain, Olivier Billet, Anne Canteaut, Nicolas Courtois, Henri Gilbert, Louis Goubin, Aline Gouget, Louis Granboulan, Cédric Lauradoux, Marine Minier, Thomas Pornin and Hervé Sibert. Also see Sosemanuk, a fast software-oriented stream cipher.

If you are used to working in languages like Jave or libraries like OpenSSL, then you might want to visit the Init-Update-Final wiki page. Crypto++ provides the transformation model, but its not obvious because its often shrouded behind Pipelines.

Note: if your project is using encryption alone to secure your data, encryption alone is usually not enough. Please take a moment to read Authenticated Encryption and understand why you should consider using a block cipher and mode like CCM, GCM, or EAX.

Encryption and Decryption

The following example shows you how to use Sosemanuk::Encryption and Sosemanuk::Decryption. &cipher[0] may look odd, but its how to get the non-const pointer from a std::string.

#include "cryptlib.h"
#include "secblock.h"
#include "sosemanuk.h"
#include "osrng.h"

#include <iostream>
#include <string>

int main()
{
    using CryptoPP::byte;
    using CryptoPP::Sosemanuk;
    using CryptoPP::SecByteBlock;
    using CryptoPP::AutoSeededRandomPool;

    AutoSeededRandomPool prng;
    std::string plain("My Plaintext!! My Dear plaintext!!"), cipher, recover;

    SecByteBlock key(32), iv(16);
    prng.GenerateBlock(key, key.size());
    prng.GenerateBlock(iv, iv.size());

    // Encryption object
    Sosemanuk::Encryption enc;    
    enc.SetKeyWithIV(key, key.size(), iv, iv.size());

    // Perform the encryption
    cipher.resize(plain.size());
    enc.ProcessData((byte*)&cipher[0], (const byte*)plain.data(), plain.size());

    std::cout << "Plain: " << plain << std::endl;
    std::cout << "Cipher: " << cipher << std::endl;

    Sosemanuk::Decryption dec;
    dec.SetKeyWithIV(key, key.size(), iv, iv.size());

    // Perform the decryption
    recover.resize(cipher.size());
    dec.ProcessData((byte*)&recover[0], (const byte*)cipher.data(), cipher.size());

    std::cout << "Recovered: " << recover << std::endl;

    return 0;
}

A typical output is shown below, including the non-printable characters from encryption.

$ ./test.exe
Plain: My Plaintext!! My Dear plaintext!!
Cipher: ▒5▒\ғs▒!▒▒D(▒▒▒<e▒`▒N▒▒▒
w
Recovered: My Plaintext!! My Dear plaintext!!

Resynchronizing

The Salsa family is both self-inverting and resynchronizable so you can use the encryption object for decryption, too.

#include "cryptlib.h"
#include "secblock.h"
#include "sosemanuk.h"
#include "osrng.h"

#include <iostream>
#include <string>

int main()
{
    using CryptoPP::byte;
    using CryptoPP::Sosemanuk;
    using CryptoPP::SecByteBlock;
    using CryptoPP::AutoSeededRandomPool;

    AutoSeededRandomPool prng;
    std::string plain("My Plaintext!! My Dear plaintext!!"), cipher, recover;

    SecByteBlock key(32), iv(16);
    prng.GenerateBlock(key, key.size());
    prng.GenerateBlock(iv, iv.size());

    // Encryption object
    Sosemanuk::Encryption enc;    
    enc.SetKeyWithIV(key, key.size(), iv, iv.size());

    // Perform the encryption
    cipher.resize(plain.size());
    enc.ProcessData((byte*)&cipher[0], (const byte*)plain.data(), plain.size());

    std::cout << "Plain: " << plain << std::endl;
    std::cout << "Cipher: " << cipher << std::endl;

    // Sosemanuk::Decryption dec;
    // dec.SetKeyWithIV(key, key.size(), iv, iv.size());

    std::cout << "Self inverting: " << enc.IsSelfInverting() << std::endl;
    std::cout << "Resynchronizable: " << enc.IsResynchronizable() << std::endl;

    enc.Resynchronize(iv, iv.size());

    // Perform the decryption
    // recover.resize(cipher.size());
    // dec.ProcessData((byte*)&recover[0], (const byte*)cipher.data(), cipher.size());

    // Perform the decryption with the decryptor
    recover.resize(cipher.size());
    enc.ProcessData((byte*)&recover[0], (const byte*)cipher.data(), cipher.size());

    std::cout << "Recovered: " << recover << std::endl;

    return 0;
}

A typical output is shown below, including the non-printable characters from encryption.

$ ./test.exe
Plain: My Plaintext!! My Dear plaintext!!
▒kÂ][▒▒_\▒▒uh▒▒▒~▒
Self inverting: 1
Resynchronizable: 1
Recovered: My Plaintext!! My Dear plaintext!!

Pipelines

You can also use stream ciphers in a Pipeline. Below is an example of Sosemanuk participating in a pipeline. Internally, StreamTransformationFilter calls ProcessData on the incoming data stream. The filter also buffers output if there is no attached transformation or sink.

#include "cryptlib.h"
#include "secblock.h"
#include "filters.h"
#include "sosemanuk.h"
#include "osrng.h"
#include "files.h"
#include "hex.h"

#include <iostream>
#include <string>

int main()
{
    using CryptoPP::byte;
    using CryptoPP::Sosemanuk;
    using CryptoPP::FileSink;
    using CryptoPP::StringSink;
    using CryptoPP::StringSource;
    using CryptoPP::HexEncoder;
    using CryptoPP::SecByteBlock;
    using CryptoPP::AutoSeededRandomPool;
    using CryptoPP::StreamTransformationFilter;

    AutoSeededRandomPool prng;
    HexEncoder encoder(new FileSink(std::cout));
    std::string plain("My Plaintext!! My Dear plaintext!!"), cipher, recover;

    SecByteBlock key(32), iv(16);
    prng.GenerateBlock(key, key.size());
    prng.GenerateBlock(iv, iv.size());

    std::cout << "Key: ";
    encoder.Put(key.data(), key.size());
    encoder.MessageEnd();
    std::cout << std::endl;

    std::cout << "IV: ";
    encoder.Put(iv.data(), iv.size());
    encoder.MessageEnd();
    std::cout << std::endl;

    // Encryption object
    Sosemanuk::Encryption enc;    
    enc.SetKeyWithIV(key, key.size(), iv, iv.size());

    // Decryption object
    Sosemanuk::Decryption dec;    
    dec.SetKeyWithIV(key, key.size(), iv, iv.size());

    StringSource ss1(plain, true, new StreamTransformationFilter(enc, new StringSink(cipher)));
    StringSource ss2(cipher, true, new StreamTransformationFilter(dec, new StringSink(recover)));

    std::cout << "Plain: " << plain << std::endl;

    std::cout << "Cipher: ";
    encoder.Put((const byte*)cipher.data(), cipher.size());
    encoder.MessageEnd();
    std::cout << std::endl;

    std::cout << "Recovered: " << recover << std::endl;

    return 0;
}

The program produces the expected output:

$ ./test.exe
Key: 3788977E163EBD8C39EC6855DF30C0AF56069C18B94A39C24F2AC0C179E21A11
IV: FA21BE3FE0CE3DECBEC0BA9E0A73359A
Plain: My Plaintext!! My Dear plaintext!!
Cipher: DADFE45F2921AEC143059AAB74EDD8F3062FC5966B660B39350C064E4989AA740CD3
Recovered: My Plaintext!! My Dear plaintext!!