I'm trying to achieve the exact opposite of this here where I need to sign a payload in Python using ECDSA and be able to verify the signature in JS.
Here is my attempt, but I'm pretty sure I'm missing something with data transformation on either or both ends.
(Key types are the same as in the answer provided to the question above)
I've tried some other variations but nothing worked so far.
(The verification on JS returns False)
Python:
import os
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.serialization import load_der_public_key, load_pem_private_key, load_der_private_key
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives import hashes
from cryptography.exceptions import InvalidSignature
import base64
import json
from hashlib import sha256
def order_dict(dictionary):
return {k: order_dict(v) if isinstance(v, dict) else v
for k, v in sorted(dictionary.items())}
async def sign_payload(private_key, data):
"""
Generate a signature based on the data using the local private key.
"""
data = order_dict(data)
# Separators prevent adding whitespaces around commas and :
payload = json.dumps(data, separators=(',', ':')).encode('utf-8')
# payload = base64.b64decode(json.dumps(data, separators=(',', ':')))
sig = private_key.sign(
payload,
ec.ECDSA(hashes.SHA256())
)
return sig
JS:
export function b642ab(base64_string){
return Uint8Array.from(window.atob(base64_string), c => c.charCodeAt(0));
}
export async function verifySignature(signature, public_key, data_in) {
// Sorting alphabetically to avoid signature mismatch with BE
const sorted_data_in = sortObjKeysAlphabetically(data_in);
var dataStr = JSON.stringify(sorted_data_in)
console.log(dataStr)
var dataBuf = new TextEncoder().encode(dataStr)
return window.crypto.subtle.verify(
{
name: "ECDSA",
namedCurve: "P-256",
hash: { name: "SHA-256" },
},
public_key,
b642ab(utf8.decode(signature)),
dataBuf
);
}
await sign_payload(private_dsa_key, generated_payload)