package com.ruoyi.common.security.utils;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;

/**
 * 类的用途：加密处理工具类
 */
public class CipherUtil {

	private int ct;

	private ECPoint p2;

	private SM3Util sm3keybase;

	private SM3Util sm3c3;

	private byte key[];

	private byte keyOff;

	protected CipherUtil() {
		this.ct = 1;
		this.key = new byte[32];
		this.keyOff = 0;
	}

	private void Reset() {
		this.sm3keybase = new SM3Util();
		this.sm3c3 = new SM3Util();

//		byte p[] = CipherUtil.byteConvert32Bytes(p2.getX().toBigInteger());
		byte p[] = CipherUtil.byteConvert32Bytes(p2.getAffineXCoord().toBigInteger());
		this.sm3keybase.update(p, 0, p.length);
		this.sm3c3.update(p, 0, p.length);

		p = CipherUtil.byteConvert32Bytes(p2.getAffineYCoord().toBigInteger());
		this.sm3keybase.update(p, 0, p.length);
		this.ct = 1;
		NextKey();
	}

	private void NextKey() {
		SM3Util sm3keycur = new SM3Util(this.sm3keybase);
		sm3keycur.update((byte) (ct >> 24 & 0xff));
		sm3keycur.update((byte) (ct >> 16 & 0xff));
		sm3keycur.update((byte) (ct >> 8 & 0xff));
		sm3keycur.update((byte) (ct & 0xff));
		sm3keycur.doFinal(key, 0);
		this.keyOff = 0;
		this.ct++;
	}


	protected void Encrypt(byte data[]) {
		this.sm3c3.update(data, 0, data.length);
		for (int i = 0; i < data.length; i++) {
			if (keyOff == key.length) {
				NextKey();
			}
			data[i] ^= key[keyOff++];
		}
	}

	protected void Init_dec(BigInteger userD, ECPoint c1) {
		this.p2 = c1.multiply(userD).normalize();
		Reset();
	}

	protected void Decrypt(byte data[]) {
		for (int i = 0; i < data.length; i++) {
			if (keyOff == key.length) {
				NextKey();
			}
			data[i] ^= key[keyOff++];
		}

		this.sm3c3.update(data, 0, data.length);
	}

	protected void Dofinal(byte c3[]) {
		byte p[] = byteConvert32Bytes(p2.getAffineYCoord().toBigInteger());
		this.sm3c3.update(p, 0, p.length);
		this.sm3c3.doFinal(c3, 0);
		Reset();
	}

	/**
	 * 整形转换成网络传输的字节流（字节数组）型数据
	 *
	 * @param num 一个整型数据
	 * @return 4个字节的自己数组
	 */
	protected static byte[] intToBytes(int num) {
		byte[] bytes = new byte[4];
		bytes[0] = (byte) (0xff & (num >> 0));
		bytes[1] = (byte) (0xff & (num >> 8));
		bytes[2] = (byte) (0xff & (num >> 16));
		bytes[3] = (byte) (0xff & (num >> 24));
		return bytes;
	}

	/**
	 * 四个字节的字节数据转换成一个整形数据
	 *
	 * @param bytes 4个字节的字节数组
	 * @return 一个整型数据
	 */
	protected static int byteToInt(byte[] bytes) {
		int num = 0;
		int temp;
		temp = (0x000000ff & (bytes[0])) << 0;
		num = num | temp;
		temp = (0x000000ff & (bytes[1])) << 8;
		num = num | temp;
		temp = (0x000000ff & (bytes[2])) << 16;
		num = num | temp;
		temp = (0x000000ff & (bytes[3])) << 24;
		num = num | temp;
		return num;
	}

	/**
	 * 长整形转换成网络传输的字节流（字节数组）型数据
	 *
	 * @param num 一个长整型数据
	 * @return 4个字节的自己数组
	 */
	protected static byte[] longToBytes(long num) {
		byte[] bytes = new byte[8];
		for (int i = 0; i < 8; i++) {
			bytes[i] = (byte) (0xff & (num >> (i * 8)));
		}

		return bytes;
	}

	/**
	 * 大数字转换字节流（字节数组）型数据 byteConvert32Bytes
	 *
	 * @author: WangBinBin
	 * @param n 大数字转换字节流
	 * @return 字节数组
	 */
	protected static byte[] byteConvert32Bytes(BigInteger n) {
		byte tmpd[] = (byte[]) null;
		if (n == null) {
			return null;
		}

		if (n.toByteArray().length == 33) {
			tmpd = new byte[32];
			System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);
		} else if (n.toByteArray().length == 32) {
			tmpd = n.toByteArray();
		} else {
			tmpd = new byte[32];
			for (int i = 0; i < 32 - n.toByteArray().length; i++) {
				tmpd[i] = 0;
			}
			System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);
		}
		return tmpd;
	}

	/**
	 * 十六进制串转化为byte数组
	 *
	 * @author: WangBinBin
	 * @param hex 十六进制串
	 * @return byte数组
	 * @throws IllegalArgumentException
	 */
	protected static byte[] hexToByte(String hex) throws IllegalArgumentException {
		if (hex.length() % 2 != 0) {
			throw new IllegalArgumentException();
		}
		try {
			return Hex.decodeHex(hex);
		} catch (DecoderException e) {
			throw new IllegalArgumentException();
		}
	}

	/**
	 * 字节数组转换为十六进制字符串
	 *
	 * @param b byte[] 需要转换的字节数组
	 * @return String 十六进制字符串
	 */
	public static String byteToHex(byte b[]) {
		return new String(Hex.encodeHex(b));
	}

}
