I have a Python backend that generates public/private keys, generates a payload, then needs to get that payload signed by the client (ReactJS or pure JS), which is later verified.
The implementation in Python looks like this:
Imports
import json
import uuid
from backend.config import STARTING_BALANCE
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import (
encode_dss_signature,
decode_dss_signature
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.serialization import load_pem_private_key
import base64
import hashlib
Generate keys:
class User:
def __init__(self):
self.address = hashlib.sha1(str(str(uuid.uuid4())[0:8]).encode("UTF-8")).hexdigest()
self.private_key = ec.generate_private_key(
ec.SECP256K1(),
default_backend()
)
self.private_key_return = self.private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
self.public_key = self.private_key.public_key()
self.serialize_public_key()
def serialize_public_key():
"""
Reset the public key to its serialized version.
"""
self.public_key = self.public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
).decode('utf-8')
Sign:
def sign(self, data):
"""
Generate a signature based on the data using the local private key.
"""
return decode_dss_signature(self.private_key.sign(
json.dumps(data).encode('utf-8'),
ec.ECDSA(hashes.SHA256())
))
Verify:
@staticmethod
def verify(public_key, data, signature):
"""
Verify a signature based on the original public key and data.
"""
deserialized_public_key = serialization.load_pem_public_key(
public_key.encode('utf-8'),
default_backend()
)
(r, s) = signature
try:
deserialized_public_key.verify(
encode_dss_signature(r, s),
json.dumps(data).encode('utf-8'),
ec.ECDSA(hashes.SHA256())
)
return True
except InvalidSignature:
return False
What I need now is to load (or even generate) the PEM keys on the client-side, then upon request, sign a JSON payload that can later be verified from the Python backend.
I tried looking into the usage of web cryptography and cryptoJS but had no luck.
I'm okay using another algorithm that is more compatible, but at the very least I need the signing functionality fully working.
I also tried compiling Python to JS using Brython and Pyodide but both could not support all the required packages.
In simple terms, I am looking for the following:
Generate Payload (Python) -----> Sign Payload (JS) -----> Verify Signature (Python)
Any help/advice would be greatly appreciated.