bambi7-service-fireworx

ESDSA-signed firework A/D service for BambiCTF7 in 2022
git clone https://git.sinitax.com/sinitax/bambi7-service-fireworx
Log | Files | Refs | README | LICENSE | sfeed.txt

crypto.py (2322B)


      1#!/usr/bin/env python3
      2
      3import random
      4from hashlib import sha256
      5
      6from Crypto.Util import number
      7from Crypto.Util.number import bytes_to_long, getPrime, inverse, long_to_bytes
      8from gmpy2 import is_prime
      9
     10L = 1024
     11N = 160
     12
     13def H(x):
     14    if type(x) == int:
     15        x = long_to_bytes(x)
     16    return bytes_to_long(sha256(x).digest())
     17
     18
     19class DSAKey:
     20    def __init__(self, p, q, g, x, y):
     21        self.p = p
     22        self.q = q
     23        self.g = g
     24        self.x = x
     25        self.y = y
     26
     27    def vals(self):
     28        return (self.p, self.q, self.g, self.x, self.y)
     29
     30    def dict(self):
     31        return {
     32            "p": self.p,
     33            "q": self.q,
     34            "g": self.g,
     35            "x": self.x,
     36            "y": self.y
     37        }
     38
     39    def gen(L=L, N=N):
     40        q = getPrime(N)
     41        low = (1 << (L-1)) // q + 1
     42        up = (1 << L) // q
     43        while True:
     44            factor = number.getRandomRange(low, up + 1)
     45            p = factor * q + 1
     46            if is_prime(p): break
     47        while True:
     48            g = pow(number.getRandomRange(2, p), factor, p)
     49            if g != 1:
     50                break
     51        x = random.randint(1, q - 1)
     52        y = pow(g, x, p)
     53        return DSAKey(p, q, g, x, y)
     54
     55    def pubkey(self):
     56        return DSAPubKey(self.p, self.q, self.g, self.y)
     57
     58    def sign(self, msg):
     59        k = H(self.y)
     60        r = pow(self.g, k, self.p) % self.q
     61        s = inverse(k, self.q) * (H(msg) + r * self.x) % self.q
     62        return r, s
     63
     64
     65class DSAPubKey:
     66    def __init__(self, p, q, g, y):
     67        self.p = p
     68        self.q = q
     69        self.g = g
     70        self.y = y
     71
     72    def vals(self):
     73        return (self.p, self.q, self.g, self.y)
     74
     75    def dict(self):
     76        return {
     77            "p": self.p,
     78            "q": self.q,
     79            "g": self.g,
     80            "y": self.y
     81        }
     82
     83    def verify(self, msg, signature):
     84        r, s = signature
     85        w = inverse(s, self.q)
     86        u1 = H(msg) * w % self.q
     87        u2 = r * w % self.q
     88        v = (pow(self.g, u1, self.p) * pow(self.y, u2, self.p) % self.p) % self.q
     89        return v == r
     90
     91def gen_challenge():
     92    return bytes_to_long(random.randbytes(16))
     93
     94if __name__ == "__main__":
     95    msg = b"flag{test}"
     96
     97    privkey = DSAKey.gen()
     98    signature = privkey.sign(msg)
     99
    100    pubkey = privkey.pubkey()
    101    assert pubkey.verify(msg, signature)