feat(tools): add ECDSA P-256 firmware signing tool

This commit is contained in:
2026-05-11 06:49:15 -07:00
parent 437f73739f
commit 031426e364
2 changed files with 104 additions and 0 deletions

41
tools/sign_firmware.py Normal file
View File

@@ -0,0 +1,41 @@
#!/usr/bin/env python3
"""Sign a firmware binary with ECDSA P-256. Outputs a raw 64-byte r||s .sig file."""
import argparse
from pathlib import Path
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
def load_private_key(key_path: Path) -> ec.EllipticCurvePrivateKey:
return serialization.load_pem_private_key(key_path.read_bytes(), password=None)
def sign_firmware(firmware_path: Path, key_path: Path) -> bytes:
key = load_private_key(key_path)
data = firmware_path.read_bytes()
sig_der = key.sign(data, ec.ECDSA(hashes.SHA256()))
r, s = decode_dss_signature(sig_der)
return r.to_bytes(32, 'big') + s.to_bytes(32, 'big')
def main() -> None:
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("firmware", help="Path to firmware .bin")
p.add_argument("--key", default="secrets/firmware_signing_key.pem",
help="Path to PEM private key")
p.add_argument("--out", help="Output .sig path (default: firmware.bin.sig)")
args = p.parse_args()
firmware = Path(args.firmware)
key_path = Path(args.key)
out_path = Path(args.out) if args.out else firmware.with_suffix(".bin.sig")
sig = sign_firmware(firmware, key_path)
out_path.write_bytes(sig)
print(f"Signed {firmware.name}{out_path} ({len(sig)} bytes)")
if __name__ == "__main__":
main()