(encryptedValue: string)
| 134 | } |
| 135 | |
| 136 | async function decryptSecret(encryptedValue: string): Promise<string> { |
| 137 | const parts = encryptedValue.split(':') |
| 138 | const ivHex = parts[0] |
| 139 | const authTagHex = parts[parts.length - 1] |
| 140 | const encrypted = parts.slice(1, -1).join(':') |
| 141 | |
| 142 | if (!ivHex || !encrypted || !authTagHex) { |
| 143 | throw new Error('Invalid encrypted value format. Expected "iv:encrypted:authTag"') |
| 144 | } |
| 145 | |
| 146 | const key = getEncryptionKeyBuffer() |
| 147 | const iv = Buffer.from(ivHex, 'hex') |
| 148 | const authTag = Buffer.from(authTagHex, 'hex') |
| 149 | |
| 150 | const decipher = createDecipheriv('aes-256-gcm', key, iv, { authTagLength: 16 }) |
| 151 | decipher.setAuthTag(authTag) |
| 152 | |
| 153 | let decrypted = decipher.update(encrypted, 'hex', 'utf8') |
| 154 | decrypted += decipher.final('utf8') |
| 155 | return decrypted |
| 156 | } |
| 157 | |
| 158 | // ---------- Schema ---------- |
| 159 | const workspaceTable = pgTable('workspace', { |
no test coverage detected