SKIPJACK
Documentation |
#include <cryptopp/skipjack.h>
|
SKIPJACK is a block cipher developed by the National Security Agency and publicly released in 1998. The cipher has a fixed 10-byte (80-bit) key length and fixed 8-byte (64-bit) block size. Skipjack provides about 80-bits of security and is no longer considered secure.
Bruce Schneier provides some history of the cipher at Declassifying Skipjack. Schneier offers a link to a reference implementation at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/skipjack. The site offers two source files - skipjack.c
and skipjack-orig.c
. skipjack.c
is an optimized implementation, and skipjack-orig.c
is a reference implementation.
The Crypto++ implementation conforms to NIST's SKIPJACK and KEA Algorithm Specifications released in May 1998, and uses test vectors from SP800-17, Modes of Operation Validation System (MOVS): Requirements and Procedures (Table 6, pp. 140-42). skipjack.c
and skipjack-orig.c
are not consitent with the Crypto++ implementation, and they fail to validate against the NIST test vectors.
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.
SKIPJACK classes
SKIPJACK provides three classes of interest. The first is the SKIPJACK
class, the second is SKIPJACK::Encryption
class, and the final is the SKIPJACK::Decryption
class.
You use the classes just like any other block cipher.
Algorithm Name
StaticAlgorithmName
and AlgorithmName
return SKIPJACK
.
int main(int argc, char* argv[]) { using namespace CryptoPP; SKIPJACK::Encryption skipjack; std::cout << "StaticAlgorithmName: " << skipjack.StaticAlgorithmName() << std::endl; std::cout << "AlgorithmName (unkeyed): " << skipjack.AlgorithmName() << std::endl; byte key[SKIPJACK::DEFAULT_KEYLENGTH]; skipjack.SetKey(key, sizeof(key)); std::cout << "AlgorithmName (keyed): " << skipjack.AlgorithmName() << std::endl; return 0; }
The program results in the following output.
$ ./test.exe StaticAlgorithmName: SKIPJACK AlgorithmName (unkeyed): SKIPJACK AlgorithmName (keyed): SKIPJACK
Sample Programs
There are three sample programs. The first shows SKIPJACK 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 program prints key and block size for the cipher.
int main(int argc, char* argv[]) { std::cout << "SKIPJACK" << std::endl; std::cout << " Default keylength: " << SKIPJACK::DEFAULT_KEYLENGTH << std::endl; std::cout << " Minimum keylength: " << SKIPJACK::MIN_KEYLENGTH << std::endl; std::cout << " Maximum keylength: " << SKIPJACK::MAX_KEYLENGTH << std::endl; std::cout << " Default blocksize: " << SKIPJACK::BLOCKSIZE << std::endl; return 0; }
Running the program results in fixed sizes of 8 and 10.
$ ./test.exe SKIPJACK Default keylength: 10 Minimum keylength: 10 Maximum keylength: 10 Default blocksize: 8
The following program shows how to operate SKIPJACK in CBC mode using a pipeline.
AutoSeededRandomPool prng; SecByteBlock key(SKIPJACK::DEFAULT_KEYLENGTH); prng.GenerateBlock(key, key.size()); SecByteBlock iv(SKIPJACK::BLOCKSIZE); 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< SKIPJACK >::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 ss1(plain, true, new StreamTransformationFilter(e, new StringSink(cipher) ) // StreamTransformationFilter ); // StringSource } catch(const CryptoPP::Exception& e) { std::cerr << e.what() << std::endl; exit(1); } /*********************************\ \*********************************/ // Pretty print encoded.clear(); StringSource ss2(key.begin(), key.size(), true, new HexEncoder( new StringSink(encoded) ) // HexEncoder ); // StringSource std::cout << "key: " << encoded << std::endl; encoded.clear(); StringSource ss3(iv.begin(), iv.size(), true, new HexEncoder( new StringSink(encoded) ) // HexEncoder ); // StringSource std::cout << "iv: " << encoded << std::endl; encoded.clear(); StringSource ss4(cipher, true, new HexEncoder( new StringSink(encoded) ) // HexEncoder ); // StringSource std::cout << "cipher text: " << encoded << std::endl; /*********************************\ \*********************************/ try { CBC_Mode< SKIPJACK >::Decryption d; d.SetKeyWithIV(key, key.size(), iv); // The StreamTransformationFilter removes // padding as required. StringSource ss5(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); }
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: 2F00288D9F41E217E75D iv: E2F9B312D8925F88 cipher text: 7B906BD1D6B94C3222DEA9E617D6094C recovered text: CBC Mode Test
Test Vectors
There was some confusion about the Crypto++ SKIPJACK algorithm because it did not arrive at expected results from the article cited by Schneier. Also see Issue 824, SKIPJACK encryption gives wrong result.
Crypto++ conforms to NIST specifications, and passes the Known Answer Tests provided at SP800-17, Modes of Operation Validation System (MOVS): Requirements and Procedures (Table 6, pp. 140-42). Botan also arrives at the expected test vector results. The first several SKIPJACK/ECB test vectors are shown below.
Key: 80000000000000000000 Plaintext: 0000000000000000 Ciphertext: 7a00e494 41461f5a # Key: 40000000000000000000 Plaintext: 0000000000000000 Ciphertext: a14ff8bc d1bc9ef9 # Key: 20000000000000000000 Plaintext: 0000000000000000 Ciphertext: d7e81038 5a42aaea
SKIPJACK/CBC test vectors are available at `TestVectors/skipjack.txt`. The collection include 1 block (8-bytes) through 10 blocks (80-bytes). The vectors were generated by Botan and cross-validated with Crypto++.
Downloads
No downloads.