Skip to content

Commit 3c59ddd

Browse files
refactor: jwt encryption without vault (#1000)
1 parent da4eca5 commit 3c59ddd

File tree

2 files changed

+22
-14
lines changed

2 files changed

+22
-14
lines changed

src/daos/AccountDao.ts

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface AccountDao {
1616
}
1717

1818
export const AccountDao = (collection: Collection, encryptionKey: string): AccountDao => {
19+
const encryptWithKey = encrypt(encryptionKey)
1920
const modelToEncryptedDocument = asyncPipe(encryptAccount(encryptionKey), modelToDocument)
2021
const documentToDecryptedModel = asyncPipe(documentToModel, decryptAccount(encryptionKey))
2122

@@ -44,7 +45,7 @@ export const AccountDao = (collection: Collection, encryptionKey: string): Accou
4445
const insertToken = async (filter: Partial<Account>, network: Network, token: string): Promise<void> => {
4546
const filterDocument = await modelToEncryptedDocument(filter)
4647
const array = network === Network.LIVE ? 'apiTokens' : 'testApiTokens'
47-
const apiTokenEncrypted = await Vault.encrypt(token)
48+
const apiTokenEncrypted = encryptWithKey(token)
4849
await collection.updateOne(filterDocument, { $push: { [array]: { token: apiTokenEncrypted } }})
4950
}
5051

@@ -89,9 +90,14 @@ const modelToDocument = (model: Partial<Account>): Partial<AccountDocument> => {
8990
}
9091

9192
const encryptAccount = (encryptionKey: string) => async (account: Partial<Account>): Promise<Partial<Account>> => {
93+
const encryptWithKey = encrypt(encryptionKey)
94+
95+
const encryptApiTokens = async (tokens: ReadonlyArray<Token>): Promise<ReadonlyArray<Token>> =>
96+
tokens.map(tokenObjectToToken).map(encryptWithKey).map(tokenToTokenObject)
97+
9298
const encryptedAccount = {
9399
...account,
94-
privateKey: account.privateKey && encrypt(account.privateKey, encryptionKey),
100+
privateKey: account.privateKey && encryptWithKey(account.privateKey),
95101
apiTokens: account.apiTokens && await encryptApiTokens(account.apiTokens),
96102
testApiTokens: account.testApiTokens && await encryptApiTokens(account.testApiTokens),
97103
}
@@ -107,9 +113,14 @@ const encryptAccount = (encryptionKey: string) => async (account: Partial<Accoun
107113
}
108114

109115
const decryptAccount = (decryptionKey: string) => async (account: Partial<Account>): Promise<Partial<Account>> => {
116+
const decrypt = decryptBackwardsCompatible(decryptionKey)
117+
118+
const decryptApiTokens = async (tokens: ReadonlyArray<Token>): Promise<ReadonlyArray<Token>> =>
119+
Promise.all(tokens.map(tokenObjectToToken).map(decrypt)).then(tokensToTokenObjects)
120+
110121
const decryptedAccount = {
111122
...account,
112-
privateKey: account.privateKey && decrypt(account.privateKey, decryptionKey),
123+
privateKey: account.privateKey && await decrypt(account.privateKey),
113124
apiTokens: account.apiTokens && await decryptApiTokens(account.apiTokens),
114125
testApiTokens: account.testApiTokens && await decryptApiTokens(account.testApiTokens),
115126
}
@@ -124,17 +135,14 @@ const decryptAccount = (decryptionKey: string) => async (account: Partial<Accoun
124135
return decryptedAccount
125136
}
126137

127-
const encryptApiTokens = async (tokens: ReadonlyArray<Token>): Promise<ReadonlyArray<Token>> => {
128-
const allTokens = tokens.map(({ token }) => token).map(Vault.encrypt, Vault)
129-
const encryptedTokens = await Promise.all(allTokens)
130-
return encryptedTokens.map(token => ({ token }))
131-
}
138+
const tokenToTokenObject = (token: string): Token => ({ token })
139+
const tokenObjectToToken = ({ token }: Token): string => token
140+
const tokensToTokenObjects = (tokens: ReadonlyArray<string>): ReadonlyArray<Token> => tokens.map(tokenToTokenObject)
132141

133-
const decryptApiTokens = async (tokens: ReadonlyArray<Token>): Promise<ReadonlyArray<Token>> => {
134-
const allTokens = tokens.map(({ token }) => token).map(Vault.decrypt, Vault)
135-
const decryptedTokens = await Promise.all(allTokens)
136-
return decryptedTokens.map(token => ({ token }))
137-
}
142+
const decryptBackwardsCompatible = (key: string) => (plaintext: string) =>
143+
plaintext.startsWith('vault')
144+
? Vault.decrypt(plaintext)
145+
: decrypt(plaintext, key)
138146

139147
interface AccountDocument {
140148
readonly id?: Buffer | Binary

src/helpers/crypto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { createCipheriv, createDecipheriv, randomBytes } from 'crypto'
33
const algorithm = 'id-aes256-GCM'
44
const ivLengthInBytes = 96
55

6-
export const encrypt = (text: string, key: string): string => {
6+
export const encrypt = (key: string) => (text: string): string => {
77
const iv = randomBytes(ivLengthInBytes)
88
const cipher = createCipheriv(algorithm, Buffer.from(key, 'hex'), iv)
99
const ciphertext = cipher.update(text, 'utf8', 'hex') + cipher.final('hex')

0 commit comments

Comments
 (0)