CHAM
Documentation |
#include <cryptopp/cham.h>
|
CHAM is a family of South Korean lightweight block ciphers created by Bonwook Koo, Dongyoung Roh, Hyeonjin Kim, Younghoon Jung, Dong-Geon Lee, and Daesung Kwon. The algorithms provide CHAM-64/128, CHAM-128/128, and CHAM-128/256. The ciphers were designed for resource constrained devices and gadgets that participate in the Internet of Things.
If you are using Clang then be sure to visit Issue 677, Clang 5.0/6.0, CHAM-64/ECB and failed self test at -O1.
Crypto++ offers several ciphers from Korea Internet & Security Agency portfolio. The algorithms include ARIA, HIGHT, LEA, LSH and SEED.
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 consider using an algorithm or mode like CCM, GCM, EAX or ChaCha20Poly1305.
Sample Programs
There are three sample programs. The first shows CHAM128 key and block sizes. The second and third use filters in a pipeline). Pipelining is a high level abstraction and it handles buffering input, buffering output and padding for you.
If you are benchmarking then you may want to visit Benchmarks | Sample Program . It shows you how to use StreamTransformation::ProcessString
method to process blocks at a time. Calling a cipher's ProcessString
or ProcessBlock
eventually call a cipher's ProcessAndXorBlock
or AdvancedProcessBlocks
, and they are the lowest level API you can use.
The first example dumps the minimum, maximum, and default key lengths used by CHAM128.
using namespace CryptoPP; int main(int argc, char* argv[]) { std::cout << "key length: " << CHAM128::DEFAULT_KEYLENGTH << std::endl; std::cout << "key length (min): " << CHAM128::MIN_KEYLENGTH << std::endl; std::cout << "key length (max): " << CHAM128::MAX_KEYLENGTH << std::endl; std::cout << "block size: " << CHAM128::BLOCKSIZE << std::endl; return 0; }
Output from the above snippet produces the following. Notice the default key size is 128 bits or 16 bytes.
key length: 16 key length (min): 16 key length (max): 32 block size: 16
Switching to CHAM64 produces the following results:
key length: 16 key length (min): 16 key length (max): 16 block size: 16
The following program shows how to operate CHAM128 in CBC mode using a pipeline. The key is declared on the stack using a SecByteBlock to ensure the sensitive material is zeroized. Similar could be used for both plain text and recovered text.
using namespace CryptoPP; void Print(const std::string& label, const std::string& val) { std::string encoded; StringSource(val, true, new HexEncoder( new StringSink(encoded) ) // HexEncoder ); // StringSource std::cout << label << ": " << encoded << std::endl; } int main(int argc, char* argv[]) { SecByteBlock key(CHAM128::DEFAULT_KEYLENGTH); SecByteBlock iv(CHAM128::BLOCKSIZE); AutoSeededRandomPool prng; prng.GenerateBlock(key, key.size()); prng.GenerateBlock(iv, iv.size()); std::string plain = "CBC Mode Test"; std::string cipher, encoded, recovered; /*********************************\ \*********************************/ try { std::cout << "plain text: " << plain << std::endl; CBC_Mode< CHAM128 >::Encryption e; e.SetKeyWithIV(key, key.size(), iv); // The StreamTransformationFilter adds padding // as required. ECB and CBC Mode must be padded // to the block size of the cipher. StringSource s(plain, true, new StreamTransformationFilter(e, new StringSink(cipher) ) // StreamTransformationFilter ); // StringSource } catch(const CryptoPP::Exception& e) { std::cerr << e.what() << std::endl; exit(1); } /*********************************\ \*********************************/ Print("key", std::string((const char*)key.begin(), key.size())); Print("iv", std::string((const char*)iv.begin(), iv.size())); Print("cipher text", cipher); /*********************************\ \*********************************/ try { CBC_Mode< CHAM128 >::Decryption d; d.SetKeyWithIV(key, key.size(), iv); // The StreamTransformationFilter removes // padding as required. StringSource s(cipher, true, new StreamTransformationFilter(d, new StringSink(recovered) ) // StreamTransformationFilter ); // StringSource std::cout << "recovered text: " << recovered << std::endl; } catch(const CryptoPP::Exception& e) { std::cerr << e.what() << std::endl; exit(1); } return 0; }
A typical output is shown below. Note that each run will produce different results because the key and initialization vector are randomly generated.
$ ./test.exe plain text: CBC Mode Test key: 16307AF17E2E89D766304B30033BAFEB iv: 573DCFE1588656EE6B09999F1F300F13 cipher text: D43D49D85EC575A78EFDE44699F79785 recovered text: CBC Mode Test
The third program modifies the second program by switching to EAX mode. Authenticity assurances can placed on the cipher text for nearly no programming costs by using an authenticated encryption mode. Below the StreamTransformationFilter was replaced by AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter.
EAX< CHAM128 >::Encryption e; e.SetKeyWithIV(key, key.size(), iv); StringSource(plain, true, new AuthenticatedEncryptionFilter(e, new StringSink(cipher) ) // StreamTransformationFilter ); // StringSource ... EAX< CHAM128 >::Decryption d; d.SetKeyWithIV(key, key.size(), iv); StringSource s(cipher, true, new AuthenticatedDecryptionFilter(d, new StringSink(recovered) ) // StreamTransformationFilter ); // StringSource
Typical output is as follows. Notice the additional cipher text bytes due to the MAC bytes. See EAX Mode for details.
$ ./test.exe plain text: EAX Mode Test key: 9A59794DCBB7E90EBCB36ED85047ED58 iv: F7B7B64A1BB6DAC0023DB6A596CCB4C5 cipher text: 17D8AFA56969CF6ACBFEA67ED005EDCF0D4530F3A2F7005BEC160FBC7C recovered text: EAX Mode Test
Switching to CHAM64 produces a similar result:
$ ./test.exe plain text: EAX Mode Test key: 0D3AD64CDECD8B58E448EF1E9E8D1D63 iv: 77EDCCE030EA263F cipher text: 63FB6F959A63DB7CB3BC353B5A922804BC142EACB5 recovered text: EAX Mode Test
To manually insert bytes into the filter, perform multiple Put
s. Though Get
is used below, a StringSink
could easily be attached and save the administrivia.
const size_t SIZE = 16 * 4; string plain(SIZE, 0x00); for(size_t i = 0; i < plain.size(); i++) plain[i] = 'A' + (i%26); ... CBC_Mode < CHAM128 >::Encryption encryption(key, sizeof(key), iv); StreamTransformationFilter encryptor(encryption, NULL); for(size_t j = 0; j < plain.size(); j++) encryptor.Put((byte)plain[j]); encryptor.MessageEnd(); size_t ready = encryptor.MaxRetrievable(); string cipher(ready, 0x00); encryptor.Get((byte*) &cipher[0], cipher.size());
Downloads
No downloads.