These Open SSL examples can be used for key generation and signature in non-production environments.
OpenSSL is not suitable for production environments. You always need to generate and store production keys using a cryptographically secure method (a key management system).
The following examples show how to generate a key pair using the common OpenSSL toolbox.
To generate a key pair using the secp256r1 elliptic curve, enter the following commands:
openssl ecparam -genkey -name secp256r1 -noout -out privateKey.pemopenssl ec -in privateKey.pem -pubout -outform DER | openssl base64 -A -out publicKey.pemTo generate a key pair using the secp256k1 elliptic curve, enter the following commands:
openssl ecparam -genkey -name secp256k1 -noout -out privateKey.pemopenssl ec -in privateKey.pem -pubout -outform DER | openssl base64 -A -out publicKey.pemTo generate a key pair using the ED25519 elliptic curve, enter the following commands:
openssl genpkey -algorithm Ed25519 -out privateKey.pemopenssl ec -in privateKey.pem -pubout -outform DER | openssl base64 -A -out publicKey.pemIn the previous examples, the public key is exported without the header and footer, which is the format that Ripple Custody expects.
To view the contents of the key files:
To view the contents of the private key files, for each file, enter the following command:
View private keycat privateKey.pemThe output is similar to the following example:
Private key output-----BEGIN EC PRIVATE KEY----- MHcCAQEEIEfoycax3w8+JvkNv+L0CHmNUAHUcgCxlnOIpw/CoXzxoAoGCCqGSM49 AwEHoUQDQgAEg36xU2KQ6xLPCvZ3JXZYf5pFCagAb7WGMlYCN92zzgi737EOkDOC MlZB0TY8CbzRHhG4RUdKuLkdRtD+OVIu2w== -----END EC PRIVATE KEY-----To view the contents of the public key files, for each file, enter the following command:
View public keycat publicKey.pemThe output is similar to the following example:
Public key outputMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg36xU2KQ6xLPCvZ3JXZYf5pFCagAb7WGMlYCN92zzgi737EOkDOCMlZB0TY8CbzRHhG4RUdKuLkdRtD+OVIu2w==
The following examples show how to:
- Sign a challenge to obtain a JSON web token (JWT)
- Submit an intent
This example shows how to sign a challenge. These steps generate the output that you need to obtain a JWT for authentication in Ripple Custody.
For more information about JWT generation, see Obtain a JSON web token (JWT) in the API guide.
To generate the signature:
Prepare a random string to use as a challenge, for example a UUID, in a text file called
challenge.txt:Prepare the challenge stringuser@HOSTNAME:~/test$ cat challenge.txt 22ff6b83-784c-46ab-8514-096c3c2b93ffSign the challenge with the secp256r1, secp256k1, or ED25519 elliptic curve.
To sign the challenge with secp256r1 or secp256k1, enter the following command:
Signature with secp256r1 or secp256k1openssl dgst -sha256 -sign privateKey.pem challenge.txt | base64The output of the signature operation is in raw format, which we converted to Base64, to give an output similar to the following example:
Output of secp256r1 or secp256k1MEQCIGtDBRAdRgUn9kT3olUGBmQbzEwQ2wQr8Ucevu6uwDmXAiB+OISmprOU7TwI0XUnyNuNQpBpyze9fnaLTp5LxZuJ/Q==To sign the challenge with ED25519:
Enter the following command:
Signature with ED25519openssl pkeyutl -sign -inkey privateKey.pem -rawin -in challenge.txt -out sig.datBecause the signature output of ED25519 is in compact format, we must first convert it to DER format.
Convert the compact signature to DER format, and then encode it in Base64, with the one of the following commands:
Signature conversion to DER and Base64cat sig.dat | hexdump -v -e '/1 "%02x"' | sed 's/\(.\{64\}\)\(.\{64\}\)/30440220\10220\2/g' | xxd -r -p | base64 -w0The output is similar to the following example:
Output of ED25519 after conversionMEQCICVs3TeU6DsaKc/DC3Y4VerQjiy/Sm4Prfyoh4yFKj1TAiBPu6/c5rxNxCU5Gl2NZH+orCUHKGFTAxcrDxRQqTYSBA==You can submit this output to Ripple Custody to obtain a JWT. For more information, see Obtain a token.
This example shows how to sign a payload before you submit an intent to create or update system data. For more information, see Sign intents.
To sign a payload for intent submission:
Save the following example in a JSON file named
v0_CreateAccount.json:Example account creation intent in JSON format{ "author":{ "id":"e02f08ce-e515-46fa-9ed3-326179a1de89", "domainId":"789265d6-aea6-4c7b-9d68-1a532ea3060b" }, "expiryAt":"2024-08-24T14:15:22Z", "targetDomainId":"789265d6-aea6-4c7b-9d68-1a532ea3060b", "id":"1b96fd0f-4e50-4782-9fae-ff0fce7f982c", "payload":{ "id":"9dbc612f-b98a-4c83-8143-9d33e1865127", "alias":"OpenSSL Test Account 1", "providerDetails":{ "vaultId":"00000000-0000-0000-0000-000000000000", "keyStrategy":"VaultHard", "type":"Vault" }, "ledgerIds":["bitcoin-cash-testnet"], "lock":"Unlocked", "customProperties":{}, "type":"v0_CreateAccount" }, "description":"OpenSSL Creation of Test Account 1", "customProperties":{}, "type":"Propose" }Sort the JSON payload, with the following command:
Sort the payload filecat v0_CreateAccount.json | jq -j -S -c > v0_CreateAccount_Sorted.jsonThe following example shows the output of the sorted JSON file:
Sorted payload output{"author":{"domainId":"777265d6-aea6-4c7b-9d68-1a532ea3060b","id":"e02f08ce-e515-46fa-9ed3-326179a1de77"},"customProperties":{},"description":"OpenSSL Creation of Test Account 1","expiryAt":"2024-08-24T14:15:22Z","id":"1b95fd0f-4e50-4782-9fae-ff0fce7f982c","payload":{"alias":"OpenSSL Test Account 2","customProperties":{},"id":"9cbc612f-b98a-4c83-8143-9d33e1865127","ledgerIds":["bitcoin-cash-testnet"],"lock":"Unlocked","providerDetails":{"keyStrategy":"VaultHard","type":"Vault","vaultId":"00000000-0000-0000-0000-000000000000"},"type":"v0_CreateAccount"},"targetDomainId":"777265d6-aea6-4c7b-9d68-1a532ea3060b","type":"Propose"}Sign the payload using secp256r1, secp256k1, or ED25519.
- To sign using secp256r1 or secp256k1, enter one of the following commands:
Payload signature using secp256r1 or secp256k1openssl dgst -sha256 -sign privateKey.pem v0_CreateAccount_Sorted.json | base64 -w0- To sign using ED25519, enter one of the following commands:
Payload signature using ED25519tmp=$(mktemp) cat v0_CreateAccount_Sorted.json | sha256sum | xxd -r -p > ${tmp} openssl pkeyutl -sign -inkey privateKey.pem -rawin -in ${tmp} | hexdump -v -e '/1 "%02x"' | sed 's/\(.\{64\}\)\(.\{64\}\)/30440220\10220\2/g' | xxd -r -p | base64 -w0 rm -f ${tmp}
All data payloads that you retrieve from Ripple Custody that are part of the secure data include a signature. To verify the authenticity of this signature, we highly recommend that you run a verification step.
To check the signature:
Retrieve the public key of Ripple Custody, with the List system properties API operation.
The API operation returns the public key as part of the response:
Custody public key{ "id": "CUSTODY_API_KEY", "value": { "publicKey": { "value": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1WXjDbBcWEVmqObzEndfnug+nd4EOEqcXMY5a5I0XvfRq1+K6Z9K1DdZ2YgFIbuzdX2Z2kOfE/fcDj/QzF5IAw==", "type": "PublicKey" } } }Save the public key value into a text file, together with a header and footer, in the following format:
Formatted public key fileCustodypublicKey.pem -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1WXjDbBcWEVmqObzEndfnug+nd4EOEqcXMY5a5I0XvfRq1+K6Z9K1DdZ2YgFIbuzdX2Z2kOfE/fcDj/zF5IAw== -----END PUBLIC KEY-----Prepare the signature string. OpenSSL expects the signature in raw format, so the signature string received needs to be converted using the following command:
Signature conversion to raw formatopenssl enc -d -A -base64 -in signatureByHarmonize.txt -out signatureByHarmonize.binSort the result, using a command similar to step 2 of Sign a payload for intent submission.
Once you have the sorted object, the Ripple Custody public key, and the signature in binary format, to verify the data, run the following command:
Data verificationopenssl pkeyutl -verify -pubin -inkey CustodypublicKey.pem -rawin -in Sorted_Object.json -sigfile signatureByHarmonize.bin
If the signature is valid, Ripple Custody returns the following message: Signature Verified Successfully