Skip to Content
📢 Breaking change: Applications using LedgerJS for transport implementation should migrate to the Device Management Kit (DMK). Learn more.

Card fund code examples

This page shows how to implement the payload-signing routine described in Payload & Signature. Each example signs a payload with your Card fund provider private key using ES256 over the secp256k1 curve, then base64Url-encodes the result to produce the signature field your response must include.

The three examples below are equivalent implementations in Java, Python, and TypeScript. Pick the one that matches your backend stack; the signing steps are the same in each case.

Each snippet expects a response protobuf message (or an already-encoded payload) and your provider’s private key. Replace the placeholder key path or value with the location of your own key.

Java

import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.security.*; import java.util.Base64; public class App { static { Security.addProvider(new BouncyCastleProvider()); } public static void main(String[] args) throws Exception { byte[] payloadBytes = response.toByteArray(); String payload = Base64.getUrlEncoder().withoutPadding().encodeToString(payloadBytes); PrivateKey key = getPrivateKeyFromPEMFile("<path to your private key>"); byte[] sign = signPayload(("." + payload).getBytes(), key); String signature = Base64.getUrlEncoder().withoutPadding().encodeToString(sign); } public static byte[] signPayload(byte[] payloadBytes, PrivateKey privateKey) throws Exception { Signature signer = Signature.getInstance("SHA256withPlain-ECDSA", "BC"); signer.initSign(privateKey); signer.update(payloadBytes); return signer.sign(); } }

Python

import base64 import os from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives import hashes from google.protobuf import message import sell_pb2 # Import the generated protobuf classes from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature def base64_url_encode(data): return base64.urlsafe_b64encode(data).rstrip(b'=').decode('utf-8') def sign_payload(payload, private_key): # Sign the payload using ECDSA with SHA-256 der_signature = private_key.sign( payload, ec.ECDSA(hashes.SHA256()) ) # Decode the DER-encoded signature to get r and s r, s = decode_dss_signature(der_signature) # Convert r and s to bytes r_bytes = r.to_bytes(32, byteorder='big') s_bytes = s.to_bytes(32, byteorder='big') return r_bytes + s_bytes if __name__ == "__main__": payload = response.SerializeToString() encoded_payload = base64_url_encode(payload) # Sign the payload signature = sign_payload(("." + encoded_payload).encode('utf-8'), private_key) # Base64 URL encode the signature encoded_signature = base64_url_encode(signature) provider_sig = { "payload": encoded_payload, "signature": encoded_signature }

typescript

const base64EncodedPayload = base64url.encode( Buffer.from(uInt8ArrayEncodedPayload), // this is encoded payload using protobuf ); function signProviderSignaturePayload(base64EncodedPayload: string): string { const ec = new EC('secp256k1'); const keyPair = ec.keyFromPrivate( <PRIVATE_KEY_GOES_HERE>, 'hex', ); const hashedMessage = crypto .createHash('sha256') .update(`.${base64EncodedPayload}`) .digest(); const signature = keyPair.sign(hashedMessage); const r = signature.r.toString('hex').padStart(64, '0'); const s = signature.s.toString('hex').padStart(64, '0'); const signatureBuffer = Buffer.from(r + s, 'hex'); const signatureBase64 = signatureBuffer.toString('base64url'); return signatureBase64; }

Cross-references

  • Backend: the endpoints that consume this signature, and the payload format it signs
  • API reference: full request and response schemas for the Card endpoints
Last updated on
Ledger
Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Stax, Ledger Flex, Ledger Nano, Ledger Nano S, Ledger OS, Ledger Wallet, [LEDGER] (logo), [L] (logo) are trademarks owned by Ledger SAS.