MCPcopy Create free account
hub / github.com/boringstack-xyz/boringstack / decryptString

Function decryptString

apps/api/src/lib/crypto/aes-gcm.utils.ts:89–137  ·  view source on GitHub ↗
(payload: string)

Source from the content-addressed store, hash-verified

87 * branch.
88 */
89export const decryptString = (payload: string): string => {
90 const parts = payload.split("$");
91
92 if (parts.length !== 4) {
93 throw ApiErrors.internal("Encrypted payload is malformed");
94 }
95
96 const [version, ivB64, ciphertextB64, tagB64] = parts;
97
98 if (version !== CIPHERTEXT_VERSION) {
99 throw ApiErrors.internal(
100 `Unsupported ciphertext version: ${version ?? "<empty>"}`
101 );
102 }
103
104 if (
105 ivB64 === undefined ||
106 ciphertextB64 === undefined ||
107 tagB64 === undefined
108 ) {
109 throw ApiErrors.internal("Encrypted payload is malformed");
110 }
111
112 const iv = Buffer.from(ivB64, "base64");
113 const ciphertext = Buffer.from(ciphertextB64, "base64");
114 const tag = Buffer.from(tagB64, "base64");
115
116 if (iv.length !== AES_GCM_IV_BYTES || tag.length !== AES_GCM_TAG_BYTES) {
117 throw ApiErrors.internal("Encrypted payload has wrong IV or tag length");
118 }
119
120 const key = decodeKey(env.MFA_ENCRYPTION_KEY);
121 const decipher = createDecipheriv(CIPHER_ALGORITHM, key, iv, {
122 authTagLength: AES_GCM_TAG_BYTES,
123 });
124
125 decipher.setAuthTag(tag);
126
127 try {
128 const plaintext = Buffer.concat([
129 decipher.update(ciphertext),
130 decipher.final(),
131 ]);
132
133 return plaintext.toString("utf8");
134 } catch {
135 throw ApiErrors.internal("Failed to decrypt payload");
136 }
137};
138
139/**
140 * Constant-time comparison for two same-length strings. Wraps

Callers 7

verifySetupMethod · 0.90
verifyTotpLoginMethod · 0.90
enrollViaServiceFunction · 0.90
generateTotpForUserFunction · 0.85
enrollMfaFunction · 0.85

Calls 2

decodeKeyFunction · 0.85
updateMethod · 0.80

Tested by 3

enrollViaServiceFunction · 0.72
generateTotpForUserFunction · 0.68
enrollMfaFunction · 0.68