Skip to content

Commit

Permalink
fix: support decrypting strings larger than 4 MiB (#123)
Browse files Browse the repository at this point in the history
The `cloakedStringRegex` regex fails on ciphertexts larger than 4 MiB.
The new `parseCloakedString` in [`@47ng/cloak@1.2.0`][1] doesn't have
this limitation.

[1]: https://github.com/47ng/cloak/releases/tag/v1.2.0

Fixes: #122
  • Loading branch information
aloisklink authored Sep 24, 2024
1 parent c17354c commit 8380200
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"migrate": "ts-node ./src/tests/migrate.ts"
},
"dependencies": {
"@47ng/cloak": "^1.1.0",
"@47ng/cloak": "^1.2.0",
"@prisma/generator-helper": "^5.9.1",
"debug": "^4.3.4",
"immer": "^10.0.3",
Expand Down
4 changes: 2 additions & 2 deletions src/encryption.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {
cloakedStringRegex,
CloakKeychain,
decryptStringSync,
encryptStringSync,
findKeyForMessage,
makeKeychainSync,
ParsedCloakKey,
parseCloakedString,
parseKeySync
} from '@47ng/cloak'
import { Draft, produce } from 'immer'
Expand Down Expand Up @@ -176,7 +176,7 @@ export function decryptOnRead<Models extends string, Actions extends string>(
field
}) {
try {
if (!cloakedStringRegex.test(cipherText)) {
if (!parseCloakedString(cipherText)) {
return
}
const decryptionKey = findKeyForMessage(cipherText, keys.keychain)
Expand Down
33 changes: 33 additions & 0 deletions src/tests/integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { cloakedStringRegex } from '@47ng/cloak'
import { createHash } from 'node:crypto'
import fs from 'node:fs/promises'
import path from 'node:path'
import { errors } from '../errors'
Expand Down Expand Up @@ -453,4 +454,36 @@ describe.each(clients)('integration ($type)', ({ client }) => {
expect(received!.name).toEqual(' François') // clear text in returned value
expect(received!.email).toEqual(normalizeTestEmail)
})

test('query field with 4 MiB+ data', async () => {
const longNameUser = {
name: 'a'.repeat(4_194_304),
email: 'mr-4MiB-name@example.test'
} as const
await client.user.upsert({
where: {
email: longNameUser.email
},
create: longNameUser,
update: longNameUser
})
const savedUser = await client.user.findUniqueOrThrow({
where: {
email: longNameUser.email
}
})
expect(savedUser.email).toStrictEqual(longNameUser.email)
// The encrypted field is larger than the unencrypted field, so just comparing
// the lengths is fine.
expect(savedUser.name?.length).toStrictEqual(longNameUser.name.length)
// Don't test for equality, otherwise we'd fill up the jest log with
// a massive error message if something goes wrong.
expect(
createHash('sha256')
.update(savedUser.name ?? '')
.digest('hex')
).toStrictEqual(
createHash('sha256').update(longNameUser.name).digest('hex')
)
}, 15_000) // storing 4 MiB into the DB is a bit slow
})
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
# yarn lockfile v1


"@47ng/cloak@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@47ng/cloak/-/cloak-1.1.0.tgz#4172ea63287d3c28aef3ac361fbe313d55647204"
integrity sha512-47dVSPgjTiH3Fgt2CATudxJAU7Fv1WjFIo2e4tXG2UcQitqmIGf9GCgv1MnGv8ctNGPAy9gsjHnNujzuZ1bOow==
"@47ng/cloak@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@47ng/cloak/-/cloak-1.2.0.tgz#7d811527b1530ac55196c7e41fc3bb3eb0c0ac82"
integrity sha512-kKufIDIfW7+YdW+m/0PIFR9zsoIan04tCiAoWsvd2e/MsIh4HtU//n/xDk8eNTTl9cN/rI78qd1r2zCP0QB7hw==
dependencies:
"@47ng/codec" "^1.0.1"
"@stablelib/base64" "^1.0.1"
Expand Down

0 comments on commit 8380200

Please sign in to comment.