LEA

From Crypto++ Wiki
Jump to navigation Jump to search
LEA
Documentation
#include <cryptopp/lea.h>

Lightweight Encryption Algortihm (LEA) is a South Korean lightweight block cipher using ARX design created by Deukjo Hong, Jung-Keun Lee, Dong-Chan Kim, Daesung Kwon, Kwon Ho Ryu, and Dong-Geon Lee. The algorithm provides a 128-bit block size and 128, 192 and 256-bit key sizes. The cipher was designed for resource constrained devices and gadgets that participate in the Internet of Things. The LEA homepage is located at Korea Internet & Security Agency.

Crypto++ offers several ciphers from Korea Internet & Security Agency portfolio. The algorithms include ARIA, HIGHT, LEA, LSH and SEED. Additionally the library offers CHAM.

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 prefer to use CCM, GCM, or EAX over other modes, such as CBC or CTR.

Sample Programs

There are three sample programs. The first shows LEA 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 multiple blocks at a time using a standard C++ interface. 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 LEA.

using namespace CryptoPP;
int main(int argc, char* argv[])
{   
   std::cout << "key length: " << LEA::DEFAULT_KEYLENGTH << std::endl;
   std::cout << "key length (min): " << LEA::MIN_KEYLENGTH << std::endl;
   std::cout << "key length (max): " << LEA::MAX_KEYLENGTH << std::endl;
   std::cout << "block size: " << LEA::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

The following program shows how to operate LEA 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(LEA::DEFAULT_KEYLENGTH);
   SecByteBlock iv(LEA::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< LEA >::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< LEA >::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: 9C9C82DA4441ADF032A412F10629C92E
iv: 28B9629CD9D92C2C8BF6A1F01F7DCCE5
cipher text: 69BA15CDE426F2B2171C733321143095
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< LEA >::Encryption e;
e.SetKeyWithIV(key, key.size(), iv);

StringSource(plain, true, 
    new AuthenticatedEncryptionFilter(e,
        new StringSink(cipher)
    ) // StreamTransformationFilter
); // StringSource

...

EAX< LEA >::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: 4D20FF5DE668A90AD8E7A5CE81CC54A2
iv: B0932A4C6CCB99F8A2E8BAC47CDC3746
cipher text: FBA5D35542EEDD2A7556764CE2FB043658D8F2789798EE8093A344F9D9
recovered text: EAX Mode Test

To manually insert bytes into the filter, perform multiple Puts. 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 < LEA >::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.