diff --git a/.infisicalignore b/.infisicalignore index a88bdccbd..4ccf734b6 100644 --- a/.infisicalignore +++ b/.infisicalignore @@ -22,3 +22,5 @@ frontend/src/components/secret-rotations-v2/ViewSecretRotationV2GeneratedCredent frontend/src/hooks/api/secretRotationsV2/types/index.ts:generic-api-key:28 frontend/src/hooks/api/secretRotationsV2/types/index.ts:generic-api-key:65 frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretRotationListView/SecretRotationItem.tsx:generic-api-key:26 +docs/documentation/platform/kms/overview.mdx:generic-api-key:281 +docs/documentation/platform/kms/overview.mdx:generic-api-key:344 diff --git a/backend/src/lib/crypto/sign/signing.ts b/backend/src/lib/crypto/sign/signing.ts index 7dd71b5f6..66f36dc0f 100644 --- a/backend/src/lib/crypto/sign/signing.ts +++ b/backend/src/lib/crypto/sign/signing.ts @@ -118,7 +118,12 @@ export const signingService = (algorithm: AsymmetricKeyAlgorithm): TAsymmetricSi } }; - const $signRsaDigest = async (digest: Buffer, privateKey: Buffer, hashAlgorithm: SupportedHashAlgorithm) => { + const $signRsaDigest = async ( + digest: Buffer, + privateKey: Buffer, + hashAlgorithm: SupportedHashAlgorithm, + signingAlgorithm: SigningAlgorithm + ) => { const tempDir = await createTemporaryDirectory("kms-rsa-sign"); const digestPath = path.join(tempDir, "digest.bin"); const sigPath = path.join(tempDir, "signature.bin"); @@ -164,12 +169,22 @@ export const signingService = (algorithm: AsymmetricKeyAlgorithm): TAsymmetricSi } return signature; + } catch (err) { + logger.error(err, "KMS: Failed to sign RSA digest"); + throw new BadRequestError({ + message: `Failed to sign RSA digest with ${signingAlgorithm} due to signing error. Ensure that your digest is hashed with ${hashAlgorithm.toUpperCase()}.` + }); } finally { await cleanTemporaryDirectory(tempDir); } }; - const $signEccDigest = async (digest: Buffer, privateKey: Buffer, hashAlgorithm: SupportedHashAlgorithm) => { + const $signEccDigest = async ( + digest: Buffer, + privateKey: Buffer, + hashAlgorithm: SupportedHashAlgorithm, + signingAlgorithm: SigningAlgorithm + ) => { const tempDir = await createTemporaryDirectory("ecc-sign"); const digestPath = path.join(tempDir, "digest.bin"); const keyPath = path.join(tempDir, "key.pem"); @@ -216,6 +231,11 @@ export const signingService = (algorithm: AsymmetricKeyAlgorithm): TAsymmetricSi } return signature; + } catch (err) { + logger.error(err, "KMS: Failed to sign ECC digest"); + throw new BadRequestError({ + message: `Failed to sign ECC digest with ${signingAlgorithm} due to signing error. Ensure that your digest is hashed with ${hashAlgorithm.toUpperCase()}.` + }); } finally { await cleanTemporaryDirectory(tempDir); } @@ -329,7 +349,12 @@ export const signingService = (algorithm: AsymmetricKeyAlgorithm): TAsymmetricSi const signDigestFunctionsMap: Record< AsymmetricKeyAlgorithm, - (data: Buffer, privateKey: Buffer, hashAlgorithm: SupportedHashAlgorithm) => Promise + ( + data: Buffer, + privateKey: Buffer, + hashAlgorithm: SupportedHashAlgorithm, + signingAlgorithm: SigningAlgorithm + ) => Promise > = { [AsymmetricKeyAlgorithm.ECC_NIST_P256]: $signEccDigest, [AsymmetricKeyAlgorithm.RSA_4096]: $signRsaDigest @@ -360,7 +385,7 @@ export const signingService = (algorithm: AsymmetricKeyAlgorithm): TAsymmetricSi }); } - const signature = await signFunction(data, privateKey, hashAlgorithm); + const signature = await signFunction(data, privateKey, hashAlgorithm, signingAlgorithm); return signature; } diff --git a/docs/documentation/platform/kms/overview.mdx b/docs/documentation/platform/kms/overview.mdx index 8991646cf..577373ab8 100644 --- a/docs/documentation/platform/kms/overview.mdx +++ b/docs/documentation/platform/kms/overview.mdx @@ -30,7 +30,9 @@ The typical workflow for using Infisical KMS consists of the following steps: as via API. -## Guide to Encrypting Data +## Encryption + +### Guide to Encrypting Data In the following steps, we explore how to generate a key and use it to encrypt data. @@ -44,7 +46,8 @@ In the following steps, we explore how to generate a key and use it to encrypt d Specify your key details. Here's some guidance on each field: - Name: A slug-friendly name for the key. - - Type: The encryption algorithm associated with the key (e.g. `AES-GCM-256`). + - Key Usage: The type of key to create (e.g `Encrypt/Decrypt` for encryption, and `Sign/Verify` for signing). + - Algorithm: The encryption algorithm associated with the key (e.g. `AES-GCM-256`). - Description: An optional description of what the intended usage is for the key. ![kms add key modal](/images/platform/kms/infisical-kms/kms-add-key-modal.png) @@ -137,7 +140,7 @@ In the following steps, we explore how to generate a key and use it to encrypt d -## Guide to Decrypting Data +### Guide to Decrypting Data In the following steps, we explore how to use decrypt data using an existing key in Infisical KMS. @@ -193,6 +196,164 @@ In the following steps, we explore how to use decrypt data using an existing key +## Signing + +### Guide to Signing Data + +In the following steps, we explore how to generate a key and use it to sign data. + + + + + + Navigate to Project > Key Management and tap on the **Add Key** button. + ![kms add key button](/images/platform/kms/infisical-kms/kms-add-key.png) + + Specify your key details. Here's some guidance on each field: + + - Name: A slug-friendly name for the key. + - Key Usage: The type of key to create (e.g `Encrypt/Decrypt` for encryption, and `Sign/Verify` for signing). + - Algorithm: The signing algorithm associated with the key (e.g. `RSA_4096`). + - Description: An optional description of what the intended usage is for the key. + + ![kms add key modal](/images/platform/kms/infisical-kms/signing/add-new-rsa-key.png) + + + + Once your key is generated, open the options menu for the newly created key and select sign data. + ![kms key options](/images/platform/kms/infisical-kms/signing/sign-options.png) + + Populate the text area with your data and tap on the Sign button. + ![kms sign data](/images/platform/kms/infisical-kms/signing/sign-data-modal.png) + + Make sure to select the appropriate signing algorithm that will be used to sign the data. + Supported signing algorithms are: + + **For RSA keys:** + - `RSASSA PSS SHA 512`: Not deterministic, and includes random salt. + - `RSASSA PSS SHA 384`: Not deterministic, and includes random salt. + - `RSASSA PSS SHA 256`: Not deterministic, and includes random salt. + - `RSASSA PKCS1 V1.5 SHA 512`: Deterministic, and does not include randomness. + - `RSASSA PKCS1 V1.5 SHA 384`: Deterministic, and does not include randomness. + - `RSASSA PKCS1 V1.5 SHA 256`: Deterministic, and does not include randomness. + + **For ECC keys:** + - `ECDSA SHA 512`: Not deterministic, and includes randomness. + - `ECDSA SHA 384`: Not deterministic, and includes randomness. + - `ECDSA SHA 256`: Not deterministic, and includes randomness. + + In this example, we'll use the `RSASSA PSS SHA 512` signing algorithm. + + + If your data is already Base64 encoded make sure to toggle the respective switch on to avoid + redundant encoding. + + + Copy and store the signature of your data. + ![kms signed data](/images/platform/kms/infisical-kms/signing/copy-signature.png) + + + + + + + To sign data, make an API request to the [Sign + Data](/api-reference/endpoints/kms/signing/sign) API endpoint, + specifying the key to use. + + ### Sample request + + ```bash Request + curl --request POST \ + --url https://app.infisical.com/api/v1/kms/keys//sign \ + --header 'Content-Type: application/json' \ + --data '{ + "data": "SGVsbG8sIFdvcmxkIQ==", // base64 encoded data + "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_512", + }' + ``` + + ### Sample response + + ```bash Response + { + "signature": "JYuiBt1Ta9pbqFIW9Ou6qzBsFhjYbMJp9k4dP87ILrO+F2MPnp85g3nOlXK1ttZmRoGWsWnLNDRn9W3rf5VtkeaixPqUW/KvY/fM3CxdMyIV3BuxlGgDksjL8X34Eqkrz4CCPo9hjB5uT+rBCOxCgZqRbOdATPipAneUapI9npseNquEeh3jPklwviBix83PJHV9PW2t03AGGUXuMY55ZaFEIMv+IrI1WYdnPVIXDyIitYsS3y+/6KRfhVeTcPNJ5Rw+FE9y1eZzDEZtTNpxOfUT3QIoXmpZlYL4HbhRuJBZ+Yx54C7uPiUIN9U69XbyXt+Kkynykw2HPaagwuCZxiqCU5sFfLnrVbc3dmZxQcX2yRrs2gmFamzBx+uVbi648H4mb7WuE5UPTBjjA11jRsBjCY0YS2T4Vgfe1RlzlPQkZgjP/bnCCGDqXa3/VZAlZX1nTI51X995bPHBQI0rq2sNDlIXenwiAy1wJSITbSI8DbUx09Cr83xCEaYAE6R6PUfog/tbIUXi0VbrYsCVkAGCK446Wb1vW6q7HR8jrjXNwmXlqN9eLbSVWqdWj7N7fieeTYSrECtUaAjxtUYTIVsH2bfT6FOEM9gMWKffOpFowVzzr3B9bNQLIhnEEwebxBw947i4OcxyVIcEUuumWxoKvcbSPxzJ8v1M3SoBBh4=", // base64 encoded signature + "keyId": "62b2c14e-58af-4199-9842-02995c63edf9", + "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_512", + } + ``` + + + To sign predigested data, you can pass `"isDigest": true` in the request body. This requires the data to be a base64 encoded digest of the data you wish to sign. + It's important that the digest is created using the same hashing algorithm as the signing algorithm. As an example, you would create the digest with `SHA512` if you are using the `RSASSA_PKCS1_V1_5_SHA_512` signing algorithm. + + + + + + +### Guide to Verifying Data + +In the following steps, we explore how to verify data using an existing key in Infisical KMS. + + + + + + Navigate to Project > Key Management and open the options menu for the key used to sign the data + you want to verify. + ![kms key options](/images/platform/kms/infisical-kms/signing/sign-options.png) + + + + Paste your signature and data into the text areas and tap on the Verify button. + ![kms verify data](/images/platform/kms/infisical-kms/signing/verify-data-modal.png) + + Your verification result will be displayed and can be copied for use. + ![kms verified data](/images/platform/kms/infisical-kms/signing/signature-verified.png) + + If the signature is invalid, you'll see an error message indicating that the signature is invalid, and the "Signature Status" field will be `Invalid`. + + + + + + + To verify data, make an API request to the [Verify + Data](/api-reference/endpoints/kms/signing/verify) API endpoint, + specifying the key to use. + + ### Sample request + + ```bash Request + curl --request POST \ + --url https://app.infisical.com/api/v1/kms/keys//verify \ + --header 'Content-Type: application/json' \ + --data '{ + "data": "SGVsbG8sIFdvcmxkIQ==", // base64 encoded data + "signature": "JYuiBt1Ta9pbqFIW9Ou6qzBsFhjYbMJp9k4dP87ILrO+F2MPnp85g3nOlXK1ttZmRoGWsWnLNDRn9W3rf5VtkeaixPqUW/KvY/fM3CxdMyIV3BuxlGgDksjL8X34Eqkrz4CCPo9hjB5uT+rBCOxCgZqRbOdATPipAneUapI9npseNquEeh3jPklwviBix83PJHV9PW2t03AGGUXuMY55ZaFEIMv+IrI1WYdnPVIXDyIitYsS3y+/6KRfhVeTcPNJ5Rw+FE9y1eZzDEZtTNpxOfUT3QIoXmpZlYL4HbhRuJBZ+Yx54C7uPiUIN9U69XbyXt+Kkynykw2HPaagwuCZxiqCU5sFfLnrVbc3dmZxQcX2yRrs2gmFamzBx+uVbi648H4mb7WuE5UPTBjjA11jRsBjCY0YS2T4Vgfe1RlzlPQkZgjP/bnCCGDqXa3/VZAlZX1nTI51X995bPHBQI0rq2sNDlIXenwiAy1wJSITbSI8DbUx09Cr83xCEaYAE6R6PUfog/tbIUXi0VbrYsCVkAGCK446Wb1vW6q7HR8jrjXNwmXlqN9eLbSVWqdWj7N7fieeTYSrECtUaAjxtUYTIVsH2bfT6FOEM9gMWKffOpFowVzzr3B9bNQLIhnEEwebxBw947i4OcxyVIcEUuumWxoKvcbSPxzJ8v1M3SoBBh4=", // base64 encoded signature + "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_512" + }' + ``` + + ### Sample response + + ```bash Response + { + "signatureValid": true, + "keyId": "62b2c14e-58af-4199-9842-02995c63edf9", + "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_512" + } + ``` + + To verify predigested data, you can pass `"isDigest": true` in the request body. This requires the data to be a base64 encoded digest of the data you wish to verify. + It's important that the digest is created using the same hashing algorithm as the signing algorithm. As an example, you would create the digest with `SHA512` if you are using the `RSASSA_PKCS1_V1_5_SHA_512` signing algorithm. + + + + + + ## FAQ @@ -205,8 +366,76 @@ In the following steps, we explore how to use decrypt data using an existing key external sources. - Currently, Infisical only supports `AES-128-GCM` and `AES-256-GCM` for - encryption operations. We anticipate supporting more algorithms and - cryptographic operations in the coming months. + Currently Infisical supports 4 different key algorithms with different purposes: + + - `RSA_4096`: For signing and verifying data. + - `ECC_NIST_P256`: For signing and verifying data. + + - `AES-256-GCM`: For encryption and decryption operations. + - `AES-128-GCM`: For encryption and decryption operations. + + We anticipate to further expand our supported algorithms and support cryptographic operations in the future. + + + To sign and verify a digest using the Infisical KMS, you can use the `Sign` and `Verify` endpoints respectively. + You will need to pass `"isDigest": true` in the request body to indicate that you are signing or verifying a digest. + The data you are signing or verifying will need to be a base64 encoded digest of the data you wish to sign or verify. + It's important that the digest is created using the same hashing algorithm as the signing algorithm. As an example, you would create the digest with `SHA512` if you are using the `RSASSA_PKCS1_V1_5_SHA_512` signing algorithm. + + To create a SHA512 digest of your data, you can use the following command with OpenSSL: + ```bash + echo -n "Hello, World" | openssl dgst -sha512 -binary | openssl base64 + ``` + + ### Sample request for signing a digest + + ```bash Request + curl --request POST \ + --url https://app.infisical.com/api/v1/kms/keys//sign \ + --header 'Content-Type: application/json' \ + --data '{ + "data": , + "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_512", + "isDigest": true + }' + ``` + + ### Sample response for signing a digest + + ```bash Response + { + "signature": , + "keyId": , + "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_512" + } + ``` + + ### Sample request for verifying a digest + + ```bash Request + curl --request POST \ + --url https://app.infisical.com/api/v1/kms/keys//verify \ + --header 'Content-Type: application/json' \ + --data '{ + "data": , + "signature": , + "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_512", + "isDigest": true + }' + ``` + + ### Sample response for verifying a digest + + ```bash Response + { + "signatureValid": true, + "keyId": , + "signingAlgorithm": "RSASSA_PKCS1_V1_5_SHA_512" + } + ``` + + + Please note that `RSA PSS` signing algorithms are not supported for digest signing and verification. Please use `RSA PKCS1 V1.5` signing algorithms for digest signing and verification, or `ECDSA` if you're using an ECC key. + diff --git a/docs/images/platform/kms/infisical-kms/signing/add-new-rsa-key.png b/docs/images/platform/kms/infisical-kms/signing/add-new-rsa-key.png new file mode 100644 index 000000000..97d7ca246 Binary files /dev/null and b/docs/images/platform/kms/infisical-kms/signing/add-new-rsa-key.png differ diff --git a/docs/images/platform/kms/infisical-kms/signing/copy-signature.png b/docs/images/platform/kms/infisical-kms/signing/copy-signature.png new file mode 100644 index 000000000..2644b358b Binary files /dev/null and b/docs/images/platform/kms/infisical-kms/signing/copy-signature.png differ diff --git a/docs/images/platform/kms/infisical-kms/signing/sign-data-modal.png b/docs/images/platform/kms/infisical-kms/signing/sign-data-modal.png new file mode 100644 index 000000000..da8a01438 Binary files /dev/null and b/docs/images/platform/kms/infisical-kms/signing/sign-data-modal.png differ diff --git a/docs/images/platform/kms/infisical-kms/signing/sign-options.png b/docs/images/platform/kms/infisical-kms/signing/sign-options.png new file mode 100644 index 000000000..7129c1d5b Binary files /dev/null and b/docs/images/platform/kms/infisical-kms/signing/sign-options.png differ diff --git a/docs/images/platform/kms/infisical-kms/signing/signature-verified.png b/docs/images/platform/kms/infisical-kms/signing/signature-verified.png new file mode 100644 index 000000000..70b7856b6 Binary files /dev/null and b/docs/images/platform/kms/infisical-kms/signing/signature-verified.png differ diff --git a/docs/images/platform/kms/infisical-kms/signing/verify-data-modal.png b/docs/images/platform/kms/infisical-kms/signing/verify-data-modal.png new file mode 100644 index 000000000..6d3683c9f Binary files /dev/null and b/docs/images/platform/kms/infisical-kms/signing/verify-data-modal.png differ