EdDSA signatures

Use black-box signatures to sign any EdDSA payload and enable support for chains that Fordefi does not yet support.

The following sample shows how to sign a transaction using an EdDSA vault. The request should be inside the body, as demonstrated here.

import base64
import datetime
import hashlib
import json

import ecdsa
import nacl.signing
import requests

payload_bytes = b"0" * 32
payload_encoded = base64.b64encode(payload_bytes).decode()

request_json = {
    "vault_id": vault_id,
    "note":" string",
    "signer_type": "api_signer",
    "type": "black_box_signature",
    "details": {
        "format": "hash_binary",
        "hash_binary": payload_encoded,
    },
}

request_body = json.dumps(request_json)
private_key_file = "private.pem"
timestamp = datetime.datetime.now().strftime("%s")
payload = f"/api/v1/transactions|{timestamp}|{request_body}"

with open(private_key_file, "r") as f:
    signing_key = ecdsa.SigningKey.from_pem(f.read())

signature = signing_key.sign(data=payload.encode(), hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_der)

resp_tx = requests.post(
    f"https://{gateway_host}/api/v1/transactions",
    headers={
        "Authorization": f"Bearer {access_token}",
        "x-signature": base64.b64encode(signature),
        "x-timestamp": timestamp.encode(),
    },
    data=request_body,
).json()

# Obtain the signature result
transaction_id = resp_tx["id"]
signed_transaction = requests.get(
    f"https://{gateway_host}/api/v1/transactions/{transaction_id}",
    headers={
        "Authorization": f"Bearer {access_token}",
    }
).json()

transaction_signature = base64.b64decode(signed_transaction["details"]["signature"])

# Obtain your vault's public key
vault = requests.get(
    f"https://{gateway_host}/api/v1/vaults/{vault_id}",
    headers={
        "Authorization": f"Bearer {access_token}",
    }
).json()

# Verify the signature
public_key_compressed = vault["public_key_compressed"]
public_key_compressed_decoded = base64.b64decode(public_key_compressed)
verifying_key = nacl.signing.VerifyKey(public_key_compressed_decoded)
verifying_key.verify(payload_bytes, transaction_signature)