# 如何对交易进行签名

# GXChain Signature的定义

如何生成公私钥对一文,我们介绍了GXChain的公私钥对基于椭圆曲线密码学(ECC)secp256k1曲线,而GXChain的签名是基于椭圆曲线数字签名算法(ECDSA)的,GXChain的签名由1字节的recover_id、32字节的r值和32字节的s值组成。

function ec_sign(message, private_key){
    let sha256_buffer = sha256(message);
    ECSignature ecsig = ECDSA.sign_compact(sha256_buffer, private_key);
    byte[32] r = ecsig.r;
    byte[32] s = ecsig.s;
    int i = ecsig.recovery_id + 4 +27; // compressed public key
    byte[65] signature = Buffer.concat(i,r,s);
    return signature;
}

# Signature的要求

为了防止双花问题,除了BIP62的要求外,GXChain对rs的值做了更严格的限制:

function isCanonical(r,s){
    return !(r[0] & 0x80)
        && !(r[0] == 0 && !(r[1] & 0x80))
        && !(s[0] & 0x80)
        && !(s[0] == 0 && !(s[1] & 0x80))
}

rs取值范围为[2^247,2^255)

加上isCanonical的判断后,sign方法是这样的

function sign(message, private_key){
    byte[65] signature = ec_sign(message,private_key);
    while(!isCanonical(signature.slice(1,33),signature.slice(33,65))){
        signature = ec_sign(message,private_key);
    }
    return signature;
}

# 讨论和参考

# 代码实现