# OpenSSL examples

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).

## Key generation examples

The following examples show how to generate a key pair using the common OpenSSL toolbox.

### Key generation using secp256r1 elliptic curve

To generate a key pair using the secp256r1 elliptic curve, enter the following commands:


```sh secp256r1 private key
openssl ecparam -genkey -name secp256r1 -noout -out privateKey.pem
```


```sh secp256r1 public key
openssl ec -in privateKey.pem -pubout -outform DER | openssl base64 -A -out publicKey.pem
```

### Key generation using secp256k1 elliptic curve

To generate a key pair using the secp256k1 elliptic curve, enter the following commands:


```sh secp256k1 private key
openssl ecparam -genkey -name secp256k1 -noout -out privateKey.pem
```


```sh secp256k1 public key
openssl ec -in privateKey.pem -pubout -outform DER | openssl base64 -A -out publicKey.pem
```

### Key generation using ED25519 elliptic curve

To generate a key pair using the ED25519 elliptic curve, enter the following commands:


```sh ED25519 private key
openssl genpkey -algorithm Ed25519 -out privateKey.pem
```


```sh ED25519 public key
openssl ec -in privateKey.pem -pubout -outform DER | openssl base64 -A -out publicKey.pem
```

### View the output

In 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:

1. To view the contents of the private key files, for each file, enter the following command:

```sh View private key
cat privateKey.pem
```
The output is similar to the following example:

```sh Private key output
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIEfoycax3w8+JvkNv+L0CHmNUAHUcgCxlnOIpw/CoXzxoAoGCCqGSM49
AwEHoUQDQgAEg36xU2KQ6xLPCvZ3JXZYf5pFCagAb7WGMlYCN92zzgi737EOkDOC
MlZB0TY8CbzRHhG4RUdKuLkdRtD+OVIu2w==
-----END EC PRIVATE KEY-----
```
2. To view the contents of the public key files, for each file, enter the following command:

```sh View public key
cat publicKey.pem
```
The output is similar to the following example:

```sh Public key output
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEg36xU2KQ6xLPCvZ3JXZYf5pFCagAb7WGMlYCN92zzgi737EOkDOCMlZB0TY8CbzRHhG4RUdKuLkdRtD+OVIu2w==
```


## Signature examples

The following examples show how to:

- Sign a challenge to obtain a JSON web token (JWT)
- Submit an intent


### Sign a challenge to obtain a JWT

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)](/products/custody/v1.15/api/get-started/jwt) in the API guide.

To generate the signature:

1. Prepare a random string to use as a challenge, for example a UUID, in a text file called `challenge.txt`:

```sh Prepare the challenge string
user@HOSTNAME:~/test$ cat challenge.txt
22ff6b83-784c-46ab-8514-096c3c2b93ff
```
2. Sign the challenge with the secp256r1, secp256k1, or ED25519 elliptic curve.
  - To sign the challenge with secp256r1 or secp256k1, enter the following command:

```sh Signature with secp256r1 or secp256k1
openssl dgst -sha256 -sign privateKey.pem challenge.txt | base64
```

```sh Signature with secp256r1 or secp256k1
openssl dgst -sha256 -sign privateKey.pem challenge.txt | base64 -w0
```
The output of the signature operation is in raw format, which we converted to Base64, to give an output similar to the following example:

```sh Output of secp256r1 or secp256k1
MEQCIGtDBRAdRgUn9kT3olUGBmQbzEwQ2wQr8Ucevu6uwDmXAiB+OISmprOU7TwI0XUnyNuNQpBpyze9fnaLTp5LxZuJ/Q==
```
  - To sign the challenge with ED25519:
    1. Enter the following command:

```sh Signature with ED25519
openssl pkeyutl -sign -inkey privateKey.pem  -rawin -in challenge.txt -out sig.dat
```
Because the signature output of ED25519 is in compact format, we must first convert it to DER format.
    2. Convert the compact signature to DER format, and then encode it in Base64, with the one of the following commands:

```sh Signature conversion to DER and Base64
cat sig.dat | hexdump -v -e '/1 "%02x"' | sed 's/\(.\{64\}\)\(.\{64\}\)/30440220\10220\2/g' | xxd -r -p | base64 -w0
```

```sh Signature conversion to DER and Base64
cat sig.dat | hexdump -v -e '/1 "%02x"' | sed 's/\(.\{64\}\)\(.\{64\}\)/30440220\10220\2/g' | xxd -r -p | base64 -b0
```
The output is similar to the following example:

```sh Output of ED25519 after conversion
MEQCICVs3TeU6DsaKc/DC3Y4VerQjiy/Sm4Prfyoh4yFKj1TAiBPu6/c5rxNxCU5Gl2NZH+orCUHKGFTAxcrDxRQqTYSBA==
```
You can submit this output to Ripple Custody to obtain a JWT. For more information, see [Obtain a token](/products/custody/v1.15/api/get-started/jwt#obtain-a-token).


### Sign a payload for intent submission

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](/products/custody/v1.15/api/get-started/key-operations/update/intent-signature).

To sign a payload for intent submission:

1. Save the following example in a JSON file named `v0_CreateAccount.json`:

```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"
}
```
2. Sort the JSON payload, with the following command:

```sh Sort the payload file
cat v0_CreateAccount.json | jq -j -S -c > v0_CreateAccount_Sorted.json
```
The following example shows the output of the sorted JSON file:

```json 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"}
```
3. Sign the payload using secp256r1, secp256k1, or ED25519.
  - To sign using secp256r1 or secp256k1, enter one of the following commands:

```sh Payload signature using secp256r1 or secp256k1
openssl dgst -sha256 -sign privateKey.pem v0_CreateAccount_Sorted.json | base64 -w0
```

```sh Payload signature using secp256r1 and secp256k1
openssl dgst -sha256 -sign privateKey.pem v0_CreateAccount_Sorted.json | base64 -b0
```
  - To sign using ED25519, enter one of the following commands:

```sh Payload signature using ED25519
tmp=$(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}
```

```sh Payload signature using ED25519
tmp=$(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 -b0
rm -f ${tmp}
```


### Check the signature returned by Ripple Custody

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:

1. Retrieve the public key of Ripple Custody, with the [List system properties](/products/custody/v1.15/api/reference/openapi/systemproperties/getsystemproperties) API operation.
The API operation returns the public key as part of the response:

```json Custody public key
{
    "id": "CUSTODY_API_KEY",
    "value": {
        "publicKey": {
            "value": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1WXjDbBcWEVmqObzEndfnug+nd4EOEqcXMY5a5I0XvfRq1+K6Z9K1DdZ2YgFIbuzdX2Z2kOfE/fcDj/QzF5IAw==",
            "type": "PublicKey"
        }
    }
}
```
2. Save the public key value into a text file, together with a header and footer, in the following format:

```sh Formatted public key file
CustodypublicKey.pem
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE1WXjDbBcWEVmqObzEndfnug+nd4EOEqcXMY5a5I0XvfRq1+K6Z9K1DdZ2YgFIbuzdX2Z2kOfE/fcDj/zF5IAw==
-----END PUBLIC KEY-----
```
3. Prepare the signature string. OpenSSL expects the signature in raw format, so the signature string received needs to be converted using the following command:

```sh Signature conversion to raw format
openssl enc -d -A -base64 -in signatureByHarmonize.txt -out signatureByHarmonize.bin
```
4. Sort the result, using a command similar to step 2 of [Sign a payload for intent submission](#sign-a-payload-for-intent-submission).
5. 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:

```sh Data verification
openssl 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`