SubtleCrypto and ECDSA

The Web Crypto API (the full name for window.crypto.subtle) is a W3C standard that has been built into browsers for years precisely because cryptography needs to be consistent and native across the web. Developers kept building their own crypto libraries in pure JavaScript before this (often with bugs or side-channel leaks), so the browsers agreed on one low-level API everyone implements. P-256 (also called secp256r1 or prime256v1) is one of only three elliptic curves officially required by the spec — the others are P-384 and P-521 — so every browser that supports ECDSA at all must support P-256. You can rely on it the same way you rely on fetch() or JSON.parse(): it’s there, it’s fast (uses hardware acceleration where possible), and it’s secure by design because the private key never leaves the browser’s secure context. That’s why we can use it in your Aliro playground without any libraries or polyfills — open the HTML file and it just works.

https://crypto.stackexchange.com/questions/73069/how-does-ecdsa-signature-verify-work-in-eos-and-eth-btc-compare-to-standard-on

Copyright STMicroselectronics

from ecdsa import SigningKey, VerifyingKey, NIST256p
from ecdsa.util import sigencode_der, sigdecode_der
from cryptography.hazmat.primitives import hashes, hmac
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os, binascii

# Generate ephemerals (asymm)
reader_priv = ec.generate_private_key(ec.SECP256R1())
reader_pub = reader_priv.public_key().public_bytes(encoding=ec.Encoding.X962, format=ec.PublicFormat.UncompressedPoint)
device_priv = ec.generate_private_key(ec.SECP256R1())
device_pub = device_priv.public_key().public_bytes(encoding=ec.Encoding.X962, format=ec.PublicFormat.UncompressedPoint)

# Fake T (transaction data concat)
T = reader_pub + device_pub + os.urandom(8) + os.urandom(32) + b'fakeFCI'  # In real: from APDUs
hash_T = hashes.Hash(hashes.SHA256()).update(T).finalize()

# Reader signs (asymm ECDSA)
reader_long_priv = SigningKey.generate(curve=NIST256p)
reader_sig = reader_long_priv.sign(hash_T, hashfunc=hashes.SHA256, sigencode=sigencode_der)

# Device verifies, derives Z/SK (asymm ECDH to symm HKDF)
reader_long_pub = reader_long_priv.verifying_key
if reader_long_pub.verify(reader_sig, hash_T, hashfunc=hashes.SHA256, sigdecode=sigdecode_der):
    Z = device_priv.exchange(ec.ECDH(), reader_priv.public_key())
    hkdf = HKDF(algorithm=hashes.SHA256(), length=32, salt=None, info=b'AliroSecureChannel')
    SK = hkdf.derive(Z)
    print("Derived SK (symm key):", binascii.hexlify(SK).decode())

    # Device response payload (TLV), encrypt with symm AES-GCM
    payload = b'\x9E' + len(reader_sig).to_bytes(1, 'big') + reader_sig  # Fake minimal: just sig
    nonce = hash_T[:12]
    aes = AESGCM(SK)
    encrypted = aes.encrypt(nonce, payload, b'AliroAuth1')
    print("Encrypted response (over NFC):", binascii.hexlify(encrypted).decode())
else:
    print("Sig verify failed")

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *