AES, Serpent or Twofish in C example?
I found a lot of implementa开发者_运维知识库tions of AES, Twofish and Serpent in C. But I don't really understand the examples. I only understand that some where provided with examples to invert a matrix.
Can someone point me to an example or .c file for to encrypt/decrypt data represented by a char*
and a password?
The wikipedia article actually links to an excellent tutorial (by X-N20) written in C that walks you through the Maths and provides C implementations on the go, which is quite useful for understanding the process. I'd also recommend reading up on finite field arithmetic.
Serpent and Twofish, having missed out on the AES title, aren't so well documented around the internet. Remember though that each provides reference implementations.
Actually implementing them yourself will require study of their respective papers and probably the reference source code.
Note that your 20 billion comments all relate to the fact that the interface NIST specified for AES was that each cipher provide a 128-bit (16 byte) input block and one of 128-bit, 192-bit and 256-bit key blocks.
In order to securely encrypt in such a way as to resist cryptanalysis properly, you need some careful work. For example, what if your last block is missing a few bytes needed? How do you pad securely? Similarly, depending on the intended usage there are other schemes, particularly for large repetitive data, designed to resist cryptanalysis where you know that the encrypted data likely contains say the contents of c:\windows
. What the commentors are trying to get at is that for any real world usage, to remain secure, these things need consideration.
Edit Since another question has cropped up on this topic, here's a few links:
- Brian Gladman's ASM/C code for various crypto-algorithms including AES, SHA and Serpent.
- OpenSSL's AES code in their CVS. See also DES. They don't implement Serpent. You might also want to look at the rest of their code under
crypto
. - Crypto++. If you can use C++ and are only an end-user of crypto, then You Need This Library (tm). There are algorithms in there I've never heard of. Their SVN trunk.
- libgcrypt provides a whole suite of cryptographic functions for
gpg
. Specifically, if you're after AES, you might not find it in here, but you will find camellia and serpent.
Trying to answer the -still unanswered- question of killercode
, here is my attempt of achieving the same thing:
Download this TwoFish code (thanks go to Schneier et al.): https://www.schneier.com/code/twofish-reference-c.zip
Use this code (at your own risk of course):
int mode = MODE_CBC; int keySize = 256; int result = 0; keyInstance ki; /* key information, including tables */ cipherInstance ci; /* keeps mode (ECB, CBC) and IV */ BYTE plainText[MAX_BLK_CNT*(BLOCK_SIZE / 8)]; // 64 in size! BYTE cipherText[MAX_BLK_CNT*(BLOCK_SIZE / 8)]; BYTE decryptOut[MAX_BLK_CNT*(BLOCK_SIZE / 8)]; BYTE iv[BLOCK_SIZE / 8]; int i; /* select number of bytes to encrypt (multiple of block) */ /* e.g., byteCnt = 16, 32, 48, 64 */ //byteCnt = (BLOCK_SIZE / 8) * (1 + (rand() % MAX_BLK_CNT)); /* generate test data */; int plainTextLength = 65; for (i = 0; i < min(plainTextLength, MAX_BLK_CNT*(BLOCK_SIZE / 8)); i++) plainText[i] = (BYTE)rand(); if (plainTextLength > MAX_BLK_CNT * BLOCK_SIZE / 8) { ::MessageBox(NULL, _T("You need to increase your MAX_BLK_CNT for the plain-text to fit in one call."), _T("Error"), MB_OK); return; } int byteCnt = ceil((double)plainTextLength / (BLOCK_SIZE / 8.0)) * (BLOCK_SIZE / 8); /* ----------------------- */ /* 'dummy' setup for a 128-bit key */ if (makeKey(&ki, DIR_ENCRYPT, keySize, NULL) != TRUE) result = 1; /* ----------------------- */ /* 'dummy' setup for cipher */ if (cipherInit(&ci, mode, NULL) != TRUE) result = 1; /* select key bits */ for (i = 0; i < keySize / 32; i++) ki.key32[i] = 0x10003 * rand(); /* run the key schedule */ reKey(&ki); /* set up random iv (if needed)*/ if (mode != MODE_ECB) { for (i = 0; i < sizeof(iv); i++) iv[i] = (BYTE)rand(); /* copy the IV to ci */ memcpy(ci.iv32, iv, sizeof(ci.iv32)); } /* encrypt the bytes */ if (blockEncrypt(&ci, &ki, plainText, byteCnt * 8, cipherText) != byteCnt * 8) result = 1; /* ----------------------- */ /* decrypt the bytes */ if (mode != MODE_ECB) /* first re-init the IV (if needed) */ memcpy(ci.iv32, iv, sizeof(ci.iv32)); if (blockDecrypt(&ci, &ki, cipherText, byteCnt * 8, decryptOut) != byteCnt * 8) result = 1; /* make sure the decrypt output matches original plaintext */ if (memcmp(plainText, decryptOut, byteCnt)) result = 1; if (result == 0) ::MessageBox(NULL, _T("Success"), _T("SUCCESS"), MB_OK);
That was my attempt and it seems working quite good.
It is using CBC mode.
I am open to suggestions, if anyone has any.
Of course you might like to make MAX_BLK_CNT
a variable and increase it accordingly, to be able to encrypt a variety of data lengths. Although I am not 100% sure if that is its normal usage.
Cheer! :)
Download OpenSSL/Putty/GnuPG sources. All of them contains source of corresponding encryption algorithm. Also, each algorithm has reference implementation in C, which can be easily found over internet.
精彩评论