📄 twofish.cpp
字号:
INPACK (1, b, 1); INPACK (2, c, 2); INPACK (3, d, 3); /* Encryption Feistel cycles. */ ENCCYCLE (0); ENCCYCLE (1); ENCCYCLE (2); ENCCYCLE (3); ENCCYCLE (4); ENCCYCLE (5); ENCCYCLE (6); ENCCYCLE (7); /* Output whitening and unpacking. */ OUTUNPACK (0, c, 4); OUTUNPACK (1, d, 5); OUTUNPACK (2, a, 6); OUTUNPACK (3, b, 7);}void twofish_encrypt (void *ctx, byte *out, const byte *in){ do_twofish_encrypt ((TWOFISH_context*)ctx, out, in); burn_stack (24+3*sizeof (void*));}/* Decrypt one block. in and out may be the same. */static voiddo_twofish_decrypt (const TWOFISH_context *ctx, byte *out, const byte *in){ /* The four 32-bit chunks of the text. */ u32 a, b, c, d; /* Temporaries used by the round function. */ u32 x, y; /* Input whitening and packing. */ INPACK (0, c, 4); INPACK (1, d, 5); INPACK (2, a, 6); INPACK (3, b, 7); /* Encryption Feistel cycles. */ DECCYCLE (7); DECCYCLE (6); DECCYCLE (5); DECCYCLE (4); DECCYCLE (3); DECCYCLE (2); DECCYCLE (1); DECCYCLE (0); /* Output whitening and unpacking. */ OUTUNPACK (0, a, 0); OUTUNPACK (1, b, 1); OUTUNPACK (2, c, 2); OUTUNPACK (3, d, 3);}void twofish_decrypt (void *ctx, byte *out, const byte *in){ do_twofish_decrypt ((TWOFISH_context*)ctx, out, in); burn_stack (24+3*sizeof (void*));}/* Test a single encryption and decryption with each key size. */static const char*selftest (void){ TWOFISH_context ctx; /* Expanded key. */ byte scratch[16]; /* Encryption/decryption result buffer. */ /* Test vectors for single encryption/decryption. Note that I am using * the vectors from the Twofish paper's "known answer test", I=3 for * 128-bit and I=4 for 256-bit, instead of the all-0 vectors from the * "intermediate value test", because an all-0 key would trigger all the * special cases in the RS matrix multiply, leaving the math untested. */ static const byte plaintext[16] = { 0xD4, 0x91, 0xDB, 0x16, 0xE7, 0xB1, 0xC3, 0x9E, 0x86, 0xCB, 0x08, 0x6B, 0x78, 0x9F, 0x54, 0x19 }; static const byte key[16] = { 0x9F, 0x58, 0x9F, 0x5C, 0xF6, 0x12, 0x2C, 0x32, 0xB6, 0xBF, 0xEC, 0x2F, 0x2A, 0xE8, 0xC3, 0x5A }; static const byte ciphertext[16] = { 0x01, 0x9F, 0x98, 0x09, 0xDE, 0x17, 0x11, 0x85, 0x8F, 0xAA, 0xC3, 0xA3, 0xBA, 0x20, 0xFB, 0xC3 }; static const byte plaintext_256[16] = { 0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6 }; static const byte key_256[32] = { 0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D, 0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F }; static const byte ciphertext_256[16] = { 0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA }; twofish_setkey (&ctx, key, sizeof(key)); twofish_encrypt (&ctx, scratch, plaintext); if (memcmp (scratch, ciphertext, sizeof (ciphertext))) return "Twofish-128 test encryption failed."; twofish_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext, sizeof (plaintext))) return "Twofish-128 test decryption failed."; twofish_setkey (&ctx, key_256, sizeof(key_256)); twofish_encrypt (&ctx, scratch, plaintext_256); if (memcmp (scratch, ciphertext_256, sizeof (ciphertext_256))) return "Twofish-256 test encryption failed."; twofish_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_256, sizeof (plaintext_256))) return "Twofish-256 test decryption failed."; return NULL;}/* More complete test program. This does 1000 encryptions and decryptions * with each of 250 128-bit keys and 2000 encryptions and decryptions with * each of 125 256-bit keys, using a feedback scheme similar to a Feistel * cipher, so as to be sure of testing all the table entries pretty * thoroughly. We keep changing the keys so as to get a more meaningful * performance number, since the key setup is non-trivial for Twofish. */#ifdef TEST#include <stdio.h>#include <string.h>#include <time.h>intmain(){ TWOFISH_context ctx; /* Expanded key. */ int i, j; /* Loop counters. */ const char *encrypt_msg; /* Message to print regarding encryption test; * the printf is done outside the loop to avoid * stuffing up the timing. */ clock_t timer; /* For computing elapsed time. */ /* Test buffer. */ byte buffer[4][16] = { {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} }; /* Expected outputs for the million-operation test */ static const byte test_encrypt[4][16] = { {0xC8, 0x23, 0xB8, 0xB7, 0x6B, 0xFE, 0x91, 0x13, 0x2F, 0xA7, 0x5E, 0xE6, 0x94, 0x77, 0x6F, 0x6B}, {0x90, 0x36, 0xD8, 0x29, 0xD5, 0x96, 0xC2, 0x8E, 0xE4, 0xFF, 0x76, 0xBC, 0xE5, 0x77, 0x88, 0x27}, {0xB8, 0x78, 0x69, 0xAF, 0x42, 0x8B, 0x48, 0x64, 0xF7, 0xE9, 0xF3, 0x9C, 0x42, 0x18, 0x7B, 0x73}, {0x7A, 0x88, 0xFB, 0xEB, 0x90, 0xA4, 0xB4, 0xA8, 0x43, 0xA3, 0x1D, 0xF1, 0x26, 0xC4, 0x53, 0x57} }; static const byte test_decrypt[4][16] = { {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}, {0x0F, 0x1E, 0x2D, 0x3C, 0x4B, 0x5A, 0x69, 0x78, 0x87, 0x96, 0xA5, 0xB4, 0xC3, 0xD2 ,0xE1, 0xF0}, {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54 ,0x32, 0x10}, {0x01, 0x23, 0x45, 0x67, 0x76, 0x54 ,0x32, 0x10, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98} }; /* Start the timer ticking. */ timer = clock (); /* Encryption test. */ for (i = 0; i < 125; i++) { twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); for (j = 0; j < 1000; j++) twofish_encrypt (&ctx, buffer[2], buffer[2]); twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); for (j = 0; j < 1000; j++) twofish_encrypt (&ctx, buffer[3], buffer[3]); twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); for (j = 0; j < 1000; j++) { twofish_encrypt (&ctx, buffer[0], buffer[0]); twofish_encrypt (&ctx, buffer[1], buffer[1]); } } encrypt_msg = memcmp (buffer, test_encrypt, sizeof (test_encrypt)) ? "encryption failure!\n" : "encryption OK!\n"; /* Decryption test. */ for (i = 0; i < 125; i++) { twofish_setkey (&ctx, buffer[2], sizeof (buffer[2])*2); for (j = 0; j < 1000; j++) { twofish_decrypt (&ctx, buffer[0], buffer[0]); twofish_decrypt (&ctx, buffer[1], buffer[1]); } twofish_setkey (&ctx, buffer[1], sizeof (buffer[1])); for (j = 0; j < 1000; j++) twofish_decrypt (&ctx, buffer[3], buffer[3]); twofish_setkey (&ctx, buffer[0], sizeof (buffer[0])); for (j = 0; j < 1000; j++) twofish_decrypt (&ctx, buffer[2], buffer[2]); } /* Stop the timer, and print results. */ timer = clock () - timer; printf (encrypt_msg); printf (memcmp (buffer, test_decrypt, sizeof (test_decrypt)) ? "decryption failure!\n" : "decryption OK!\n"); printf ("elapsed time: %.1f s.\n", (float) timer / CLOCKS_PER_SEC); return 0;}#endif /* TEST */const char *twofish_get_info(int algo, size_t *keylen, size_t *blocksize, size_t *contextsize, int (**r_setkey) (void *c, const byte *key, unsigned keylen), void (**r_encrypt) (void *c, byte *outbuf, const byte *inbuf), void (**r_decrypt) (void *c, byte *outbuf, const byte *inbuf) ){ *keylen = algo==10? 256 : 128; *blocksize = 16; *contextsize = sizeof (TWOFISH_context); *r_setkey = twofish_setkey; *r_encrypt = twofish_encrypt; *r_decrypt = twofish_decrypt; if( algo == 10 ) return "TWOFISH"; if (algo == 102) /* This algorithm number is assigned for * experiments, so we can use it */ return "TWOFISH128"; return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -