Skip to content

Latest commit

 

History

History
 
 

Bitcoin

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Bitcoin

项目完成人:郭灿林

文件名 项目
bitcoinTX.md Project: send a tx on Bitcoin testnet, and parse the tx data down to every bit, better write script yourself
ECDSA.py Project: forge a signature to pretend that you are Satoshi

运行指导: 需要安装以下库,并且需要python运行环境。

pip install numpy
pip install Crypto
pip install hashlib

Bitcoin TX 分析

file :bitcoinTX.md

Project : send a tx on Bitcoin testnet, and parse the tx data down to every bit, better write script yourself

具体报告见bitcoinTX.md文件。

ECDSA签名伪造

file : ECDSA.py

Project : forge a signature to pretend that you are Satoshi.

该项目实现了ECDSA签名和验证,并且实现了签名的伪造,其中签名的伪造只能得到某个特定hash值的签名,但是无法直接得到消息的签名值,随机选择$u,v$,计算$R'=(x',y')=uG+vP, r' = x' \pmod{n}$,为了通过验证,需要$s'^{-1}(e'G+r'P) = uG + vP$,令$e'=r'uv^{-1}\pmod{n},s'=r'v^{-1}\pmod{n}$,那么得到的$(r',s')$即为哈希值$e'$用未知的私钥$d$签的签名。

某次运行结果如下:

签名验证:

pic

伪造成功:

pic

代码说明

add函数和mult函数分别实现了椭圆曲线加法群上的加法和点乘运算。两个函数参考了组员李岱耕的SM2实现部分。

def add(P, Q):
        if not P:
            return Q
        if not Q:
            return P
        if P[0] == Q[0]:
            if (P[1] + Q[1]) % p == 0:
                return
            lmd = (3 * P[0] * Q[0] + a) * \
                pow(int(P[1] + Q[1]), p - 2, p) % p
        else:
            lmd = (Q[1] - P[1]) * pow(int(Q[0] - P[0]), p - 2, p) % p
        x = (lmd * lmd - P[0] - Q[0]) % p
        y = (lmd * (P[0] - x) - P[1]) % p
        return x, y

def mult(n, P):
        if n == 0:
            return
        Q = mult(n >> 1, P)
        return add(add(Q, Q), P) if n & 1 else add(Q, Q)

ECDSASign函数实现了ECDSA签名算法的签名部分,ECDSAVrfy函数实现了ECDSA签名算法的验证部分。

def ECDSASign(d, e, n, G):  #e = hash(m)
    while 1:
        k = random.randint(1, n)
        R = mult(k, G)
        r = R[0] % n
        s = (inverse(k, n) * (e + d * r)) % n
        if s == 0 or r == 0:
            continue
        else:
            break
    return [r, s]
def ECDSAVrfy(P, e, n, G, r, s):  #e = hash(m)
    w = inverse(s, n) % n
    t1 = (e * w) % n
    t2 = (r * w) % n
    X = add(mult(t1, G), mult(t2, P))
    if X == None:
        print("the sig invalid")
        return
    else:
        r_ = X[0] % n
    if r == r_:
        return 1
    else:
        return 0

pretend函数实现了对某个hash值的签名伪造。

def pretend(G, P, n):
    u = random.randint(1, n)
    v = random.randint(1, n)
    R = ECCADD(ECCMUL(u, G), ECCMUL(v, P))
    if R == 0:
        r = 0
    else:
        r = R[0] % n
    e = (r * u * inverse(v, n)) % n
    s = (r * inverse(v, n)) % n
    return e, r, s