예제 #1
0
def test_crack_prvkey() -> None:

    ec = CURVES["secp256k1"]

    # FIXME: make it random
    q = 0x17E14A7B6A307F426A94F8114701E7C8E774E7F9A47E2C2035DB29A206321725

    msg1 = "Paolo is afraid of ephemeral random numbers"
    m_1 = reduce_to_hlen(msg1)
    k = _rfc6979(m_1, q)
    sig1 = dsa._sign(m_1, q, k)

    msg2 = "and Paolo is right to be afraid"
    m_2 = reduce_to_hlen(msg2)
    # reuse same k
    sig2 = dsa._sign(m_2, q, k)

    qc, kc = dsa.crack_prvkey(msg1, sig1, msg2, sig2)
    assert q in (qc, ec.n - qc)
    assert q == qc
    assert k in (kc, ec.n - kc)
    # assert k == kc

    with pytest.raises(BTClibValueError, match="not the same r in signatures"):
        dsa.crack_prvkey(msg1, sig1, msg2, (16, sig1[1]))

    with pytest.raises(BTClibValueError, match="identical signatures"):
        dsa.crack_prvkey(msg1, sig1, msg1, sig1)
예제 #2
0
def test_rfc6979_tv() -> None:

    fname = "rfc6979.json"
    filename = path.join(path.dirname(__file__), "test_data", fname)
    with open(filename, "r") as file_:
        test_dict = json.load(file_)

    for ec_name in test_dict:
        ec = CURVES[ec_name]
        test_vectors = test_dict[ec_name]
        for x, x_U, y_U, hf, msg, k, r, s in test_vectors:
            x = int(x, 16)
            m = reduce_to_hlen(msg, hf=getattr(hashlib, hf))
            # test RFC6979 implementation
            k2 = _rfc6979(m, x, ec, getattr(hashlib, hf))
            assert k == hex(k2)
            # test RFC6979 usage in DSA
            sig = dsa._sign(m,
                            x,
                            k2,
                            low_s=False,
                            ec=ec,
                            hf=getattr(hashlib, hf))
            assert r == hex(sig[0])
            assert s == hex(sig[1])
            # test that RFC6979 is the default nonce for DSA
            sig = dsa._sign(m,
                            x,
                            None,
                            low_s=False,
                            ec=ec,
                            hf=getattr(hashlib, hf))
            assert r == hex(sig[0])
            assert s == hex(sig[1])
            # test key-pair coherence
            U = mult(x, ec.G, ec)
            assert int(x_U, 16), int(y_U, 16) == U
            # test signature validity
            dsa.assert_as_valid(msg, U, sig, ec, getattr(hashlib, hf))
예제 #3
0
def sign(ec: Curve,
         hf: Callable[[Any], Any],
         msg: bytes,
         q: int,
         k: Optional[int] = None) -> ECDS:
    """ECDSA signing operation according to SEC 1

       http://www.secg.org/sec1-v2.pdf
    """

    # https://tools.ietf.org/html/rfc6979#section-3.2
    # The message msg is first processed by hf, yielding the value
    # msghd = hf(msg), a sequence of bits of length hlen.
    # Normally, hf is chosen such that
    # its output length hlen is roughly equal to nlen, since the overall
    # security of the signature scheme will depend on the smallest of hlen
    # and nlen; however, the ECDSA standard support all combinations of
    # hlen and nlen.

    # Steps numbering follows SEC 1 v.2 section 4.1.3

    msghd = hf(msg).digest()  # 4
    # H(msg) is transformed into an integer modulo ec.n using int_from_bits:
    c = int_from_bits(ec, msghd)  # 5

    # The secret key q: an integer in the range 1..n-1.
    # SEC 1 v.2 section 3.2.1
    if not 0 < q < ec.n:
        raise ValueError(f"private key {hex(q)} not in [1, n-1]")

    if k is None:
        k = _rfc6979(ec, hf, c, q)  # 1
    if not 0 < k < ec.n:
        raise ValueError(f"ephemeral key {hex(k)} not in [1, n-1]")

    # second part delegated to helper function
    return _sign(ec, c, q, k)
예제 #4
0
    return r == v  # 8


random.seed(42)

# setup
qs = []
es = []
Qs = []
sigs = []
for _ in range(5):
    q = random.getrandbits(ec.nlen) % ec.n
    qs.append(q)
    Qs.append(ec.mult(q, ec.G))
    e = random.getrandbits(ec.nlen) % ec.n
    es.append(e)
    k = _rfc6979(e, q)
    sigs.append(_sign(e, q, k))

start = time.time()
for i in range(len(qs)):
    assert _verhlp(ec, es[i], Qs[i], sigs[i], True)
elapsed1 = time.time() - start

start = time.time()
for i in range(len(qs)):
    assert _verhlp(ec, es[i], Qs[i], sigs[i], False)
elapsed2 = time.time() - start

print(elapsed2 / elapsed1)