diff --git a/backend/src/lib/secret/index.ts b/backend/src/lib/secret/index.ts index 848ebde70..361d152de 100644 --- a/backend/src/lib/secret/index.ts +++ b/backend/src/lib/secret/index.ts @@ -1,10 +1,10 @@ import crypto from "crypto"; import { z } from "zod"; -import { SecretKeyEncoding, TProjectKeys } from "@app/db/schemas"; +import { TProjectKeys } from "@app/db/schemas"; -import { decryptAsymmetric, decryptSymmetric } from "../crypto"; -import { decryptSymmetric128BitHexKeyUTF8, TDecryptSymmetricInput } from "../crypto/encryption"; +import { decryptAsymmetric } from "../crypto"; +// import { decryptSymmetric128BitHexKeyUTF8, TDecryptSymmetricInput } from "../crypto/encryption"; export enum SecretDocType { Secret = "secret", @@ -43,38 +43,60 @@ const PartialDecryptedSecretSchema = z.object({ export type TPartialSecret = z.infer; export type TPartialDecryptedSecret = z.infer; -const symmetricDecrypt = ({ - keyEncoding, +// const symmetricDecrypt = ({ +// keyEncoding, +// ciphertext, +// tag, +// iv, +// key, +// isApprovalSecret +// }: TDecryptSymmetricInput & { keyEncoding: SecretKeyEncoding; isApprovalSecret: boolean }) => { +// try { +// if (keyEncoding === SecretKeyEncoding.UTF8 || isApprovalSecret) { +// const data = decryptSymmetric128BitHexKeyUTF8({ key, iv, tag, ciphertext }); +// return data; +// } +// if (keyEncoding === SecretKeyEncoding.BASE64) { +// const data = decryptSymmetric({ key, iv, tag, ciphertext }); +// return data; +// } +// throw new Error("BAD_ENCODING"); +// } catch (err) { +// if (err instanceof Error && err.message === "BAD_ENCODING") { +// throw new Error("Invalid key encoding, cannot decrypt secret!"); +// } + +// // This is taken directly from our frontend secret decryption logic. +// const decipher = crypto.createDecipheriv("aes-256-gcm", key, Buffer.from(iv, "base64")); +// decipher.setAuthTag(Buffer.from(tag, "base64")); + +// let data = decipher.update(ciphertext, "base64", "utf8"); +// data += decipher.final("utf8"); + +// console.log(data); + +// return data; +// } +// }; + +const decryptSecret = ({ ciphertext, - tag, iv, - key, - isApprovalSecret -}: TDecryptSymmetricInput & { keyEncoding: SecretKeyEncoding; isApprovalSecret: boolean }) => { - try { - if (keyEncoding === SecretKeyEncoding.UTF8 || isApprovalSecret) { - const data = decryptSymmetric128BitHexKeyUTF8({ key, iv, tag, ciphertext }); - return data; - } - if (keyEncoding === SecretKeyEncoding.BASE64) { - const data = decryptSymmetric({ key, iv, tag, ciphertext }); - return data; - } - throw new Error("BAD_ENCODING"); - } catch (err) { - if (err instanceof Error && err.message === "BAD_ENCODING") { - throw new Error("Invalid key encoding, cannot decrypt secret!"); - } + tag, + key +}: { + ciphertext: string; + iv: string; + tag: string; + key: string | Buffer; +}) => { + const decipher = crypto.createDecipheriv("aes-256-gcm", key, Buffer.from(iv, "base64")); + decipher.setAuthTag(Buffer.from(tag, "base64")); - // This is taken directly from our frontend secret decryption logic. - const decipher = crypto.createDecipheriv("aes-256-gcm", key, Buffer.from(iv, "base64")); - decipher.setAuthTag(Buffer.from(tag, "base64")); + let cleartext = decipher.update(ciphertext, "base64", "utf8"); + cleartext += decipher.final("utf8"); - let data = decipher.update(ciphertext, "base64", "utf8"); - data += decipher.final("utf8"); - - return data; - } + return cleartext; }; export const decryptSecrets = ( @@ -96,45 +118,52 @@ export const decryptSecrets = ( const secrets: TPartialDecryptedSecret[] = []; encryptedSecrets.forEach((encSecret) => { - const secretKey = symmetricDecrypt({ - ciphertext: encSecret.secretKeyCiphertext, - iv: encSecret.secretKeyIV, - tag: encSecret.secretKeyTag, - key, - keyEncoding: encSecret.keyEncoding as SecretKeyEncoding, - isApprovalSecret: encSecret.docType === SecretDocType.ApprovalSecret - }); + try { + console.log(encSecret.keyEncoding); - const secretValue = symmetricDecrypt({ - ciphertext: encSecret.secretValueCiphertext, - iv: encSecret.secretValueIV, - tag: encSecret.secretValueTag, - key, - keyEncoding: encSecret.keyEncoding as SecretKeyEncoding, - isApprovalSecret: encSecret.docType === SecretDocType.ApprovalSecret - }); + const secretKey = decryptSecret({ + ciphertext: encSecret.secretKeyCiphertext, + iv: encSecret.secretKeyIV, + tag: encSecret.secretKeyTag, + key + // keyEncoding: encSecret.keyEncoding as SecretKeyEncoding, + // isApprovalSecret: encSecret.docType === SecretDocType.ApprovalSecret + }); - const secretComment = - encSecret.secretCommentCiphertext && encSecret.secretCommentIV && encSecret.secretCommentTag - ? symmetricDecrypt({ - ciphertext: encSecret.secretCommentCiphertext, - iv: encSecret.secretCommentIV, - tag: encSecret.secretCommentTag, - key, - keyEncoding: encSecret.keyEncoding as SecretKeyEncoding, - isApprovalSecret: encSecret.docType === SecretDocType.ApprovalSecret - }) - : ""; + const secretValue = decryptSecret({ + ciphertext: encSecret.secretValueCiphertext, + iv: encSecret.secretValueIV, + tag: encSecret.secretValueTag, + key + // keyEncoding: encSecret.keyEncoding as SecretKeyEncoding, + // isApprovalSecret: encSecret.docType === SecretDocType.ApprovalSecret + }); - const decryptedSecret: TPartialDecryptedSecret = { - id: encSecret.id, - secretKey, - secretValue, - secretComment, - docType: encSecret.docType - }; + const secretComment = + encSecret.secretCommentCiphertext && encSecret.secretCommentIV && encSecret.secretCommentTag + ? decryptSecret({ + ciphertext: encSecret.secretCommentCiphertext, + iv: encSecret.secretCommentIV, + tag: encSecret.secretCommentTag, + key + // keyEncoding: encSecret.keyEncoding as SecretKeyEncoding, + // isApprovalSecret: encSecret.docType === SecretDocType.ApprovalSecret + }) + : ""; - secrets.push(decryptedSecret); + const decryptedSecret: TPartialDecryptedSecret = { + id: encSecret.id, + secretKey, + secretValue, + secretComment, + docType: encSecret.docType + }; + + secrets.push(decryptedSecret); + } catch (err) { + // This is ok, because we check that the decrypted secrets array length is the same as the encrypted secrets array length. + console.log(`[${encSecret.id}] - failed to decrypt`, err); + } }); return secrets; diff --git a/backend/src/services/project/project-queue.ts b/backend/src/services/project/project-queue.ts index ff61f34f9..5c1e35d82 100644 --- a/backend/src/services/project/project-queue.ts +++ b/backend/src/services/project/project-queue.ts @@ -143,7 +143,12 @@ export const projectQueueFactory = ({ secrets.push(...approvalSecrets.map((el) => ({ ...el, docType: SecretDocType.ApprovalSecret }))); } - const decryptedSecrets = decryptSecrets(secrets, userPrivateKey, oldProjectKey); + const decryptedSecrets = decryptSecrets( + // secrets.filter((s) => s.keyEncoding === "base64"), + secrets, + userPrivateKey, + oldProjectKey + ); console.log( decryptedSecrets