<commit_before>#!/usr/bin/env python3

""" Elliptic Curve Digital Signature Algorithm
"""

from hashlib import sha256
from ellipticcurves import secp256k1 as ec
from numbertheory import mod_inv
from rfc6979 import rfc6979
from ecsignutils import int_from_hash
from WIF_address import int_from_prvkey


def ecdsa_sign(m, prv, eph_prv=None, hasher=sha256):
    if type(m) == str: m = hasher(m.encode()).digest()
    prv = int_from_prvkey(prv)
    eph_prv = rfc6979(prv, m, hasher) if eph_prv is None else int_from_prvkey(eph_prv)
    return ecdsa_sign_raw(m, prv, eph_prv)


def ecdsa_sign_raw(m, prv, eph_prv):
    R = ec.pointMultiply(eph_prv)
    r = R[0] % ec.order
    h = int_from_hash(m, ec.order)
    # assert h
    s = mod_inv(eph_prv, ec.order) * (h + prv * r) % ec.order
    assert r != 0 and s != 0, "failed to sign"
    return r, s


def ecdsa_verify(m, dsasig, pub, hasher=sha256):
    if type(m) == str: m = hasher(m.encode()).digest()
    check_dsasig(dsasig)
    pub =  ec.tuple_from_point(pub)
    return ecdsa_verify_raw(m, dsasig, pub)


def ecdsa_verify_raw(m, dsasig, pub):
    h = int_from_hash(m, ec.order)
    r, s = dsasig
    s1 = mod_inv(s, ec.order)
    # by choice at this level do not manage point at infinity (h = 0, R = 0G)
    R = ec.pointAdd(ec.pointMultiply(r * s1 % ec.order, pub),
                    ec.pointMultiply(h * s1 % ec.order))
    return R[0] % ec.order == r


def ecdsa_pubkey_recovery(m, dsasig, y_mod_2, hasher=sha256):
    if type(m) == str: m = hasher(m.encode()).digest()
    check_dsasig(dsasig)
    assert y_mod_2 in (0, 1)
    return ecdsa_pubkey_recovery_raw(m, dsasig, y_mod_2)


def ecdsa_pubkey_recovery_raw(m, dsasig, y_mod_2):
    h = int_from_hash(m, ec.order)
    r, s = dsasig # FIXME: why is s not used?
    r1 = mod_inv(r, ec.order)
    R = (r, ec.y(r, y_mod_2))
    # by choice at this level do not manage point at infinity (h = 0, R = 0G)
    return ec.pointAdd(ec.pointMultiply(dsasig[1] * r1 % ec.order, R),
                       ec.pointMultiply(-h * r1 % ec.order))


def check_dsasig(dsasig):
    """check sig has correct dsa format
    """
    assert type(dsasig) == tuple and \
          len(dsasig) == 2 and \
          type(dsasig[0]) == int and type(dsasig[1]) == int, \
          "dsasig must be a tuple of 2 int"
    assert 0 < dsasig[0] and dsasig[0] < ec.order and \
           0 < dsasig[1] and dsasig[1] < ec.order, "r and s must be in [1..order]"

import unittest

class TestEcdsa(unittest.TestCase):
    def test_ecdsa(self):<commit_msg>use unpacked value from sig<commit_after>#!/usr/bin/env python3

""" Elliptic Curve Digital Signature Algorithm
"""

from hashlib import sha256
from ellipticcurves import secp256k1 as ec
from numbertheory import mod_inv
from rfc6979 import rfc6979
from ecsignutils import int_from_hash
from WIF_address import int_from_prvkey


def ecdsa_sign(m, prv, eph_prv=None, hasher=sha256):
    if type(m) == str: m = hasher(m.encode()).digest()
    prv = int_from_prvkey(prv)
    eph_prv = rfc6979(prv, m, hasher) if eph_prv is None else int_from_prvkey(eph_prv)
    return ecdsa_sign_raw(m, prv, eph_prv)


def ecdsa_sign_raw(m, prv, eph_prv):
    R = ec.pointMultiply(eph_prv)
    r = R[0] % ec.order
    h = int_from_hash(m, ec.order)
    # assert h
    s = mod_inv(eph_prv, ec.order) * (h + prv * r) % ec.order
    assert r != 0 and s != 0, "failed to sign"
    return r, s


def ecdsa_verify(m, dsasig, pub, hasher=sha256):
    if type(m) == str: m = hasher(m.encode()).digest()
    check_dsasig(dsasig)
    pub =  ec.tuple_from_point(pub)
    return ecdsa_verify_raw(m, dsasig, pub)


def ecdsa_verify_raw(m, dsasig, pub):
    h = int_from_hash(m, ec.order)
    r, s = dsasig
    s1 = mod_inv(s, ec.order)
    # by choice at this level do not manage point at infinity (h = 0, R = 0G)
    R = ec.pointAdd(ec.pointMultiply(r * s1 % ec.order, pub),
                    ec.pointMultiply(h * s1 % ec.order))
    return R[0] % ec.order == r


def ecdsa_pubkey_recovery(m, dsasig, y_mod_2, hasher=sha256):
    if type(m) == str: m = hasher(m.encode()).digest()
    check_dsasig(dsasig)
    assert y_mod_2 in (0, 1)
    return ecdsa_pubkey_recovery_raw(m, dsasig, y_mod_2)


def ecdsa_pubkey_recovery_raw(m, dsasig, y_mod_2):
    h = int_from_hash(m, ec.order)
    r, s = dsasig
    r1 = mod_inv(r, ec.order)
    R = (r, ec.y(r, y_mod_2))
    # by choice at this level do not manage point at infinity (h = 0, R = 0G)
    return ec.pointAdd(ec.pointMultiply(s * r1 % ec.order, R),
                       ec.pointMultiply(-h * r1 % ec.order))


def check_dsasig(dsasig):
    """check sig has correct dsa format
    """
    assert type(dsasig) == tuple and \
          len(dsasig) == 2 and \
          type(dsasig[0]) == int and type(dsasig[1]) == int, \
          "dsasig must be a tuple of 2 int"
    assert 0 < dsasig[0] and dsasig[0] < ec.order and \
           0 < dsasig[1] and dsasig[1] < ec.order, "r and s must be in [1..order]"

import unittest

class TestEcdsa(unittest.TestCase):
    def test_ecdsa(self):
{'fraction_non_alphanumeric': 0.1247016706443914, 'fraction_numerical': 0.024463007159904536, 'mean_word_length': 3.0886178861788616, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6028759', 'n_tokens_mistral': 2136, 'n_tokens_neox': 2038, 'n_words': 533}