package znx.utils;

import java.util.*;
import javax.crypto.spec.*;
import java.security.spec.*;
import javax.crypto.*;
import java.security.*;

public class LMEncryption {
    private static final String ASYNC_TRANSFORMATION_PADDING = "RSA/ECB/PKCS1Padding";
    private static final String SYNC_ALGORITHM = "md5";
    private static final String SYNC_SECRET_KEY_ALGORITHM = "DESede";
    private static final String SYNC_TRANSFORMATION_PADDING = "DESede/CBC/PKCS5Padding";
    private static final String ALGORITHM = "RSA";

    public static PublicKey generatePublicKey(final byte[] publicKeyBytes) {
        try {
            final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            final X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes);
            return keyFactory.generatePublic(publicKeySpec);
        } catch (Exception e) {
        }
        return null;
    }

    public static PrivateKey generatePrivateKey(final byte[] privateKeyBytes) {
        PrivateKey privateKey = null;
        if (privateKeyBytes != null) {
            try {
                final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
                final PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
                privateKey = keyFactory.generatePrivate(privateKeySpec);
            } catch (Exception e) {

            }
        }
        return privateKey;
    }

    public static PrivateKey generatePrivateKey(final String encodedPrivateKey) {
        final byte[] privateKeyBytes = Base64.decode(encodedPrivateKey);
        return generatePrivateKey(privateKeyBytes);
    }

    public static byte[] decrypt(final byte[] data, final Key key) {
        return cipherAsymmetric(data, key, 2);
    }

    private static byte[] cipherAsymmetric(final byte[] data, final Key key, final int mode) {
        try {
            final Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(mode, key);
            return cipher.doFinal(data);
        } catch (Exception e) {

        }
        return null;
    }

    public static byte[] decrypt(final byte[] data, final String digestString) {
        return cipherSymmetric(data, digestString, 2);
    }

    private static byte[] cipherSymmetric(final byte[] data, final String digestString, final int mode) {
        try {
            final MessageDigest md = MessageDigest.getInstance("md5");
            final byte[] digestOfPassword = md.digest(digestString.getBytes("utf-8"));
            final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
            for (int j = 0, k = 16; j < 8; keyBytes[k++] = keyBytes[j++]) {
            }
            final SecretKey key = new SecretKeySpec(keyBytes, "DESede");
            final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
            cipher.init(mode, key, new IvParameterSpec(new byte[8]));
            return cipher.doFinal(data);
        } catch (Exception e) {

        }
        return null;
    }

    public static byte[] encrypt(final byte[] data, final Key key) {
        return cipherAsymmetric(data, key, 1);
    }

    public static byte[] encrypt(final byte[] data, final String digestString) {
        return cipherSymmetric(data, digestString, 1);
    }

    public static KeyPair generateKeyPair() {
        return generateKeyPair(1024);
    }

    public static KeyPair generateKeyPair(final int keySize) {
        try {
            final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            final SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            keyGen.initialize(keySize, random);
            return keyGen.generateKeyPair();
        } catch (Exception e) {

        }
        return null;
    }

    private KeyPair generateKeyPair(final byte[] publicKeyBytes, final byte[] privateKeyBytes) {
        final PublicKey publicKey = generatePublicKey(publicKeyBytes);
        final PrivateKey privateKey = generatePrivateKey(privateKeyBytes);
        return new KeyPair(publicKey, privateKey);
    }
}
