Ethereum: Key generation signatures

TLDR: When sending responses containing validator metadata, Kiln includes a cryptographic signature allowing you to confirm that the validator public key originates from Kiln’s secure provisioning infrastructure.


Our POST /v1/eth/keys endpoint returns validator data, including the following fields:pubkeysignatureamountdeposit_data_rootwithdrawal_credentialskiln_signature.

The signature ensures the validator data is valid

signature is a cryptographic "proof of possession". It signs over pubkeywithdrawal_credentials, and amount by the validator's private key to prove the data supplied in a funding transaction matches the data that was used to create the validator being funded. Lines 132-144 of the Beacon Deposit Contract verify this data against the supplied deposit_data_root and will revert the transaction if unsuccessful.

Purpose of Lines 132–144

When a user deposits ETH to become a validator, they submit a deposit_data object containing:

  • pubkey: The validator's public key
  • withdrawal_credentials: Information for future fund withdrawals
  • amount: The amount of ETH being staked
  • signature: A cryptographic signature proving ownership of the pubkey

These fields are hashed together to form a deposit_data_root, which is then included in the deposit transaction.

Lines 132–144 verify that the provided deposit_data_root matches the hash of the submitted deposit_data. If there's a mismatch, the transaction is reverted. This ensures that only valid and authenticated validator data is accepted, maintaining the security and integrity of the Beacon Chain.

❗️

Warning!

The signature could be valid but the data returned could be the result of a man-in-the-middle attack on the endpoint such that the validator data and signature returned correspond to validators not created by Kiln. Depositing to such a validator would mean potential missed rewards or slashing by the malicious actor.

The kiln_signature ensures it was generated by Kiln

In addition, Kiln provides kiln_signature, a verifiable signature of the validator's pubkey by a private GPG key held within Kiln’s infra, so you know the validator returned by our API is from Kiln.

To get this field, one must use the kiln_signature parameter in the query’s body.

Here's how you can use this signature to verify the validator authenticity:

Copy Kiln’s public key and save as a plain text file named signing-pubkey.pem.

  1. Hoodi
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEaSCITBYJKwYBBAHaRw8BAQdATuE9FdTavn2yLEiw1kLeLHKn0Rb0H49qtDS8
fR6lLaG0NEV0aGVyZXVtIEtleWdlbiB0ZXN0bmV0IDxldGgta2V5Z2VuLXRlc3Ru
ZXRAa2lsbi5maT6IkwQTFgoAOxYhBDk9rxVWXz2Sifc1YRUtRPn5IhmVBQJpIIhM
AhsDBQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAAAoJEBUtRPn5IhmVwk8A/A5P
v65nC4xlBstx4nWzO12GAvS+6AEUc2Xv1ekypr25AQD9Md9/rYIGYvkz8DYE1KWZ
UE9xDjvULmNcqMSlwDjtA7g4BGkgiEwSCisGAQQBl1UBBQEBB0D4ZwAxhqRdpGKT
LsybogHdBIL8hnjqloXpJ8KTgdiIbQMBCAeIeAQYFgoAIBYhBDk9rxVWXz2Sifc1
YRUtRPn5IhmVBQJpIIhMAhsMAAoJEBUtRPn5IhmVm50BAPyjQOYK6WFdW8KQSlcD
XgA85uKoKEHC3CvuH7zyrFYjAQD3Rje98y4wgbag/Yv048VQZKaF+P/G8DqwIUba
jrQ3Dg==
=52Hf
-----END PGP PUBLIC KEY BLOCK----
  1. Mainnet
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEaSCHtxYJKwYBBAHaRw8BAQdA7rDNfjNbVUXUPX8MPDLJpysWmquw4cxjwHvP
1P5TFA60JEV0aGVyZXVtIEtleWdlbiA8ZXRoLWtleWdlbkBraWxuLmZpPoiTBBMW
CgA7FiEEgJLkPHB0TA8dggCSj65w/bg1LXwFAmkgh7cCGwMFCwkIBwICIgIGFQoJ
CAsCBBYCAwECHgcCF4AACgkQj65w/bg1LXxFJwD/YWy+Pc5QKqi7fadyjLD71Sn1
2tAkqkFsMeudf7afpIUA/0lkL2AvfudtH0hMYfbyOq2f6ufV1JKpIIz80JyOVGMF
uDgEaSCHtxIKKwYBBAGXVQEFAQEHQBg6080td4XTpvQrQDmaabvK8atRGcVeFqge
o116lXpAAwEIB4h4BBgWCgAgFiEEgJLkPHB0TA8dggCSj65w/bg1LXwFAmkgh7cC
GwwACgkQj65w/bg1LXx3vgEAiATkj1gZpI2ESW1nakpvyXv/gy+2+uv7BHmWI+zK
YskBAMPoqvs6HmQRpRg57CptEDh1DW6NK9crTg4j5ECMWZYC
=oChV
-----END PGP PUBLIC KEY BLOCK-----

e.g.

echo '-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEaSCHtxYJKwYBBAHaRw8BAQdA7rDNfjNbVUXUPX8MPDLJpysWmquw4cxjwHvP
1P5TFA60JEV0aGVyZXVtIEtleWdlbiA8ZXRoLWtleWdlbkBraWxuLmZpPoiTBBMW
CgA7FiEEgJLkPHB0TA8dggCSj65w/bg1LXwFAmkgh7cCGwMFCwkIBwICIgIGFQoJ
CAsCBBYCAwECHgcCF4AACgkQj65w/bg1LXxFJwD/YWy+Pc5QKqi7fadyjLD71Sn1
2tAkqkFsMeudf7afpIUA/0lkL2AvfudtH0hMYfbyOq2f6ufV1JKpIIz80JyOVGMF
uDgEaSCHtxIKKwYBBAGXVQEFAQEHQBg6080td4XTpvQrQDmaabvK8atRGcVeFqge
o116lXpAAwEIB4h4BBgWCgAgFiEEgJLkPHB0TA8dggCSj65w/bg1LXwFAmkgh7cC
GwwACgkQj65w/bg1LXx3vgEAiATkj1gZpI2ESW1nakpvyXv/gy+2+uv7BHmWI+zK
YskBAMPoqvs6HmQRpRg57CptEDh1DW6NK9crTg4j5ECMWZYC
=oChV
-----END PGP PUBLIC KEY BLOCK-----' > signing-pubkey.pem
  1. Grab the pubkey from the response of POST /v1/eth/keys, remove 0x, and store it in a file named pubkey.txt:

    echo -n "8baf2048d74713be4f72d758648ecaaa78e0fe81fec8d080180df18f0d7fe2e0475aac4761a8a1550a59cb9606acf2fc" > pubkey.txt
  2. Grab the kiln_signature from the response, remove 0x, and store the binary format in a file named signature.bin:

    echo "c2ab04001608005d058269370fa30910152d44f9f9221995351400000000001c001073616c74406e6f746174696f6e732e6f70656e7067706a732e6f72672331bfd9723edbad06fce2c2180dc6f0162104393daf15565f3d9289f73561152d44f9f922199500001f2800ff705bc03cbf9c810bbcc89a0290597e2384e68aa64cbf750eb40310d3de970c410100ee43706cbf434ca9465f3c983646567430edd90ef16b15be637694eae8cdc10d" | xxd -r -p > signature.bin
  3. Verify the signature using OpenGPG:

    gpg --import signing-pubkey.pem
    gpg --verify signature.bin pubkey.txt
  4. Verify that the decoded signature matches the message. The command above should say that the signature is valid