Skip to content

Commit

Permalink
suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
prayanshchh committed Oct 29, 2024
1 parent a0fba68 commit 7ffee91
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 22 deletions.
3 changes: 3 additions & 0 deletions setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,9 @@ export async function redisConfiguration(): Promise<void> {
export async function setEncryptionKey(): Promise<void> {
try {
if (process.env.ENCRYPTION_KEY) {
if (!/^[a-f0-9]{64}$/.test(process.env.ENCRYPTION_KEY)) {
throw new Error("Existing encryption key has invalid format");
}
console.log("\n Encryption Key already present.");
} else {
const encryptionKey = crypto.randomBytes(32).toString("hex");
Expand Down
13 changes: 10 additions & 3 deletions src/models/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,19 @@ userSchema.pre('save', async function (next) {
const decrypted = decryptEmail(this.email).decrypted;
if(!validator.isEmail(decrypted))
{
throw new Error('Invalid email format');
throw new Error(`Invalid email format: ${decrypted}`);
}
// Generate hashedEmail when email changes
const crypto = require('crypto');
this.hashedEmail = crypto
.createHmac("sha256", process.env.HASH_PEPPER)
.update(decrypted.toLowerCase())
.digest("hex");
}
catch(error)
catch(error: unknown)
{
throw new Error('Email validation failed');
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
throw new Error(`Email validation failed: ${errorMessage}`);
}
}
next();
Expand Down
14 changes: 7 additions & 7 deletions src/utilities/encryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ const algorithm = "aes-256-gcm";
const authTagLength = 16;
const authTagHexLength = authTagLength * 2;

const saltLength = 16;
const ivLength = 16;

export function generateRandomIV(): string {
return crypto.randomBytes(saltLength).toString("hex");
return crypto.randomBytes(ivLength).toString("hex");
}

export function encryptEmail(email: string): string {
Expand Down Expand Up @@ -52,8 +52,8 @@ export function decryptEmail(encryptedData: string): {
if (!isValidHex(encryptedHex)) {
throw new Error("Invalid encrypted data: not a hex string");
}
const minLength = saltLength * 2 + authTagHexLength + 2;
const maxLength = saltLength * 2 + authTagHexLength + 1000;
const minLength = ivLength * 2 + authTagHexLength + 2;
const maxLength = ivLength * 2 + authTagHexLength + 1000;
if (encryptedData.length < minLength) {
throw new Error("Invalid encrypted data: input is too short.");
} else if (encryptedData.length > maxLength) {
Expand All @@ -71,10 +71,10 @@ const maxLength = saltLength * 2 + authTagHexLength + 1000;
}

const authTag = Buffer.from(
encryptedData.slice(saltLength * 2, saltLength * 2 + authTagHexLength),
encryptedData.slice(ivLength * 2, ivLength * 2 + authTagHexLength),
"hex",
);
const encrypted = encryptedData.slice(saltLength * 2 + authTagHexLength);
const encrypted = encryptedData.slice(ivLength * 2 + authTagHexLength);

const decipher = crypto.createDecipheriv(
algorithm,
Expand All @@ -90,7 +90,7 @@ const maxLength = saltLength * 2 + authTagHexLength + 1000;
decipher.update(Buffer.from(encrypted, "hex")),
decipher.final(),
]).toString("utf8");
} catch (error) {
} catch {
throw new Error("Decryption failed: invalid data or authentication tag.");
}
return {decrypted};
Expand Down
22 changes: 17 additions & 5 deletions src/utilities/hashEmail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,20 @@ export function hashEmail(email: string) : string {
}

export function compareHashedEmails(a: string, b: string): boolean {
return crypto.timingSafeEqual(
Buffer.from(a, 'hex'),
Buffer.from(b, 'hex')
);
}
if (!a || !b || typeof a !== 'string' || typeof b !== 'string') {
return false;
}

if (!/^[0-9a-f]+$/i.test(a) || !/^[0-9a-f]+$/i.test(b)) {
return false;
}

try {
return crypto.timingSafeEqual(
Buffer.from(a, 'hex'),
Buffer.from(b, 'hex')
);
} catch (error) {
return false;
}
}
16 changes: 9 additions & 7 deletions tests/utilities/hashingModule.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ describe("hashingModule", () => {
});
});

it("should produce diffrent hashes with diffrent HASH_PEPPER values", () => {
const email = "[email protected]"
process.env.HASH_PEPPER = "pepper1";
const hash1 = hashEmail(email);
process.env.HASH_PEPPER = "pepper2";
const hash2 = hashEmail(email);
expect(hash1).not.toEqual(hash2);
it("should produce different hashes with different HASH_PEPPER values", () => {
const email = "[email protected]"
const originalPepper = process.env.HASH_PEPPER;
process.env.HASH_PEPPER = "pepper1";
const hash1 = hashEmail(email);
process.env.HASH_PEPPER = "pepper2";
const hash2 = hashEmail(email);
expect(hash1).not.toEqual(hash2);
process.env.HASH_PEPPER = originalPepper;
})
})
})

0 comments on commit 7ffee91

Please sign in to comment.