Beispiel #1
0
def test_int_from_integer():
    i = secrets.randbits(256 - 8)
    assert i == int_from_integer(i)
    assert i == int_from_integer(hex(i).upper())
    assert i == int_from_integer(bin(i).upper())
    assert i == int_from_integer(hex_string(i))
    assert i == int_from_integer(i.to_bytes(32, "big"))
Beispiel #2
0
def test_int_from_integer() -> None:
    for i in (
        secrets.randbits(256 - 8),
        0x0B6CA75B7D3076C561958CCED813797F6D2275C7F42F3856D007D587769A90,
    ):
        assert i == int_from_integer(i)
        assert i == int_from_integer(" " + hex(i).upper())
        assert -i == int_from_integer(hex(-i).upper() + " ")
        assert i == int_from_integer(hex_string(i))
        assert i == int_from_integer(i.to_bytes(32, "big"))
Beispiel #3
0
    def test_utils(self):
        b = bytes_from_octets(int_with_whitespaces)
        s = b.hex()  # lower case, no spaces
        self.assertNotEqual(int_with_whitespaces, s)
        self.assertEqual(hash160(int_with_whitespaces), hash160(s))
        self.assertEqual(hash256(int_with_whitespaces), hash256(s))

        i = secrets.randbits(256)
        self.assertEqual(i, int_from_integer(i))
        self.assertEqual(i, int_from_integer(i.to_bytes(32, "big")))
        self.assertEqual(i, int_from_integer(hex(i)))
Beispiel #4
0
    def __init__(self, p: Integer, a: Integer, b: Integer, G: Point) -> None:

        super().__init__(p, a, b)

        # 2. check that xG and yG are integers in the interval [0, p−1]
        # 4. Check that yG^2 = xG^3 + a*xG + b (mod p)
        if len(G) != 2:
            raise BTClibValueError("Generator must a be a sequence[int, int]")
        self.G = (int_from_integer(G[0]), int_from_integer(G[1]))
        if not self.is_on_curve(self.G):
            raise BTClibValueError("Generator is not on the curve")
        self.GJ = self.G[0], self.G[1], 1  # Jacobian coordinates
Beispiel #5
0
def multi_mult(scalars: Sequence[Integer],
               points: Sequence[Point],
               ec: Curve = secp256k1) -> Point:
    """Return the multi scalar multiplication u1*Q1 + ... + un*Qn.

    Use Bos-Coster's algorithm for efficient computation.
    """

    if len(scalars) != len(points):
        err_msg = "mismatch between number of scalars and points: "
        err_msg += f"{len(scalars)} vs {len(points)}"
        raise BTClibValueError(err_msg)

    jac_points: List[JacPoint] = []
    ints: List[int] = []
    for Q, i in zip(points, scalars):
        i = int_from_integer(i) % ec.n
        if i == 0:  # early optimization, even if not strictly necessary
            continue
        ints.append(i)
        ec.require_on_curve(Q)
        jac_points.append(jac_from_aff(Q))

    R = _multi_mult(ints, jac_points, ec)
    return ec.aff_from_jac(R)
Beispiel #6
0
def double_mult(u: Integer,
                H: Point,
                v: Integer,
                Q: Point,
                ec: Curve = secp256k1) -> Point:
    "Double scalar multiplication (u*H + v*Q)."

    ec.require_on_curve(H)
    HJ = jac_from_aff(H)

    ec.require_on_curve(Q)
    QJ = jac_from_aff(Q)

    u = int_from_integer(u) % ec.n
    v = int_from_integer(v) % ec.n
    R = _double_mult(u, HJ, v, QJ, ec)
    return ec.aff_from_jac(R)
Beispiel #7
0
    def __init__(self, p: Integer, a: Integer, b: Integer) -> None:
        # Parameters are checked according to SEC 1 v.2 3.1.1.2.1

        p = int_from_integer(p)
        a = int_from_integer(a)
        b = int_from_integer(b)

        # 1) check that p is a prime
        # Fermat test will do as _probabilistic_ primality test...
        if p < 2 or p % 2 == 0 or pow(2, p - 1, p) != 1:
            err_msg = "p is not prime: "
            err_msg += f"'{hex_string(p)}'" if p > HEX_THRESHOLD else f"{p}"
            raise BTClibValueError(err_msg)

        plen = p.bit_length()
        # byte-length
        self.p_size = ceil(plen / 8)
        # must be true to break simmetry using quadratic residue
        self.p_is_3_mod_4 = p % 4 == 3
        self.p = p

        # 2. check that a and b are integers in the interval [0, p−1]
        if a < 0:
            raise BTClibValueError(f"negative a: {a}")
        if p <= a:
            err_msg = "p <= a: " + (f"'{hex_string(p)}' <= '{hex_string(a)}'"
                                    if p > HEX_THRESHOLD else f"{p} <= {a}")
            raise BTClibValueError(err_msg)
        if b < 0:
            raise BTClibValueError(f"negative b: {b}")
        if p <= b:
            err_msg = "p <= b: " + (f"'{hex_string(p)}' <= '{hex_string(b)}'"
                                    if p > HEX_THRESHOLD else f"{p} <= {b}")
            raise BTClibValueError(err_msg)

        # 3. Check that 4*a^3 + 27*b^2 ≠ 0 (mod p)
        d = 4 * a * a * a + 27 * b * b
        if d % p == 0:
            raise BTClibValueError("zero discriminant")
        self._a = a
        self._b = b
Beispiel #8
0
def mult(m: Integer,
         Q: Optional[Point] = None,
         ec: Curve = secp256k1) -> Point:
    "Elliptic curve scalar multiplication."
    if Q is None:
        QJ = ec.GJ
    else:
        ec.require_on_curve(Q)
        QJ = jac_from_aff(Q)

    m = int_from_integer(m) % ec.n
    R = _mult(m, QJ, ec)
    return ec.aff_from_jac(R)
Beispiel #9
0
    def __init__(
        self,
        p: Integer,
        a: Integer,
        b: Integer,
        G: Point,
        n: Integer,
        cofactor: int,
        weakness_check: bool = True,
        name: Optional[str] = None,
    ) -> None:

        super().__init__(p, a, b, G)
        n = int_from_integer(n)

        # Security level is expressed in bits, where n-bit security
        # means that the attacker would have to perform 2^n operations
        # to break it. Security bits are half the key size for asymmetric
        # elliptic curve cryptography, i.e. half of the number of bits
        # required to express the group order n or, holding Hasse theorem,
        # to express the field prime p

        self.n = n
        self.nlen = n.bit_length()
        self.n_size = (self.nlen + 7) // 8

        # 5. Check that n is prime.
        if n < 2 or n % 2 == 0 or pow(2, n - 1, n) != 1:
            err_msg = "n is not prime: "
            err_msg += f"{hex_string(n)}" if n > HEX_THRESHOLD else f"{n}"
            raise BTClibValueError(err_msg)
        delta = int(2 * sqrt(self.p))
        # also check n with Hasse Theorem
        if cofactor < 2 and not self.p + 1 - delta <= n <= self.p + 1 + delta:
            err_msg = "n not in p+1-delta..p+1+delta: "
            err_msg += f"{hex_string(n)}" if n > HEX_THRESHOLD else f"{n}"
            raise BTClibValueError(err_msg)

        # 7. Check that G ≠ INF, nG = INF
        if self.G[1] == 0:
            err_msg = "INF point cannot be a generator"
            raise BTClibValueError(err_msg)
        jac_inf = _mult(n, self.GJ, self)
        if jac_inf[2] != 0:
            err_msg = "n is not the group order: "
            err_msg += f"{hex_string(n)}" if n > HEX_THRESHOLD else f"{n}"
            raise BTClibValueError(err_msg)

        # 6. Check cofactor
        exp_cofactor = int(1 / n + delta / n + self.p / n)
        if cofactor != exp_cofactor:
            err_msg = f"invalid cofactor: {cofactor}, expected {exp_cofactor}"
            raise BTClibValueError(err_msg)
        self.cofactor = cofactor

        # 8. Check that n ≠ p
        if n == p:
            raise BTClibValueError(
                f"n=p weak curve: {hex_string(n)}")  # pragma: no cover

        if weakness_check:
            # 8. Check that p^i % n ≠ 1 for all 1≤i<100
            for i in range(1, 100):
                if pow(self.p, i, n) == 1:
                    raise UserWarning("weak curve")

        self.name = name