
#include <string.h>
#include "sign.h"
#include "hash.h"
#include "utils.h"

void getFullkey(
    ECC_PARAMS *params,
    char *ID,  // 用户ID
    big d,     // 用户部分私钥
    big x,     // 用户秘密值
    epoint *X, // 用户公钥
    big sa    // 用户完整私钥
)
{
    // 计算hash值H_2(ID, X)
    big h_2_big = mirvar(0);
    hash2(ID, X, (*params).p, h_2_big);

    // 计算sa = d + h_2*x mod p
    big tmp = mirvar(0);
    multiply(x, h_2_big, tmp);
    add(d, tmp, sa);
    power(sa, 1, (*params).p, sa); // mod p

    mirkill(h_2_big);
    mirkill(tmp);
}

void sign_Thumbur(
    ECC_PARAMS *params,
    char *ID,  // 用户ID
    char *msg, // 签名消息
    big sa,    // 输入用户完整私钥
    epoint *Q, // 输入用户完整公钥
    epoint *U, // 输出签名的随机数变换
    epoint *PK_pub, //输入KGC的公钥
    big v      // 输出签名的计算值
)
{
    // 产生随机数u,计算U=uP
    big u = mirvar(0);
    bigrand((*params).p, u);
    ecurve_mult(u, (*params).P, U);

    // 计算hash值H_3(ID, msg, Q, U, PK_pub)
    big h_3_big = mirvar(0);
    hash3(ID, msg, Q, U, PK_pub, (*params).p, h_3_big);

    // 计算签名值 v = u + h_3*sa
    big tmp = mirvar(0);
    multiply(sa, h_3_big, tmp);
    add(u, tmp, v);
    power(v, 1, (*params).p, v); // mod p
    outbig(v, "v");

    mirkill(u);
    mirkill(h_3_big);
    mirkill(tmp);
}

bool verify_Thumbur(
    ECC_PARAMS *params,
    char *ID,
    char *msg,
    epoint *Q,
    epoint *PK_pub,
    epoint *U,
    big v
)
{
    // 计算hash值H_1(ID, Q, PK_pub)
    big h_1_big = mirvar(0);
    hash1(ID, Q, PK_pub, (*params).p, h_1_big);

    // 计算hash值H_3(ID, msg, Q, U, PK_pub)
    big h_3_big = mirvar(0);
    hash3(ID, msg, Q, U, PK_pub, (*params).p, h_3_big);

    // 验签等式 v*P = U + h_3(Q + h_1*P_pub)
    // 等式左边：
    epoint *left = epoint_init();
    ecurve_mult(v, (*params).P, left);

    // 等式右边：
    epoint *tmp_p = epoint_init();
    ecurve_mult(h_1_big, PK_pub, tmp_p);
    ecurve_add(Q, tmp_p);
    ecurve_mult(h_3_big, tmp_p, tmp_p);
    ecurve_add(U, tmp_p);

    bool bRv = false;
    if (epoint_comp(left, tmp_p))
    {
        bRv = true;
    }
    else
    {
        bRv = false;
    }

    mirkill(h_1_big);
    mirkill(h_3_big);
    epoint_free(left);
    epoint_free(tmp_p);
    return bRv;
}