Files
attack-defense-platform/receiver/modules/blinkpdf/decdsa.py
T
2025-10-10 22:18:06 +07:00

104 lines
3.8 KiB
Python

import hashlib
import random
from ecdsa import NIST256p, ellipticcurve
class DECDSA:
def __init__(self, privateKey):
self.curve = NIST256p
self.order = self.curve.order
self.generator = self.curve.generator
self.private_key = int(privateKey, 16) % self.order
self.public_key = self.private_key * self.generator
# self.generate_keypair()
# def generate_keypair(self):
# test
# self.private_key = 68643326375728294502573326707893599968874260096336631364679496614035223206444
# self.private_key = random.randint(1, self.order - 1)
# self.public_key = self.private_key * self.generator
def lift_x(self, x):
p = self.curve.curve._CurveFp__p
a = self.curve.curve._CurveFp__a
b = self.curve.curve._CurveFp__b
y_squared = (x**3 + a*x + b) % p
y = pow(y_squared, (p + 1) // 4, p)
if (y * y) % p != y_squared:
raise ValueError(f"No valid point found for x={x}")
point1 = ellipticcurve.Point(self.curve.curve, x, y)
point2 = ellipticcurve.Point(self.curve.curve, x, p - y)
if y > p - y:
return point2
else:
return point1
def sign(self, message):
m1, m2 = message[:len(message)//2], message[len(message)//2:]
h1 = hashlib.sha256(m1).digest()[1:]
h2 = hashlib.sha256(m2).digest()[1:]
z1 = int.from_bytes(h1, byteorder='big') % self.order
z2 = int.from_bytes(h2, byteorder='big') % self.order
while True:
k1 = random.randint(z1, z1*4)
k2 = random.randint(z2, z2*4)
R1 = k1 * self.generator
R2 = k2 * self.generator
r1 = R1.x() % self.order
r2 = R2.x() % self.order
R_att_x = (self.lift_x(r1) + self.lift_x(r2)).x() % self.order
# assert for checking valid points
if(R_att_x!=(R1+R2).x() % self.order):
continue
if r1 == 0 or r2 == 0:
continue
ks = pow(k1, -1, self.order) + pow(k2, -1, self.order)
s = (pow(k1*k2, -1, self.order) * (z1 + r1 * self.private_key + z2 + r2 * self.private_key) * pow(ks, -1, self.order)) % self.order
if s == 0:
continue
r1, r2, s = int(r1), int(r2), int(s)
return self.sign_to_bytes(r1, r2, s)
def verify(self, message, signature):
r1, r2, s = self.bytes_to_sign(signature)
if not (1 <= r1 < self.order and 1 <= r2 < self.order and 1 <= s < self.order):
return False
m1, m2 = message[:len(message)//2], message[len(message)//2:]
h1 = hashlib.sha256(m1).digest()[1:]
h2 = hashlib.sha256(m2).digest()[1:]
z1 = int.from_bytes(h1, byteorder='big') % self.order
z2 = int.from_bytes(h2, byteorder='big') % self.order
s_inv = pow(s, -1, self.order)
u1 = (z1 * s_inv) % self.order
u2 = (z2 * s_inv) % self.order
u3 = (r1 * s_inv) % self.order
u4 = (r2 * s_inv) % self.order
R = u1 * self.generator + u3 * self.public_key + u2 * self.generator + u4 * self.public_key
R_x = R.x() % self.order
R_att_x = (self.lift_x(r1) + self.lift_x(r2)).x() % self.order
return R_x == R_att_x
def long_to_bytes(self, x):
return x.to_bytes(32, "big")
def bytes_to_long(self, x):
return int.from_bytes(x, "big")
def sign_to_bytes(self, r1, r2, s):
first_part = self.long_to_bytes(r1)
second_part = self.long_to_bytes(r2)
third_part = self.long_to_bytes(s)
return first_part + second_part + third_part
def bytes_to_sign(self, x):
r1 = self.bytes_to_long(x[:32])
r2 = self.bytes_to_long(x[32:64])
s = self.bytes_to_long(x[64:])
return r1, r2, s