mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-10 23:28:45 +00:00
123 lines
3.1 KiB
TypeScript
123 lines
3.1 KiB
TypeScript
import crypto from 'crypto';
|
|
|
|
import { SecretDataProps, Tag } from 'public/data/frequentInterfaces';
|
|
|
|
import getLatestFileKey from '@app/pages/api/workspace/getLatestFileKey';
|
|
|
|
import { decryptAssymmetric, encryptSymmetric } from '../cryptography/crypto';
|
|
|
|
interface EncryptedSecretProps {
|
|
id: string;
|
|
createdAt: string;
|
|
environment: string;
|
|
secretCommentCiphertext: string;
|
|
secretCommentIV: string;
|
|
secretCommentTag: string;
|
|
secretKeyCiphertext: string;
|
|
secretKeyIV: string;
|
|
secretKeyTag: string;
|
|
secretValueCiphertext: string;
|
|
secretValueIV: string;
|
|
secretValueTag: string;
|
|
type: 'personal' | 'shared';
|
|
tags: Tag[];
|
|
}
|
|
|
|
/**
|
|
* Encypt secrets before pushing the to the DB
|
|
* @param {object} obj
|
|
* @param {object} obj.secretsToEncrypt - secrets that we want to encrypt
|
|
* @param {object} obj.workspaceId - the id of a project in which we are encrypting secrets
|
|
* @returns
|
|
*/
|
|
const encryptSecrets = async ({
|
|
secretsToEncrypt,
|
|
workspaceId,
|
|
env
|
|
}: {
|
|
secretsToEncrypt: SecretDataProps[];
|
|
workspaceId: string;
|
|
env: string;
|
|
}) => {
|
|
let secrets;
|
|
try {
|
|
const sharedKey = await getLatestFileKey({ workspaceId });
|
|
|
|
const PRIVATE_KEY = localStorage.getItem('PRIVATE_KEY') as string;
|
|
|
|
let randomBytes: string;
|
|
if (Object.keys(sharedKey).length > 0) {
|
|
// case: a (shared) key exists for the workspace
|
|
randomBytes = decryptAssymmetric({
|
|
ciphertext: sharedKey.latestKey.encryptedKey,
|
|
nonce: sharedKey.latestKey.nonce,
|
|
publicKey: sharedKey.latestKey.sender.publicKey,
|
|
privateKey: PRIVATE_KEY
|
|
});
|
|
} else {
|
|
// case: a (shared) key does not exist for the workspace
|
|
randomBytes = crypto.randomBytes(16).toString('hex');
|
|
}
|
|
|
|
secrets = secretsToEncrypt.map((secret) => {
|
|
// encrypt key
|
|
const {
|
|
ciphertext: secretKeyCiphertext,
|
|
iv: secretKeyIV,
|
|
tag: secretKeyTag
|
|
} = encryptSymmetric({
|
|
plaintext: secret.key,
|
|
key: randomBytes
|
|
});
|
|
|
|
// encrypt value
|
|
const {
|
|
ciphertext: secretValueCiphertext,
|
|
iv: secretValueIV,
|
|
tag: secretValueTag
|
|
} = encryptSymmetric({
|
|
plaintext: secret.value ?? '',
|
|
key: randomBytes
|
|
});
|
|
|
|
// encrypt comment
|
|
const {
|
|
ciphertext: secretCommentCiphertext,
|
|
iv: secretCommentIV,
|
|
tag: secretCommentTag
|
|
} = encryptSymmetric({
|
|
plaintext: secret.comment ?? '',
|
|
key: randomBytes
|
|
});
|
|
|
|
const result: EncryptedSecretProps = {
|
|
id: secret.id,
|
|
createdAt: '',
|
|
environment: env,
|
|
secretKeyCiphertext,
|
|
secretKeyIV,
|
|
secretKeyTag,
|
|
secretValueCiphertext,
|
|
secretValueIV,
|
|
secretValueTag,
|
|
secretCommentCiphertext,
|
|
secretCommentIV,
|
|
secretCommentTag,
|
|
type:
|
|
secret.valueOverride === undefined || secret?.value !== secret?.valueOverride
|
|
? 'shared'
|
|
: 'personal',
|
|
tags: secret.tags
|
|
};
|
|
|
|
return result;
|
|
});
|
|
} catch (error) {
|
|
console.log('Error while encrypting secrets');
|
|
}
|
|
|
|
return secrets;
|
|
};
|
|
|
|
export default encryptSecrets;
|