package com.adioss.security.symmetric.block;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;

public class AESSymmetricEncryption {

    private static final byte[] KEY = hexStringToByteArray("C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF");
    private static final byte[] IV = new byte[]{(byte) 0x69, (byte) 0x2b, (byte) 0x74, (byte) 0x34, (byte) 0x02, (byte) 0xb2, (byte) 0xc4, (byte) 0x9e,
            (byte) 0xf9, (byte) 0x44, (byte) 0x99, (byte) 0xc9, (byte) 0x80, (byte) 0x65, (byte) 0xcd, (byte) 0x8f};
    
    private static final byte[] MESSAGE = "Hello!!".getBytes();

    static void encryptDecryptECB() throws Exception {
        SecretKey secretKey = new SecretKeySpec(KEY, "AES");

        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        byte[] encrypted = cipher.doFinal(MESSAGE);
        System.out.println("cipher: " + show(encrypted));

        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        byte[] original = cipher.doFinal(encrypted);
        System.out.println("plain: " + show(original) + "        " + new String(original));
    }

    static void encryptDecryptCBC() throws Exception {
        SecretKey secretKey = new SecretKeySpec(KEY, "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(IV));
        byte[] encrypted = cipher.doFinal(MESSAGE);
        System.out.println("cipher: " + show(encrypted));

        cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(IV));
        byte[] original = cipher.doFinal(encrypted);
        System.out.println("plain: " + show(original) + "        " + new String(original));
    }

    static void encryptDecryptGCM() throws Exception {
        SecureRandom random = SecureRandom.getInstanceStrong();
        SecretKey secretKey = new SecretKeySpec(KEY, "AES");

        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");  // GCM is no padding: NoPadding is here only for convention
        final byte[] iv = new byte[12];
        random.nextBytes(iv);
        GCMParameterSpec spec = new GCMParameterSpec(128, IV);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec);
        byte[] encrypted = cipher.doFinal(MESSAGE);
        System.out.println("cipher: " + show(encrypted));

        cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
        byte[] original = cipher.doFinal(encrypted);
        System.out.println("plain: " + show(original) + "        " + new String(original));
    }

    private static String show(byte[] encrypted) {
        String result = "";
        for (byte b : encrypted) {
            result += b + " ";
        }
        return result;
    }

    private static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }
}

@@ -263,15 +263,8 @@
 m;%0A%0A
-public 
 clas
@@ -290,17 +290,16 @@
 ption %7B%0A
-%0A
     priv
@@ -332,64 +332,251 @@
 Y = 
-hexStringToByteArray(%22C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF%22)
+new byte%5B%5D%7B(byte) 0x69, (byte) 0x69, (byte) 0x2b, (byte) 0x74, (byte) 0x9e,%0A            (byte) 0x80, (byte) 0x80, (byte) 0x65, (byte) 0x74, (byte) 0x65, (byte) 0x9e, (byte) 0x99, (byte) 0x99,%0A            (byte) 0x99, (byte) 0x74, (byte) 0x99,%7D
 ;%0A  
@@ -842,20 +842,16 @@
  0x8f%7D;%0A
-    
 %0A    pri
@@ -3074,333 +3074,7 @@
    %7D
-%0A%0A    private static byte%5B%5D hexStringToByteArray(String s) %7B%0A        int len = s.length();%0A        byte%5B%5D data = new byte%5Blen / 2%5D;%0A        for (int i = 0; i %3C len; i += 2) %7B%0A            data%5Bi / 2%5D = (byte) ((Character.digit(s.charAt(i), 16) %3C%3C 4) + Character.digit(s.charAt(i + 1), 16));%0A        %7D%0A        return data;%0A    %7D
 %0A%7D%0A

Add some AES tests