# Stark signatures

Payloads to stark signing are a result of a Pedersen hash.

Depending on your implementation of the Pedersen hash, the result of this hash might be an integer, or encoded in 32-byte representation, according to [Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)](https://www.rfc-editor.org/rfc/rfc6979#section-2.3.2).

Fordefi supports these formats:

- `hash_integer`: This is the integer representation, encoded as a hex string, starting with 0x and followed by an even number of hex-digits.
- `hash_binary`: This is the 32-byte encoded format.


Once the payload is signed, under the `details` field in the `Get Transaction` response, the `signature` object will hold the R- and S-values of the signature.

### Example

This example demonstrates how to use the new stark vault for creating and signing stark signatures.


```python
import requests
import base64
import json
import datetime
import ecdsa
import hashlib

# https://github.com/starkware-libs/cairo-lang
from starkware.crypto.signature.signature import verify, pedersen_hash

# Obtain the hash of the transaction
payload_int = pedersen_hash(0xdeadbeaf)

# Build the signature request
request_json = {
    "vault_id": vault_id,
    "note":" string",
    "signer_type": "api_signer",
    "type": "black_box_signature",
    "details": {
        "format": "hash_integer",
        "hash_integer": "0x{:064x}".format(payload_int),
    },
}

# Alternatively, you can use the binary hash
# this is useful if pedersen_hash implementation you are using returns bytes according to https://www.rfc-editor.org/rfc/rfc6979#section-2.3.2
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 = str(int(datetime.datetime.now(datetime.timezone.utc).timestamp()))
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()

r = int(signed_transaction["details"]["signature"]["r"], 16)
s = int(signed_transaction["details"]["signature"]["s"], 16)

# 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()

stark_key = int(vault["details"]["stark_key"], 16)

# Verify the signature
assert verify(payload_int, r, s, stark_key)

# You can also use the public key in the compressed format
compressed_public_key = base64.b64decode(vault["public_key_compressed"])

# This is the relation between the compressed public key and the stark key
assert int.from_bytes(compressed_public_key[1:], byteorder="big") == stark_key
```

##