Initial commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
from .signature import *
|
||||
from .cipher import *
|
||||
@@ -0,0 +1,43 @@
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import pad, unpad
|
||||
from Crypto.Util.number import long_to_bytes, bytes_to_long
|
||||
import hashlib
|
||||
import random
|
||||
import os
|
||||
|
||||
# This will be the base dont change it
|
||||
q = 135589091449528481388008471290289910812753186702167314685052586130282290721619
|
||||
p = 271178182899056962776016942580579821625506373404334629370105172260564581443239
|
||||
g = pow(2, (p-1)//p, p)
|
||||
|
||||
def encryptMessage(message, PRIVATE_KEY):
|
||||
key = hashlib.sha256(bytes.fromhex(PRIVATE_KEY)).digest()[:16]
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv=os.urandom(16))
|
||||
ciphertext = cipher.iv + cipher.encrypt(pad(message,16))
|
||||
digest_message = int(hashlib.sha256(message).hexdigest(), 16)
|
||||
x = int(PRIVATE_KEY, 16)
|
||||
rand = random.Random()
|
||||
rand.seed(bytes_to_long(message))
|
||||
k = rand.getrandbits(216)
|
||||
r = pow(g, k, p) % q
|
||||
s = (pow(k, -1, q) * (digest_message + r * x)) % q
|
||||
y = pow(g, x, q)
|
||||
signature = long_to_bytes(y).zfill(32).hex() + long_to_bytes(digest_message).zfill(32).hex() + long_to_bytes(r).zfill(32).hex() + long_to_bytes(s).zfill(32).hex()
|
||||
return ciphertext.hex() + signature
|
||||
|
||||
def decryptMessage(ciphertext, PRIVATE_KEY):
|
||||
cps = bytes.fromhex(ciphertext)
|
||||
y = bytes_to_long(cps[-128:-96].lstrip(b'0'))
|
||||
dig = bytes_to_long(cps[-96:-64].lstrip(b'0'))
|
||||
r = bytes_to_long(cps[-64:-32].lstrip(b'0'))
|
||||
s = bytes_to_long(cps[-32:].lstrip(b'0'))
|
||||
u = pow(s, -1, q)
|
||||
v = pow(g, (dig * u) % q, p) * pow(y, (r * u)%q, p) % p % q
|
||||
ciphertext = cps[:-128]
|
||||
iv = ciphertext[:16]
|
||||
ct = ciphertext[16:]
|
||||
key = hashlib.sha256(bytes.fromhex(PRIVATE_KEY)).digest()[:16]
|
||||
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
|
||||
plaintext = cipher.decrypt(ct)
|
||||
plain = unpad(plaintext, 16)
|
||||
return v == r, plain
|
||||
@@ -0,0 +1,104 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
from .decdsa import DECDSA
|
||||
import PyPDF2
|
||||
import io
|
||||
|
||||
def sign_pdf(file, PRIVATE_KEY):
|
||||
try:
|
||||
decdsa = DECDSA(privateKey=PRIVATE_KEY)
|
||||
pdf_reader = PyPDF2.PdfReader(file)
|
||||
pdf_writer = PyPDF2.PdfWriter()
|
||||
for page in pdf_reader.pages:
|
||||
pdf_writer.add_page(page)
|
||||
|
||||
pdf_data = io.BytesIO()
|
||||
pdf_writer.write(pdf_data)
|
||||
pdf_data.seek(0)
|
||||
pdf_content = pdf_data.read()
|
||||
signature = decdsa.sign(pdf_content)
|
||||
pdf_writer.add_metadata({'/Signature': signature.hex()})
|
||||
signed_pdf = io.BytesIO()
|
||||
pdf_writer.write(signed_pdf)
|
||||
signed_pdf.seek(0)
|
||||
return signed_pdf
|
||||
except:
|
||||
return False
|
||||
|
||||
def verify_signature(file, PRIVATE_KEY):
|
||||
try:
|
||||
decdsa = DECDSA(privateKey=PRIVATE_KEY)
|
||||
pdf_reader = PyPDF2.PdfReader(file)
|
||||
signature_text = pdf_reader.metadata.get('/Signature', '')
|
||||
signature = bytes.fromhex(signature_text)
|
||||
pdf_data = io.BytesIO()
|
||||
pdf_writer = PyPDF2.PdfWriter()
|
||||
for page in pdf_reader.pages:
|
||||
pdf_writer.add_page(page)
|
||||
|
||||
pdf_writer.write(pdf_data)
|
||||
pdf_data.seek(0)
|
||||
pdf_content = pdf_data.read()
|
||||
return decdsa.verify(pdf_content,signature)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
Reference in New Issue
Block a user