package org.bdware.sc.bean;

import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
import org.zz.gmhelper.BCECUtil;
import org.zz.gmhelper.SM2KeyPair;
import org.zz.gmhelper.SM2Util;

import java.math.BigInteger;

public abstract class SM2Verifiable {
    // signature is der encoded
    public String signature;

    public abstract String getPublicKey();

    public abstract void setPublicKey(String pubkey);

    public abstract String getContentStr();

    public void doSignature(String privateKey) {
        BigInteger pKey = new BigInteger(privateKey, 16);
        ECPoint p = SM2Util.G_POINT.multiply(pKey).normalize();
        doSignature(new SM2KeyPair(new ECPublicKeyParameters(p, SM2Util.DOMAIN_PARAMS), pKey));
    }

    public void doSignature(SM2KeyPair pair) {
        try {
            setPublicKey(pair.getPublicKeyStr());

            signature =
                    ByteUtils.toHexString(
                            SM2Util.sign(
                                    pair.getPrivateKeyParameter(), getContentStr().getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean verifySignature() {
        try {
            String verifiedStr = getContentStr();
            ECPublicKeyParameters pubKey =
                    BCECUtil.createECPublicKeyFromStrParameters(
                            getPublicKey(), SM2Util.CURVE, SM2Util.DOMAIN_PARAMS);
            return SM2Util.verify(
                    pubKey, verifiedStr.getBytes(), ByteUtils.fromHexString(signature));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }
}
