Skip to content

Commit

Permalink
Encrypt secrets with public key
Browse files Browse the repository at this point in the history
  • Loading branch information
ZIJ committed Aug 2, 2024
1 parent 8be4f37 commit 11beb09
Showing 1 changed file with 56 additions and 9 deletions.
65 changes: 56 additions & 9 deletions src/data/admin/encryption.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { supabaseAdminClient } from '@/supabase-clients/admin/supabaseAdminClient';
import { EnvVar } from '@/types/userTypes';
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';

import { scrypt } from 'crypto';
import {
createCipheriv,
createDecipheriv,
publicEncrypt,
randomBytes,
} from 'crypto';

import { constants, scrypt } from 'crypto';
import { promisify } from 'util';

const scryptAsync = promisify(scrypt);
Expand All @@ -13,7 +18,38 @@ async function deriveKey(projectId: string, salt: Buffer): Promise<Buffer> {
return scryptAsync(keyMaterial, salt, 32) as Promise<Buffer>;
}

export async function encrypt(
export async function encryptSecretWithPublicKey(
text: string,
projectId: string,
): Promise<string> {
const { data: orgData } = await supabaseAdminClient
.from('projects')
.select('organization_id')
.eq('id', projectId)
.single();
const { data: publicKeyData } = await supabaseAdminClient
.from('organizations')
.select('public_key')
.eq('id', orgData?.organization_id || '')
.single();
const publicKey = publicKeyData?.public_key;
if (!publicKey) {
console.error('No secrets key in the org');
throw new Error('No secrets key in the org');
}
const buffer = Buffer.from(text, 'utf8');
const encrypted = publicEncrypt(
{
key: publicKey,
padding: constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha256',
},
buffer,
);
return encrypted.toString('base64');
}

export async function encryptWithDerivedKey(
text: string,
projectId: string,
): Promise<string> {
Expand All @@ -37,7 +73,7 @@ export async function encrypt(
);
}

export async function decrypt(
export async function decryptWithDerivedKey(
encryptedText: string,
projectId: string,
): Promise<string> {
Expand Down Expand Up @@ -67,15 +103,23 @@ export async function storeEncryptedEnvVar(
name,
isSecret,
});
const encrypted = await encrypt(value, projectId);
//TODO better name
const plainTextValue = isSecret
? encryptSecretWithPublicKey(value, projectId)
: value;

const encryptedWithDerivedKeyValue = await encryptWithDerivedKey(
value,
projectId,
);

const { data, error } = await supabaseAdminClient
.from('encrypted_env_vars')
.upsert(
{
project_id: projectId,
name,
encrypted_value: encrypted,
encrypted_value: encryptedWithDerivedKeyValue,
is_secret: isSecret,
updated_at: new Date().toISOString(),
},
Expand Down Expand Up @@ -103,7 +147,10 @@ export async function getDecryptedEnvVar(projectId: string, name: string) {
if (data.is_secret) {
return { value: null, isSecret: true };
}
const decryptedValue = await decrypt(data.encrypted_value, projectId);
const decryptedValue = await decryptWithDerivedKey(
data.encrypted_value,
projectId,
);
return { value: decryptedValue, isSecret: false };
}

Expand Down Expand Up @@ -145,7 +192,7 @@ export async function getAllEnvVars(projectId: string): Promise<EnvVar[]> {
name: item.name,
value: item.is_secret
? '********'
: await decrypt(item.encrypted_value, projectId),
: await decryptWithDerivedKey(item.encrypted_value, projectId),
is_secret: item.is_secret,
updated_at: item.updated_at,
};
Expand Down

0 comments on commit 11beb09

Please sign in to comment.