Java tutorial
//package com.java2s; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; import java.nio.ByteBuffer; import java.security.*; import java.util.Arrays; public class Main { static final int AES_BLOCK_SIZE = 16; public static byte[] messageEncrypt(byte[] authKey, byte[] msgKey, byte[] data, boolean isOut) { byte[] key = getAESkey(authKey, msgKey, isOut); byte[] iv = getAESiv(authKey, msgKey, isOut); return aesIGEencrypt(iv, key, data); } public static byte[] getAESkey(byte[] authKey, byte[] msgKey, boolean isOut) { int x = 0; if (!isOut) x = 8; ByteBuffer tempA = ByteBuffer.allocate(msgKey.length + 32); tempA.put(msgKey); tempA.put(authKey, x, 32); byte[] a = getSHA1hash(tempA.array()); ByteBuffer tempB = ByteBuffer.allocate(msgKey.length + 32); tempB.put(authKey, 32 + x, 16); tempB.put(msgKey); tempB.put(authKey, 48 + x, 16); byte[] b = getSHA1hash(tempB.array()); ByteBuffer tempC = ByteBuffer.allocate(msgKey.length + 32); tempC.put(authKey, 64 + x, 32); tempC.put(msgKey); byte[] c = getSHA1hash(tempC.array()); ByteBuffer key = ByteBuffer.allocate(8 + 12 + 12); key.put(a, 0, 8); key.put(b, 8, 12); key.put(c, 4, 12); return key.array(); } public static byte[] getAESiv(byte[] authKey, byte[] msgKey, boolean isOut) { int x = 0; if (!isOut) x = 8; ByteBuffer tempA = ByteBuffer.allocate(msgKey.length + 32); tempA.put(msgKey); tempA.put(authKey, x, 32); byte[] a = getSHA1hash(tempA.array()); ByteBuffer tempB = ByteBuffer.allocate(msgKey.length + 32); tempB.put(authKey, 32 + x, 16); tempB.put(msgKey); tempB.put(authKey, 48 + x, 16); byte[] b = getSHA1hash(tempB.array()); ByteBuffer tempC = ByteBuffer.allocate(msgKey.length + 32); tempC.put(authKey, 64 + x, 32); tempC.put(msgKey); byte[] c = getSHA1hash(tempC.array()); ByteBuffer tempD = ByteBuffer.allocate(msgKey.length + 32); tempD.put(msgKey); tempD.put(authKey, 96 + x, 32); byte[] d = getSHA1hash(tempD.array()); ByteBuffer iv = ByteBuffer.allocate(12 + 8 + 4 + 8); iv.put(a, 8, 12); iv.put(b, 0, 8); iv.put(c, 16, 4); iv.put(d, 0, 8); return iv.array(); } public static byte[] aesIGEencrypt(byte[] tmpAESiv, byte[] tmpAesKey, byte[] data) { try { ByteBuffer out = ByteBuffer.allocate(data.length); byte[] ivp = Arrays.copyOfRange(tmpAESiv, 0, tmpAESiv.length / 2); byte[] iv2p = Arrays.copyOfRange(tmpAESiv, tmpAESiv.length / 2, tmpAESiv.length); int len = data.length / AES_BLOCK_SIZE; byte[] xorInput = null; byte[] xorOutput = null; SecretKeySpec keySpec = null; keySpec = new SecretKeySpec(tmpAesKey, "AES"); Cipher cipher = null; cipher = Cipher.getInstance("AES/ECB/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, keySpec); byte[] input = null; byte[] output = null; for (int i = 0; i < len; i++) { input = Arrays.copyOfRange(data, i * AES_BLOCK_SIZE, (i + 1) * AES_BLOCK_SIZE); xorInput = xor(input, ivp); output = cipher.doFinal(xorInput); xorOutput = xor(output, iv2p); out.put(xorOutput); ivp = xorOutput; iv2p = input; } return out.array(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } return null; } public static byte[] getSHA1hash(byte[] dataByte) { MessageDigest md = null; byte[] sha1hash = new byte[20]; try { md = MessageDigest.getInstance("SHA-1"); md.update(dataByte, 0, dataByte.length); sha1hash = md.digest(); return sha1hash; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. } return null; } public static byte[] xor(byte[] a, byte[] b) { if (a.length == b.length) { byte[] res = new byte[a.length]; for (int i = 0; i < a.length; i++) { res[i] = (byte) (a[i] ^ b[i]); } return res; } else return null; } }