package org.bdware.sc.boundry.utils;

import org.bdware.sc.compiler.PermissionStub;
import org.bdware.sc.node.Permission;
import wrp.jdk.nashorn.internal.runtime.PropertyMap;
import wrp.jdk.nashorn.internal.runtime.ScriptObject;
import wrp.jdk.nashorn.internal.scripts.JO;

import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

@PermissionStub(permission = Permission.AES)
public class AESUtil {
    public static ScriptObject encrypt(String key, String plaintext) throws NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
        JO ret = new JO(PropertyMap.newMap());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        String iv = generateKey(128);
        IvParameterSpec ivSpec = new IvParameterSpec(DatatypeConverter.parseHexBinary(iv));
        byte[] byteContent = plaintext.getBytes();
        SecretKeySpec secretKeySpecSpec = new SecretKeySpec(DatatypeConverter.parseHexBinary(key), "AES");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpecSpec, ivSpec);
        byte[] result = cipher.doFinal(byteContent);
        ret.put("iv", iv, false);
        ret.put("cipherText", DatatypeConverter.printHexBinary(result).toLowerCase(), false);
        return ret;
    }

    public static String decrypt(String key, String ciphertext, String iv) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
//        JO ret = new JO(PropertyMap.newMap());
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        IvParameterSpec ivSpec = new IvParameterSpec(DatatypeConverter.parseHexBinary(iv));
        byte[] byteContent = DatatypeConverter.parseHexBinary(ciphertext);
        SecretKeySpec secretKeySpecSpec = new SecretKeySpec(DatatypeConverter.parseHexBinary(key), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpecSpec, ivSpec);
        byte[] result = cipher.doFinal(byteContent);
        return new String(result);
    }

    public static String generateKey(int bit) throws NoSuchAlgorithmException {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(bit);
        SecretKey secretKey = keyGenerator.generateKey();
        return DatatypeConverter.printHexBinary(secretKey.getEncoded()).toLowerCase();
    }
}
