8

I found a lot of implementations 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?

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
killercode
  • 1,666
  • 5
  • 29
  • 42
  • 2
    http://polarssl.org/trac/browser/trunk/library/aes.c http://polarssl.org/trac/browser/trunk/include/polarssl/aes.h the `981 int aes_self_test( int verbose )` function contains the necessary example code to work with. – soulseekah Jan 14 '11 at 06:35
  • i seen this before, but it only encrypts char array of length 16, and im not that good to mod the main functions, thank you – killercode Jan 14 '11 at 06:40
  • Also this one here is good as well http://www.hoozi.com/Articles/AESEncryption.htm try googling for the other two, there are lots of them around, and their `test` functions usually contain good examples. I hope I've understood and helped you with your question, if not, please elaborate more. – soulseekah Jan 14 '11 at 06:40
  • @killercode So what is your main objective? That you can't find an implementation suitable for your requirements? What are these requirements, please define them in the question. – soulseekah Jan 14 '11 at 06:42
  • And by the way, don't forget that AES is a block cipher. – soulseekah Jan 14 '11 at 06:43
  • 1
    all i need is just (char *) encryption, i just wanna secure some data in my application files using any of those encryptions. something like AESEncrypt(char *Data, int len, char *Password, int KeySize);, if possible thats all – killercode Jan 14 '11 at 06:50
  • You may want to try Rijndael instead of AES, the former supports encryption of block sizes in any multiple of 32-bits, whereas AES is limited to 128-bits (16 chars) per block. – soulseekah Jan 14 '11 at 06:50
  • ok, anything will do, i just cant seem to find a good example, and im not really a C guru, just want this thing done, thank you. – killercode Jan 14 '11 at 06:52
  • Twofish is also a 128-bit max. block size cipher, and so is Serpent. You shall have to encrypt your data block by block, and decrypt it block by block. – soulseekah Jan 14 '11 at 06:52
  • u dont know any examples i can make use of? – killercode Jan 14 '11 at 06:53
  • @killercode if you're not limited to C, I suggest looking into CryptoPP C++ library. You'll have to download, compile and link the library to your application. – soulseekah Jan 14 '11 at 06:54
  • 1
    16 octets is the native block length for AES, Twofish, and Serpent. If you have found an API that gives you this then you need to implement a cipher mode around it. The recommended mode for those block ciphers is CBC in most cases. http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation – Lunatic Experimentalist Jan 14 '11 at 06:56
  • The Hoozi implementation of AES is good. http://www.hoozi.com/post/829n1/advanced-encryption-standard-aes-implementation-in-c-c-with-comments-part-1-encryption has all what you are looking for in the `main()` function, try it out, it works. – soulseekah Jan 14 '11 at 06:57
  • i am, i have to do it in c, since most of my app is in c, i cant port all that all over, and im better in c – killercode Jan 14 '11 at 06:57
  • If most of your app is in C, then I assume you know enough C to interface the Hooze implementation, its `main()` contains the correct procedure, the necessary loops and everything. – soulseekah Jan 14 '11 at 06:59
  • yea, but again, it only supports char data[16] to encrypt, and my data could be big, can't loop throught every 16 chars, that will definetly take time, and check if not aligned data too :/ – killercode Jan 14 '11 at 07:02
  • "You are advised not to use this implementation directly in any security product or application. Please use this AES source code only a base for starting your work. You may add some feedback mechanisms (also called Cipher Block Chaining Modes) to increase the security of this AES implementation and also to reduce security risks such as Block Replay. If you are not using any Cipher Block Chaining Mode, an adversary may be able to detect and exploit patterns in your message." ~ Hoozi. Read what @Lunatic Experimentatlist wrote. – soulseekah Jan 14 '11 at 07:03
  • @killercode, the cipher is a block cipher, you'll have to loop through, there is no other way. Check stream ciphers if you're not up to the CBC idea. http://en.wikipedia.org/wiki/Stream_cipher#Usage – soulseekah Jan 14 '11 at 07:05
  • 1
    dude, i just wanna encrypt my strings, its not that essential to study, block cipher or stream cipher i just wanna encrypt my strings in c, Rijndael, Aes, Twofish, CBC, EBC whatever that will do it – killercode Jan 14 '11 at 07:07
  • @killercode Go with RC4 http://en.wikipedia.org/wiki/RC4#Implementation stream cipher then. If you want something even simpler, without the need to study, use a Ceasar Cipher. – soulseekah Jan 14 '11 at 07:09
  • 1
    i just asked for AES or Twofish or Rijndael or Serpent, thats all im asking – killercode Jan 14 '11 at 07:19
  • If you decide to at least read and understand the source code for AES implementation, http://polarssl.org/trac/browser/trunk/library/aes.c the PolarSSL file has got tests (and the code for) three cipher modes of AES (lines 981 up to the end). – soulseekah Jan 14 '11 at 07:21
  • @killercode, if you're really wanting block ciphers you'll have to do some reading (wiki+source code), I don't see any other way out. It will take you less than a day to understand it all and implement it. – soulseekah Jan 14 '11 at 07:23

3 Answers3

8

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.
Community
  • 1
  • 1
  • thanks, but still the problem presists, im not into cryptography, i just needed some strings encrypted, my field is totally diffrent, if there is any ready made example would be kewl, thanks. – killercode Jan 15 '11 at 04:57
  • Unfortunately cryptography is difficult to implement securely and most uses are part of larger products. There aren't many cases for just encrypting what you'd call a string - normally you're looking at encrypting bytes of data. In fact, ciphers are designed for that purpose. But crypto++ might be good for you, as others have suggested. My links will help you understand the implementation but if you just want to use it crypto++ is not a bad start. –  Jan 16 '11 at 16:46
  • 1
    I am the author of that AES tutorial. I have also made a Twofish tutorial, located here: http://www.rohitab.com/discuss/topic/36074-c-twofish/ – Ledio Berdellima Mar 29 '11 at 21:17
  • @X-N20 Ah hello! It's a good tutorial. I've linked your SO account next to the mention of it so that it's clearer. –  Mar 29 '11 at 21:22
  • Tutorial link is broken :( – kemicofa ghost Nov 15 '16 at 14:25
1

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! :)

NoOne
  • 3,851
  • 1
  • 40
  • 47
0

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.

Nickolay Olshevsky
  • 13,706
  • 1
  • 34
  • 48