drizzle-team / drizzle-orm

Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
https://orm.drizzle.team
Apache License 2.0
23.88k stars 596 forks source link

[FEATURE]: A way to encrypt the data that gets stored in the database and decrypt when reading #2098

Open abhay-ramesh opened 6 months ago

abhay-ramesh commented 6 months ago

Describe what you want

I had a use case where i want to encrypt perticular fields that gets stored on the database and if the feature is already there then can someone guide me how can i achive with drizzle

saborrie commented 5 months ago

What about creating a custom column type?

You could try something like this:

const encryptedText = customType<{ data: string }>({
  dataType() {
    return "text";
  },
  fromDriver(value: unknown) {
    return decrypt(
      Buffer.from(value as string, "hex"),
      Buffer.from(process.env.ENCRYPTION_KEY!, "hex")
    ).toString("utf8");
  },
  toDriver(value: string) {
    return encrypt(
      Buffer.from(value, "utf8"),
      Buffer.from(process.env.ENCRYPTION_KEY!, "hex")
    ).toString("hex");
  },
});

export const account = pgTable("account", {
  id: uuid("id").primaryKey(),
  email: encryptedText("email_digest"),
});

And then you can use the answers from here to help you write your encrypt and decrypt methods: https://stackoverflow.com/questions/6953286/how-to-encrypt-data-that-needs-to-be-decrypted-in-node-js

slawton3 commented 4 months ago

Thanks to the above comment, I was able to implement encrypted token storage with CryptoJS

const encryptedText = customType<{ data: string }>({
  dataType() {
    return "text"
  },
  fromDriver(value: unknown) {
    return CryptoJS.AES.decrypt(String(value), env.CRYPTO_SECRET).toString(
      CryptoJS.enc.Utf8
    )
  },
  toDriver(value: string) {
    return CryptoJS.AES.encrypt(value, env.CRYPTO_SECRET).toString()
  },
})
abhay-ramesh commented 4 months ago

Hey, just curious can we get something like this example get added into the docs for common use cases

Thanks to the above comment, I was able to implement encrypted token storage with CryptoJS

const encryptedText = customType<{ data: string }>({
  dataType() {
    return "text"
  },
  fromDriver(value: unknown) {
    return CryptoJS.AES.decrypt(String(value), env.CRYPTO_SECRET).toString(
      CryptoJS.enc.Utf8
    )
  },
  toDriver(value: string) {
    return CryptoJS.AES.encrypt(value, env.CRYPTO_SECRET).toString()
  },
})