#include "aes.hpp"
#include "stream.hpp"
#include "rng.hpp"
#include "hex.hpp"
#include <iostream>
int main(){
using C = symmetric::Aes<256>;
//First generate a key for the cipher.
csprng::BlockCipherRng<C> rng;
auto key = C::key_t().data(); //Don't want to declare the actual type.
rng.get_bytes(key.data(), key.size());
std::cout << "key = " << utility::buffer_to_hex_string(key) << std::endl;
//Now let's encrypt an arbitrary string.
std::string plaintext = "Just some arbitrary plaintext. I'm not counting ""characters, so there's a 1/16 chance the length will be divisible by ""16, which is what I don't want.";
std::vector<std::uint8_t> ciphertext(plaintext.size());
std::cout <<
"plaintext = \"" << plaintext << "\"\n""plaintext = " << utility::buffer_to_hex_string(plaintext.data(),
plaintext.size()) << std::endl;
{
symmetric::stream::CtrCipherStream<C> stream(C(key), {}, true);
stream.write(plaintext.data(), plaintext.size());
stream.terminate();
stream.read(ciphertext.data(), ciphertext.size());
}
std::cout << "ciphertext = " << utility::buffer_to_hex_string(ciphertext)
<< std::endl;
//Now let's decrypt it.
std::string decrypted(ciphertext.size(), 0);
{
symmetric::stream::CtrCipherStream<C> stream(C(key), {}, false);
stream.write(ciphertext.data(), ciphertext.size());
stream.terminate();
stream.read(decrypted.data(), decrypted.size());
}
std::cout << "decrypted = \"" << decrypted << "\"\n";
return 0;
}
key = d3d848716bfc98cddd5c2091d3da7198f5b7e7a0e1cdd3d69262639e8a131406
plaintext = "Just some arbitrary plaintext. I'm not counting characters, so ther
e's a 1/16 chance the length will be divisible by 16, which is what I don't want
."
plaintext = 4a75737420736f6d652061726269747261727920706c61696e746578742e2049276d
206e6f7420636f756e74696e6720636861726163746572732c20736f207468657265277320612031
2f3136206368616e636520746865206c656e6774682077696c6c20626520646976697369626c6520
62792031362c2077686963682069732077686174204920646f6e27742077616e742e
ciphertext = bcf4f06ec9d2b85ee6c8cba0e054b38676ee52d0da504655f0f82ea404b66c0b375
6e8ecf595028d725c9870121788fc971b1ab26c3bcce839cedc0535ef96b5ee65eb0f5c05a5f5ae9
f34519231c30081d75dccf8e02878928d57a88769d26cdccc959d292e6d70523d49e574ce49963dc
fedfb9bb1d7ec2b98d1d47394568ea8302a6b442a8e97008583f3c8e10bd113621656
decrypted = "Just some arbitrary plaintext. I'm not counting characters, so ther
e's a 1/16 chance the length will be divisible by 16, which is what I don't want
."
What happens if the length is divisible by 16?
If the number is divisible by 16, could you not wrap the sentence in a known phrase that is later removed after decryption?
string preprocessText(string text)
{
string retval = "<resized>";
if(text.length()%16)
{
retval = text;
}
else
{
retval += text;
retval += "</resized>";
}
return retval;
}
string removeTag(string text)
{
if( !((text.length() - (length of tags)) % 16))
{
// if text starts with the tag, then truncate and return
// else return whole text
}
// otherwise return text
}
string result = encrypt(preprocessText("Oh no, this sentence is 48 character long. oops."));
removeTag(decrypt(result));
I suppose this might be considered taboo since a different program using the encrypt/decrypt libs would not know that there are tags in the data, which would cause them to decrypt and display the tag as well... Also the user might be the suspicious type and wonder why sometimes the output is longer than expected on the encrypted data.
Thank you for using the unlicense-license, this will be an excellent study source.
Nothing special, but the point of CTR is that you can turn a block cipher into a stream cipher. AES has a 16-byte block, so if the example plaintext has a length divisible by 16, it doesn't demonstrate that CTR is correctly streamifying the cipher.