Skip to content

Instantly share code, notes, and snippets.

@bricef
Last active May 11, 2024 21:15
Show Gist options
  • Save bricef/2436364 to your computer and use it in GitHub Desktop.
Save bricef/2436364 to your computer and use it in GitHub Desktop.
A simple example of using AES encryption in Java and C.

README

DO NOT USE THIS CODE IN PRODUCTION

This is an educational example of how to use the Java and C AES libraries originally from a Stackoverflow Answer. This code is not safe and it is not an example of how to securely use AES.

Many additional factors will need to be considered when buidling a secure system that uses AES, for example: How to properly use IVs; Block cipher modes and their properties; Secure key generation; Key distribution; message and author authentication; and many more factors besides.

At a minimum, you'll want to go through and make sure you understand the Cryptography Engineering Book, and are aware of any current security issues reported about the library you are using.

If you don't already

  • Know how to use and import a C library
  • Understand what IVs are and how they should be used
  • Understand the difference between block size and key size
  • Know that Libmcrypt is deprecated and why you still want to use it

Do not use this code.

Libmcrypt is deprecated

The library used in the C example, Libmcrypt, is deprecated. It'll work, but for most use cases, you'll want to use a more modern cryptographic library. Current recommeded best practice would point to NaCl and its close cousin Libsodium Which have been extensively tested, audited and only allow current best practice algorithms and methods.

Issues with the code

As commented below there are a couple of issues with the code. It was written to be a quick example, not a reference and as such handles its data badly.

@rwst comments:

[...] the buffer, when decrypted, certainly won't have a 0 byte at the end, so printing it as is, even if it is printable, will get another unexpected result.

You should know what this means and how to handle the case where the decrypted data doesn't include a terminating null character.

You should be able to realise that the C code currently encrypts memory outside of the plaintext string since the buffer length is greater than the string length (and why the Java string is padded). If this isn't clear to you, don't use this code.

Common issues

AES.c:9:20: fatal error: mcrypt.h: No such file or directory

If you are getting this error and do not know what it means or how to resolve it, STOP. YOU DO NOT KNOW ENOUGH TO BE WRITING SECURITY SOFTWARE. I will not help you to resolve this issue, to discourage you from continuing with this code sample.

I'm sorry to be so blunt, and don't want to discourage you from learning C programming or software security, which are both very rewarding, but you should start your journey with a simpler example. There are many great resources for you. I'd recommend starting with The C Programming Language. It's old now, and has some questionable examples and practices, but it's still a great start. There is also a communtiy list of resources on Stackoverflow to get you started.

Recommended resources

If you want to learn more about how to use cryptography correctly, a good start is Cryptography Engineering. You should also use modern, independently audited and tested libraries like NaCl or Libsodium.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
* MCrypt API available online:
* http://linux.die.net/man/3/mcrypt
*/
#include <mcrypt.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
int encrypt(
void* buffer,
int buffer_len, /* Because the plaintext could include null bytes*/
char* IV,
char* key,
int key_len
){
MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
int blocksize = mcrypt_enc_get_block_size(td);
if( buffer_len % blocksize != 0 ){return 1;}
mcrypt_generic_init(td, key, key_len, IV);
mcrypt_generic(td, buffer, buffer_len);
mcrypt_generic_deinit (td);
mcrypt_module_close(td);
return 0;
}
int decrypt(
void* buffer,
int buffer_len,
char* IV,
char* key,
int key_len
){
MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL);
int blocksize = mcrypt_enc_get_block_size(td);
if( buffer_len % blocksize != 0 ){return 1;}
mcrypt_generic_init(td, key, key_len, IV);
mdecrypt_generic(td, buffer, buffer_len);
mcrypt_generic_deinit (td);
mcrypt_module_close(td);
return 0;
}
void display(char* ciphertext, int len){
int v;
for (v=0; v<len; v++){
printf("%d ", ciphertext[v]);
}
printf("\n");
}
int main()
{
MCRYPT td, td2;
char* plaintext = "test text 123";
char* IV = "AAAAAAAAAAAAAAAA";
char* key = "0123456789abcdef";
int keysize = 16; /* 128 bits */
char* buffer;
int buffer_len = 16;
buffer = calloc(1, buffer_len);
strncpy(buffer, plaintext, buffer_len);
printf("==C==\n");
printf("plain: %s\n", plaintext);
encrypt(buffer, buffer_len, IV, key, keysize);
printf("cipher: "); display(buffer , buffer_len);
decrypt(buffer, buffer_len, IV, key, keysize);
printf("decrypt: %s\n", buffer);
return 0;
}
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES {
static String IV = "AAAAAAAAAAAAAAAA";
static String plaintext = "test text 123\u0000\u0000\u0000"; /*Note null padding*/
static String encryptionKey = "0123456789abcdef";
public static void main(String [] args) {
try {
System.out.println("==Java==");
System.out.println("plain: " + plaintext);
byte[] cipher = encrypt(plaintext, encryptionKey);
System.out.print("cipher: ");
for (int i=0; i<cipher.length; i++)
System.out.print(new Integer(cipher[i])+" ");
System.out.println("");
String decrypted = decrypt(cipher, encryptionKey);
System.out.println("decrypt: " + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
}
@caoyang1024
Copy link

Thank you for this. I have 2 questions

  1. I got an error says: Input length not multiple of 16 bytes. Can I change the padding to 'AES/CBC/PKCS5Padding' ?

  2. Should I change the IV ' static String IV = "AAAAAAAAAAAAAAAA";' to another value?

@jouini1311
Copy link

Thank you for this post

@Shardss
Copy link

Shardss commented May 3, 2015

I tried using this example but it doesn't work. I read the first comment and started doing corrections: the key and the IV seem fine to me (he's doing a .getBytes() call, where's the problem? Is this not a conversion?) and for adding the 0 byte at the end of the buffer, I altered the decryption function to:

public String decrypt(byte[] cipherText, String encryptionKey, String IV) throws Exception
{
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));

byte[] buff = cipher.doFinal(cipherText);
byte[] res = new byte[buff.length +1];
for(byte i=0; i<buff.length; i++)
{res[i] = buff[i];}
res[res.length-1] = 0;

return new String(res,"UTF-8");
}

It still doesn't work and returns gibberish. Can someone please help :S?

@NitinLnt
Copy link

Please tell me the procedure of compilation. I tried but could not include mcrypt file
getting this error:
root@sysadmin-OptiPlex-7010:/home/sysadmin/Workspace/g# gcc -o a AES.c
AES.c:9:20: fatal error: mcrypt.h: No such file or directory
#include <mcrypt.h>
^
compilation terminated.

@gurudath
Copy link

Please see my blog , you can find step by step implementation of aes-cipher-encryption-decryption-algorithms https://gurudathbn.wordpress.com/2015/02/04/aes-cipher-encryption-decryption-algorithms-using-ruby-on-rails/ for clear solution for ruby on rails

@xeno6696
Copy link

xeno6696 commented Aug 6, 2015

Please note that this implementation isn't secure... its simple and quick. It has a weakness:

https://cwe.mitre.org/data/definitions/329.html

@xeno6696
Copy link

xeno6696 commented Aug 6, 2015

Java doesn't use "\0" for null bytes either.

static String plaintext = "test text 123\0\0\0"; /*Note null padding*/
should be
static String plaintext = "test text 123\u0000\u0000\u0000"; /*Note null padding*/

@Dhevasenapathi
Copy link

Is it possible to include encryption in embedded c code.

@codingalpha
Copy link

Also you can check this C Program To Encrypt and Decrypt Text Files using Caesar Cipher's Text!
Link: http://www.codingalpha.com/file-handling-program-to-encrypt-and-decrypt-in-c-programming/

@ymanzon
Copy link

ymanzon commented Jun 14, 2016

excelent post!

@darill
Copy link

darill commented Jul 17, 2016

god afternoonmm please l am a student at level 4 in security... and our teacher ask us to write a software on an AES encryption system with a graphical user interface using java... so how can l start please

@Thuetar
Copy link

Thuetar commented Aug 12, 2016

Don't know about everyone else, but I love doing someone's homework.
@darill can you please give us some more details regarding your homework?

@Noe007
Copy link

Noe007 commented Sep 2, 2016

Thanks:)

@amkah
Copy link

amkah commented Dec 11, 2016

Can any body explain to me how to use the mcrypt API? Thanks in advance

@klgopal
Copy link

klgopal commented Feb 14, 2017

pls can anyone confirm if rijndael-128 used in C implementation is AES 256 bit encryption or not.

will the same prog work with keysize as 32 instead of 16 in c program.

@shai1esh
Copy link

can you modify the code using new libraries as mcrypt.h is abandoned...!

@mootensai
Copy link

Sorry, i'm a noob here, could someone explain why the cipher text is integer?? If I encrypt use PHP, the output is letters and special chars.
How to make output letters and special chars??

@melvyniandrag
Copy link

melvyniandrag commented Nov 7, 2017

@rwst I don't know what you mean about the the defining full 8 bit byte data and waiting for compiler magic? I think youre referring to passing char* to int mcrypt_generic_init( MCRYPT td, void *key, int lenofkey, void *IV);? Anyway who cares. At the end of the day I don't know of anyone using mcrypt, I've only seen gcrypt in production.

http://mcrypt.hellug.gr/lib/mcrypt.3.html

@22karthik
Copy link

Hi
I am getting mcrypt.h file not found.Please let me know how to use mycrypt.h api

@akshay0297
Copy link

akshay0297 commented Feb 14, 2018

If you are using Ubuntu add related mcrypt libraries using the command sudo apt-get install libmcrypt-dev

@Hansum
Copy link

Hansum commented Feb 19, 2018

How can we use the MCRYPT API? PLSS REPLY ASAP :(

@chandralakagwad
Copy link

Thank you.. Your post was really helpful

@chandralakagwad
Copy link

If I want to encrypt the whole file instead of just a single sentence. What modification is required in the code? and How can we get the secret key? Its not displayed in the output.

@EdTodd
Copy link

EdTodd commented Dec 30, 2020

I've got an app with microprocessors using C talking to Android using Java. I am using AES-128, but am trying to make keys more complex. Examples I have seen use the Base64 character set in keys, but I am trying to use a full 128 bit key, any value (apart from 0x00 bytes, which I am avoiding for C reasons). In my tests, I managed to get a message from Java to C devices and decrypt it properly. The reply does not decrypt properly in the Java code. If I turn off the top bit (sign bit) in all 16 bytes, it works. This sort of turns my attempt at full AES 128 into a sort of AES 112. Is there an Android Java function that will get me round this?

@EdTodd
Copy link

EdTodd commented Dec 30, 2020

The Java AES code I am using has "Created by tehcpu on 11/12/17." in the header.

@bricef
Copy link
Author

bricef commented Jan 4, 2021

@EdTodd

apart from 0x00 bytes, which I am avoiding for C reasons

Don't. That creates a bias in the key generation that can be exploited.

@rwst & @xeno6696

Thank you both for the corrections. This was never meant as a reference or canonical example, just a quick brain dump for a stackoverflow answer. Didn't realise people would pick this up like this! I'll make sure that's clear in the code itself and attempt to remedy the issues you found.

@Padmanabh82
Copy link

After running this code i getting an error

/usr/bin/ld: /tmp/cc33RZwa.o: in function encrypt': ex.c:(.text+0x34): undefined reference to mcrypt_module_open'
/usr/bin/ld: ex.c:(.text+0x44): undefined reference to mcrypt_enc_get_block_size' /usr/bin/ld: ex.c:(.text+0x72): undefined reference to mcrypt_generic_init'
/usr/bin/ld: ex.c:(.text+0x88): undefined reference to mcrypt_generic' /usr/bin/ld: ex.c:(.text+0x94): undefined reference to mcrypt_generic_deinit'
/usr/bin/ld: ex.c:(.text+0xa0): undefined reference to mcrypt_module_close' /usr/bin/ld: /tmp/cc33RZwa.o: in function decrypt':
ex.c:(.text+0xdf): undefined reference to mcrypt_module_open' /usr/bin/ld: ex.c:(.text+0xef): undefined reference to mcrypt_enc_get_block_size'
/usr/bin/ld: ex.c:(.text+0x11d): undefined reference to mcrypt_generic_init' /usr/bin/ld: ex.c:(.text+0x133): undefined reference to mdecrypt_generic'
/usr/bin/ld: ex.c:(.text+0x13f): undefined reference to mcrypt_generic_deinit' /usr/bin/ld: ex.c:(.text+0x14b): undefined reference to mcrypt_module_close'
collect2: error: ld returned 1 exit status

@aziascreations
Copy link

Could you at the very least have the decency to include instructions on how you can install the package for God's sake...

@bricef
Copy link
Author

bricef commented Nov 16, 2021

Could you at the very least have the decency to include instructions on how you can install the package for God's sake...

@aziascreations Firstly, please read the README carefully. I deliberately did not include such instructions to prevent people who have no business writing crypto code from doing this. As clearly stated:

If you are getting this error and do not know what it means or how to resolve it, STOP. YOU DO NOT KNOW ENOUGH TO BE WRITING SECURITY SOFTWARE. I will not help you to resolve this issue, to discourage you from continuing with this code sample.

Secondly, don't be entitled. I don't owe you any instructions. If you're interested in paying me to write a thorough AES guide in Java and C or for me to provide you with consultancy, please don't hesitate to reach out by email [email protected].

@adityashah1603
Copy link

i am getting undefined references for some of the predefined function from the mcrypt file, i checked the names and they match, any fix? if yes it would be highly appreciated to be answered ASAP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment