Merge pull request #3357 from Infisical/daniel/kms-sign-verify

feat(kms): sign & verify data
This commit is contained in:
Daniel Hougaard
2025-04-13 22:22:23 +04:00
committed by GitHub
49 changed files with 2334 additions and 171 deletions
@@ -106,6 +106,10 @@ export const eventToNameMap: { [K in EventType]: string } = {
[EventType.GET_CMEK]: "Get KMS key",
[EventType.CMEK_ENCRYPT]: "Encrypt with KMS key",
[EventType.CMEK_DECRYPT]: "Decrypt with KMS key",
[EventType.CMEK_SIGN]: "Sign with KMS key",
[EventType.CMEK_VERIFY]: "Verify with KMS key",
[EventType.CMEK_LIST_SIGNING_ALGORITHMS]: "List signing algorithms for KMS key",
[EventType.CMEK_GET_PUBLIC_KEY]: "Get public key for KMS key",
[EventType.UPDATE_EXTERNAL_GROUP_ORG_ROLE_MAPPINGS]:
"Update SSO group to organization role mapping",
[EventType.GET_EXTERNAL_GROUP_ORG_ROLE_MAPPINGS]: "List SSO group to organization role mapping",
@@ -110,6 +110,10 @@ export enum EventType {
GET_CMEK = "get-cmek",
CMEK_ENCRYPT = "cmek-encrypt",
CMEK_DECRYPT = "cmek-decrypt",
CMEK_SIGN = "cmek-sign",
CMEK_VERIFY = "cmek-verify",
CMEK_LIST_SIGNING_ALGORITHMS = "cmek-list-signing-algorithms",
CMEK_GET_PUBLIC_KEY = "cmek-get-public-key",
UPDATE_EXTERNAL_GROUP_ORG_ROLE_MAPPINGS = "update-external-group-org-role-mapping",
GET_EXTERNAL_GROUP_ORG_ROLE_MAPPINGS = "get-external-group-org-role-mapping",
GET_PROJECT_TEMPLATES = "get-project-templates",
@@ -8,6 +8,10 @@ import {
TCmekDecryptResponse,
TCmekEncrypt,
TCmekEncryptResponse,
TCmekSign,
TCmekSignResponse,
TCmekVerify,
TCmekVerifyResponse,
TCreateCmek,
TDeleteCmek,
TUpdateCmek
@@ -74,6 +78,44 @@ export const useCmekEncrypt = () => {
});
};
export const useCmekSign = () => {
return useMutation({
mutationFn: async ({
keyId,
data,
signingAlgorithm,
isBase64Encoded
}: TCmekSign & { isBase64Encoded: boolean }) => {
const res = await apiRequest.post<TCmekSignResponse>(`/api/v1/kms/keys/${keyId}/sign`, {
data: isBase64Encoded ? data : encodeBase64(Buffer.from(data)),
signingAlgorithm
});
return res.data;
}
});
};
export const useCmekVerify = () => {
return useMutation({
mutationFn: async ({
keyId,
data,
signature,
signingAlgorithm,
isBase64Encoded
}: TCmekVerify & { isBase64Encoded: boolean }) => {
const res = await apiRequest.post<TCmekVerifyResponse>(`/api/v1/kms/keys/${keyId}/verify`, {
data: isBase64Encoded ? data : encodeBase64(Buffer.from(data)),
signature,
signingAlgorithm
});
return res.data;
}
});
};
export const useCmekDecrypt = () => {
return useMutation({
mutationFn: async ({ keyId, ciphertext }: TCmekDecrypt) => {
+59 -3
View File
@@ -1,10 +1,18 @@
import { z } from "zod";
import { OrderByDirection } from "@app/hooks/api/generic/types";
export enum KmsKeyUsage {
ENCRYPT_DECRYPT = "encrypt-decrypt",
SIGN_VERIFY = "sign-verify"
}
export type TCmek = {
id: string;
keyUsage: KmsKeyUsage;
name: string;
description?: string;
encryptionAlgorithm: EncryptionAlgorithm;
encryptionAlgorithm: AsymmetricKeyAlgorithm | SymmetricKeyAlgorithm;
projectId: string;
isDisabled: boolean;
isReserved: boolean;
@@ -17,7 +25,8 @@ export type TCmek = {
type ProjectRef = { projectId: string };
type KeyRef = { keyId: string };
export type TCreateCmek = Pick<TCmek, "name" | "description" | "encryptionAlgorithm"> & ProjectRef;
export type TCreateCmek = Pick<TCmek, "name" | "description" | "encryptionAlgorithm" | "keyUsage"> &
ProjectRef;
export type TUpdateCmek = KeyRef &
Partial<Pick<TCmek, "name" | "description" | "isDisabled">> &
ProjectRef;
@@ -26,6 +35,13 @@ export type TDeleteCmek = KeyRef & ProjectRef;
export type TCmekEncrypt = KeyRef & { plaintext: string; isBase64Encoded?: boolean };
export type TCmekDecrypt = KeyRef & { ciphertext: string };
export type TCmekSign = KeyRef & { data: string; signingAlgorithm: SigningAlgorithm };
export type TCmekVerify = KeyRef & {
data: string;
signature: string;
signingAlgorithm: SigningAlgorithm;
};
export type TProjectCmeksList = {
keys: TCmek[];
totalCount: number;
@@ -44,6 +60,18 @@ export type TCmekEncryptResponse = {
ciphertext: string;
};
export type TCmekSignResponse = {
signature: string;
keyId: string;
signingAlgorithm: SigningAlgorithm;
};
export type TCmekVerifyResponse = {
signatureValid: boolean;
keyId: string;
signingAlgorithm: SigningAlgorithm;
};
export type TCmekDecryptResponse = {
plaintext: string;
};
@@ -52,7 +80,35 @@ export enum CmekOrderBy {
Name = "name"
}
export enum EncryptionAlgorithm {
export enum AsymmetricKeyAlgorithm {
RSA_4096 = "RSA_4096",
ECC_NIST_P256 = "ECC_NIST_P256"
}
// Supported symmetric encrypt/decrypt algorithms
export enum SymmetricKeyAlgorithm {
AES_GCM_256 = "aes-256-gcm",
AES_GCM_128 = "aes-128-gcm"
}
export const AllowedEncryptionKeyAlgorithms = z.enum([
...Object.values(SymmetricKeyAlgorithm),
...Object.values(AsymmetricKeyAlgorithm)
] as [string, ...string[]]).options;
export enum SigningAlgorithm {
// RSA PSS algorithms
RSASSA_PSS_SHA_256 = "RSASSA_PSS_SHA_256",
RSASSA_PSS_SHA_384 = "RSASSA_PSS_SHA_384",
RSASSA_PSS_SHA_512 = "RSASSA_PSS_SHA_512",
// RSA PKCS#1 v1.5 algorithms
RSASSA_PKCS1_V1_5_SHA_256 = "RSASSA_PKCS1_V1_5_SHA_256",
RSASSA_PKCS1_V1_5_SHA_384 = "RSASSA_PKCS1_V1_5_SHA_384",
RSASSA_PKCS1_V1_5_SHA_512 = "RSASSA_PKCS1_V1_5_SHA_512",
// ECDSA algorithms
ECDSA_SHA_256 = "ECDSA_SHA_256",
ECDSA_SHA_384 = "ECDSA_SHA_384",
ECDSA_SHA_512 = "ECDSA_SHA_512"
}