Add agent workflows & stuff
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
'use node';
|
||||
|
||||
import {
|
||||
createCipheriv,
|
||||
createDecipheriv,
|
||||
createHash,
|
||||
randomBytes,
|
||||
} from 'node:crypto';
|
||||
import { ConvexError } from 'convex/values';
|
||||
|
||||
const getSecret = () => {
|
||||
const secret =
|
||||
process.env.SPOON_ENCRYPTION_KEY?.trim() ??
|
||||
process.env.INSTANCE_SECRET?.trim();
|
||||
if (!secret) {
|
||||
throw new ConvexError(
|
||||
'SPOON_ENCRYPTION_KEY is not configured. Add it before storing user API keys.',
|
||||
);
|
||||
}
|
||||
return secret;
|
||||
};
|
||||
|
||||
const getKey = () => createHash('sha256').update(getSecret()).digest();
|
||||
|
||||
export const encryptSecret = (plaintext: string) => {
|
||||
const iv = randomBytes(12);
|
||||
const cipher = createCipheriv('aes-256-gcm', getKey(), iv);
|
||||
const ciphertext = Buffer.concat([
|
||||
cipher.update(plaintext, 'utf8'),
|
||||
cipher.final(),
|
||||
]);
|
||||
const tag = cipher.getAuthTag();
|
||||
return [
|
||||
iv.toString('base64url'),
|
||||
tag.toString('base64url'),
|
||||
ciphertext.toString('base64url'),
|
||||
].join('.');
|
||||
};
|
||||
|
||||
export const decryptSecret = (encrypted: string) => {
|
||||
const [ivRaw, tagRaw, ciphertextRaw] = encrypted.split('.');
|
||||
if (!ivRaw || !tagRaw || !ciphertextRaw) {
|
||||
throw new ConvexError('Stored secret has an invalid format.');
|
||||
}
|
||||
const decipher = createDecipheriv(
|
||||
'aes-256-gcm',
|
||||
getKey(),
|
||||
Buffer.from(ivRaw, 'base64url'),
|
||||
);
|
||||
decipher.setAuthTag(Buffer.from(tagRaw, 'base64url'));
|
||||
const plaintext = Buffer.concat([
|
||||
decipher.update(Buffer.from(ciphertextRaw, 'base64url')),
|
||||
decipher.final(),
|
||||
]);
|
||||
return plaintext.toString('utf8');
|
||||
};
|
||||
Reference in New Issue
Block a user