Skip to content

Commit

Permalink
feat: encrypt data
Browse files Browse the repository at this point in the history
  • Loading branch information
phukon committed Mar 14, 2024
1 parent 255998e commit b684293
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 37 deletions.
2 changes: 1 addition & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
"tabWidth": 2,
"semi": true,
"singleQuote": false,
"printWidth": 120
"printWidth": 130
}
48 changes: 31 additions & 17 deletions src/app/api/fetchPosts/route.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import {currentUser } from "@/lib/auth";
import { currentUser } from "@/lib/auth";
import { decryptData } from "@/lib/graph/encryptData";

export async function GET(_: Request): Promise<Response> {
const user = await currentUser()
const user = await currentUser();

if (!user?.email) {
return new Response(JSON.stringify({
message: "Unauthorized",
}), {
status: 401,
});
return new Response(
JSON.stringify({
message: "Unauthorized",
}),
{
status: 401,
}
);
}

// save to cloudflare
const getResponse = await fetch(
`${process.env.WORKER_BASE_URL}?getAllFromUser=${user.email}`,
{
method: "GET",
headers: {
"X-Custom-Auth-Key": `${process.env.SECURITY_KEY}`,
},
const getResponse = await fetch(`${process.env.WORKER_BASE_URL}?getAllFromUser=${user.email}`, {
method: "GET",
headers: {
"X-Custom-Auth-Key": `${process.env.SECURITY_KEY}`,
},
);
});

if (getResponse.status !== 200) {
return new Response("Failed to get", {
Expand All @@ -32,11 +33,24 @@ export async function GET(_: Request): Promise<Response> {

const keys = Object.keys(data);

const values = Object.values(data);
// const values = Object.values(data);

const decryptedValuesArray: any = [];
for (const key in data) {
if (data.hasOwnProperty(key)) {
const encryptedValue = data[key];
const decryptedValue = decryptData({
encryptedData: encryptedValue,
enKey: process.env.ENCRYPTION_KEY!,
initVector: process.env.INITIALIZATION_VECTOR!,
});
decryptedValuesArray.push(decryptedValue);
}
}

// convert to list of [key, value] pairs
const result = keys.map((key, index) => {
return [key, values[index]];
return [key, decryptedValuesArray[index]];
});

return new Response(JSON.stringify(result), {
Expand Down
50 changes: 33 additions & 17 deletions src/app/api/note/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// import { env } from "@/env"; // for edge runtime
import {currentUser } from "@/lib/auth";
import { currentUser } from "@/lib/auth";
import { db } from "@/lib/db";
import { exportContentAsText } from "@/lib/extractText";
import { decryptData, encryptData } from "@/lib/graph/encryptData";

// export const runtime = "edge";

Expand All @@ -25,25 +26,33 @@ export async function POST(req: Request): Promise<Response> {
});
}

const userNote = await db.note.findFirst({where: {
userId: user.id,
id: id
}})
const userNote = await db.note.findFirst({
where: {
userId: user.id,
id: id,
},
});

if (!userNote) {
return new Response('Unauthorized', { status: 401 });
return new Response("Unauthorized", { status: 401 });
}

const ENCRYPTEDDATA = encryptData({
data: data,
enKey: process.env.ENCRYPTION_KEY!,
initVector: process.env.INITIALIZATION_VECTOR!,
});

const key = `${user.email}-${id}`;

/**
* save meta-data to postgress db
* Since I receive an array for words grouped together by a type, we have multiple words per elements.
* Therefore I transform the array to have one word per element and get the word count.
*/
const wordCount = exportContentAsText(data).join(' ').split(/\s+/).length
const wordCount = exportContentAsText(data).join(" ").split(/\s+/).length;

await db.note.update({where: {id: id}, data: {wordCount: wordCount}} )
await db.note.update({ where: { id: id }, data: { wordCount: wordCount } });

// save to cloudflare
const putResponse = await fetch(`${process.env.WORKER_BASE_URL}?key=${key}`, {
Expand All @@ -52,7 +61,7 @@ export async function POST(req: Request): Promise<Response> {
"Content-Type": "application/json",
"X-Custom-Auth-Key": `${process.env.SECURITY_KEY}`,
},
body: JSON.stringify(data),
body: ENCRYPTEDDATA,
});

if (putResponse.status !== 200) {
Expand Down Expand Up @@ -81,13 +90,15 @@ export async function GET(req: Request): Promise<Response> {
});
}

const userNote = await db.note.findFirst({where: {
userId: user.id,
id: id
}})
const userNote = await db.note.findFirst({
where: {
userId: user.id,
id: id,
},
});

if (!userNote) {
return new Response('Unauthorized', { status: 401 });
return new Response("Unauthorized", { status: 401 });
}

const key = `${user.email}-${id}`;
Expand All @@ -106,9 +117,14 @@ export async function GET(req: Request): Promise<Response> {
});
}

const data = await getResponse.json();
const data = await getResponse.text();
const DECRYPTEDDATA = decryptData({
encryptedData: data,
enKey: process.env.ENCRYPTION_KEY!,
initVector: process.env.INITIALIZATION_VECTOR!,
});

return new Response(JSON.stringify(data), {
return new Response(JSON.stringify(DECRYPTEDDATA), {
status: 200,
});
}
Expand All @@ -128,7 +144,7 @@ export async function DELETE(req: Request): Promise<Response> {
});
}

await db.note.delete({where: {id: id}} )
await db.note.delete({ where: { id: id } });

const key = `${user.email}-${id}`;

Expand Down
2 changes: 1 addition & 1 deletion src/components/auth/user-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
// import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import { useCurrentUser } from "@/hooks/use-current-user";
import { LogoutButton } from "@/components/auth/logout-button";
import { SidebarContext } from "../ui/sidebar";
Expand Down
53 changes: 53 additions & 0 deletions src/lib/graph/encryptData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as crypto from "crypto";

export const encryptData = ({ data, enKey, initVector }: { data: any, enKey: string, initVector: string }): string => {
const stringData = JSON.stringify(data);
const algorithm = "aes-256-cbc";
const keyBuffer = Buffer.from(enKey, "hex"); // Convert hex string to buffer
const ivBuffer = Buffer.from(initVector, "hex"); // Convert hex string to buffer

const cipher = crypto.createCipheriv(algorithm, keyBuffer, ivBuffer);
let encryptedData = cipher.update(stringData, "utf-8", "hex");
encryptedData += cipher.final("hex");

return encryptedData;
};

export const decryptData = ({ encryptedData, enKey, initVector }: { encryptedData: string, enKey: string, initVector: string }): string => {
const algorithm = "aes-256-cbc";
const keyBuffer = Buffer.from(enKey, "hex"); // Convert hex string to buffer
const ivBuffer = Buffer.from(initVector, "hex"); // Convert hex string to buffer

const decipher = crypto.createDecipheriv(algorithm, keyBuffer, ivBuffer);
let decryptedData = decipher.update(encryptedData, "hex", "utf-8");
decryptedData += decipher.final("utf-8");

return decryptedData;
};

/**
* Example Usage below
* The key should be 32 bytes or 256 bits in length!!
* Come up with a better approach later.
* ~ Riki
const data = 'Hello, world!';
const key = '16e8632fcd04627647c2bbef1495d6b2c2da8fe37d579708abb00f2ab63586';
const iv = '450fd739c2e540bad33a847aac8c6811';
const encryptedString = encryptData({
data: data,
enKey: key,
initVector: iv,
});
console.log("Encrypted:", encryptedString);
const decryptedString = decryptData({
encryptedData: encryptedString,
enKey: key,
initVector: iv,
});
console.log("Decrypted:", decryptedString);
*/
3 changes: 2 additions & 1 deletion vercel.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"graph": false,
"landing": false,
"trash": false,
"redesign": true
"redesign": true,
"encryption": false
}
},
"crons": [
Expand Down

0 comments on commit b684293

Please sign in to comment.