The AES, TDES, and EES examples illustrate the processing of a single block of data. Obviously, one can process successive blocks by placing the crypt() call within a while or for loop. In practice, however, when using these block ciphers you'll need to pad out your data to a multiple of the cipher's block size. Further information on padding appears in the section Padding Before Encryption at the bottom of this page.
The sample code fragments provided in this section
all implement the following pseudocode:
// generate a random 192-bit (24-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(24); // instantiate an AES object; initialize it to perform ECB encryption cdk::AES aesi; aesi.init(AES::ENCRYPT, +strKey, strKey.c_str()); // encrypt a block of plaintext char *pbuf ="0123456789abcdef"; // sample plaintext char cbuf[16]; // output buffer for ciphertext aesi.crypt(16, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the AES object to perform decryption aesi.clear(); aesi.init(AES::DECRYPT, +strKey, strKey.c_str()); // decrypt a block of ciphertext char obuf[16]; // buffer for plaintext aesi.crypt(16, cbuf, obuf); // obuf now contains copy of plaintext
// generate a random 192-bit (24-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(24); cdk::str strIV = prngi.gens(16); // need a 16-byte IV for AES-CBC // instantiate an AES object; initialize it to perform CBC encryption cdk::AES aesi; aesi.init(AES::ENCRYPT, +strKey, strKey.c_str(), AES::CBC, strIV.c_str()); // encrypt a block of plaintext char *pbuf ="0123456789abcdef"; // sample plaintext char cbuf[16]; // output buffer for ciphertext aesi.crypt(16, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the AES object to perform decryption aesi.clear(); aesi.init(AES::DECRYPT, +strKey, strKey.c_str(), AES::CBC, strIV.c_str()); // decrypt a block of ciphertext char obuf[16]; // buffer for plaintext aesi.crypt(16, cbuf, obuf); // obuf now contains copy of plaintext
// generate a random 192-bit (24-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(24); // instantiate a DES object; initialize it to perform TDES-ECB encryption cdk::DES desi; desi.init(DES::ENCRYPT, +strKey, strKey.c_str(), DES::ALG_TDES); // encrypt a block of plaintext char *pbuf ="01234567"; // sample plaintext char cbuf[8]; // output buffer for ciphertext desi.crypt(8, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the DES object to perform decryption desi.clear(); desi.init(DES::DECRYPT, +strKey, strKey.c_str(), DES::ALG_TDES); // decrypt a block of ciphertext char obuf[8]; // buffer for plaintext desi.crypt(8, out, obuf); // obuf now contains copy of plaintext
// generate a random 192-bit (24-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(24); cdk::str strIV = prngi.gens(8); // need an 8-byte IV for TDES-CBC // instantiate a DES object; initialize it to perform TDES-CBC encryption cdk::DES desi; desi.init(DES::ENCRYPT, +strKey, strKey.c_str(), DES::ALG_TDES, DES::CBC, strIV.c_str()); // encrypt a block of plaintext char *pbuf ="01234567"; // sample plaintext char cbuf[8]; // output buffer for ciphertext desi.crypt(8, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the DES object to perform decryption desi.clear(); desi.init(DES::DECRYPT, +strKey, strKey.c_str(), DES::ALG_TDES, DES::CBC, strIV.c_str()); // decrypt a block of ciphertext char obuf[8]; // buffer for plaintext desi.crypt(8, out, obuf); // obuf now contains copy of plaintext
// generate a random 80-bit (10-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(10); // instantiate an EES object; initialize it to perform ECB encryption cdk::EES eesi; eesi.init(EES::ENCRYPT, +strKey, strKey.c_str()); // encrypt a block of plaintext char *pbuf ="01234567"; // sample plaintext char cbuf[8]; // output buffer for ciphertext eesi.crypt(8, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the EES object to perform decryption eesi.clear(); eesi.init(EES::DECRYPT, +strKey, strKey.c_str()); // decrypt a block of ciphertext char obuf[8]; // buffer for plaintext eesi.crypt(8, out, obuf); // obuf now contains copy of plaintext
// generate a random 80-bit (10-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(10); cdk::str strIV = prngi.gens(8); // need an 8-byte IV for EES-CBC // instantiate an EES object; initialize it to perform CBC encryption cdk::EES eesi; eesi.init(EES::ENCRYPT, +strKey, strKey.c_str(), EES::CBC, strIV.c_str()); // encrypt the data char *pbuf ="01234567"; // sample plaintext char cbuf[8]; // output buffer for ciphertext eesi.crypt(8, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the EES object to perform decryption eesi.clear(); eesi.init(EES::DECRYPT, +strKey, strKey.c_str(), EES::CBC, strIV.c_str()); // decrypt a block of ciphertext char obuf[8]; // buffer for plaintext eesi.crypt(8, out, obuf); // obuf now contains copy of plaintext
// generate a random 128-bit (16-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(16); // instantiate an RC2 object; initialize it to perform ECB encryption cdk::RC2 rc2i; rc2i.init(RC2::ENCRYPT, +strKey, strKey.c_str()); // encrypt a block of plaintext char *pbuf ="01234567"; // sample plaintext char cbuf[8]; // output buffer for ciphertext rc2i.crypt(8, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the RC2 object to perform decryption rc2i.clear(); rc2i.init(RC2::DECRYPT, +strKey, strKey.c_str()); // decrypt a block of ciphertext char obuf[8]; // buffer for plaintext rc2i.crypt(8, out, obuf); // obuf now contains copy of plaintext
// generate a random 128-bit (16-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(16); cdk::str strIV = prngi.gens(8); // need an 8-byte IV for RC2-CBC // instantiate an RC2 object; initialize it to perform CBC encryption cdk::RC2 rc2i; rc2i.init(RC2::ENCRYPT, +strKey, strKey.c_str(), strIV.c_str()); // encrypt a block of plaintext char *pbuf ="01234567"; // sample plaintext char cbuf[8]; // output buffer for ciphertext rc2i.crypt(8, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the RC2 object to perform decryption rc2i.clear(); rc2i.init(RC2::DECRYPT, +strKey, strKey.c_str(), strIV.c_str()); // decrypt a block of ciphertext char obuf[8]; // buffer for plaintext rc2i.crypt(8, out, obuf); // obuf now contains copy of plaintext
// generate a random 128-bit (16-byte) session key cdk::PRNG prngi; cdk::str strKey = prngi.gens(16); // instantiate an RC2 object and initialize it cdk::RC4 rc4i; rc4i.init(+strKey, strKey.c_str()); // encrypt the plaintext char *pbuf ="01234567abc"; // sample plaintext (arbitrary length) char cbuf[11]; // output buffer for ciphertext rc4i.crypt(11, pbuf, cbuf); // cbuf now contains ciphertext // reinitialize the RC2 object to perform decryption rc4i.init(+strKey, strKey.c_str()); // decrypt the ciphertext char obuf[11]; // buffer for plaintext rc4i.crypt(11, out, obuf); // obuf now contains copy of plaintext
NOTE: RC4 is a stream cipher so padding is not required.
A standard padding mechanism is specified in PKCS #5. It is relatively straightforward to implement, but since it is not exposed in the CDK the code and a use case are provided here. Note that you only need to pad the last block of your data.
cdk::str makep5(const cdk::str x, int n=8) { // pad according to PKCS #5 (RFC 1423), n = 8 or 16 cdk::str y = x; int len = n * ((+x + n)/n); cdk::str fill = cdk::single(n - (+x % n)); while ( +y < len ) y += fill; return y; } cdk::str parsep5(const cdk::str x, int n=8) { // strip padding according to PKCS #5 (RFC 1423) cdk::str strRetVal = cdk::str(0); if ( +x != 0 ) { int pad = x[+x-1]; if ( !(pad < 1 || pad > n) ) strRetVal = x.trunc(+x-pad); } return strRetVal; } int main() { int i; cdk::str strIn = "short"; cdk::str strPadded; char szOut[16]; cdk::PRNG prngi; cdk::str strKey = prngi.gens(24); // 16 = 128-bit, 24 = 192-bit, 32 = 256-bit // instantiate a AES object to perform encryption. cdk::AES aesi; i = aesi.init(AES::ENCRYPT, +strKey, strKey.c_str()); if (i) return i; if (+strIn % 16 != 0) // padding required { strPadded = makep5(strIn, 16); } // encrypt the data char out[16]; i = aesi.crypt(16, strPadded.c_str(), out); if (i) return i; // Decrypt it and unpad i = aesi.init(AES::DECRYPT, +strKey, strKey.c_str()); if (i) return i; i = aesi.crypt(16, out, out); cdk::str strOut(16, out); strOut = parsep5(strOut, 16); if (strOut != strIn) return 1; // error return 0; }
For information concerning the objects used here see:
The next topic is Using the Message Digest Functions.
| ISC Cryptographic Development Kit - User's Guide | |
| Questions? E-mail ISC technical support | |
| Copyright© 2002-2006 Information Security Corp. All rights reserved. |