diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..0d36f0e --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +ENCRYPTION_KEY=b5df1f760870a9a150bd25bbe665e0753f481210e4d90eeeacff075e6b51d6c6 diff --git a/jest.config.js b/jest.config.js index 41794cf..c619449 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,6 +2,7 @@ module.exports = { preset: 'ts-jest', testEnvironment: 'node', + setupFiles: ["<rootDir>/tests/setup.ts"], moduleNameMapper: { '^@/(.*)$': '<rootDir>/src/$1', }, diff --git a/package-lock.json b/package-lock.json index 3108156..f70b65a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "yubico-validation-server", "version": "0.1.0", "dependencies": { + "cryptr": "^6.3.0", "next": "14.1.0", "react": "^18", "react-dom": "^18", @@ -19,6 +20,7 @@ "@types/react": "^18", "@types/react-dom": "^18", "autoprefixer": "^10.0.1", + "dotenv": "^16.3.2", "eslint": "^8", "eslint-config-next": "14.1.0", "jest": "^29.7.0", @@ -2708,6 +2710,11 @@ "node": ">= 8" } }, + "node_modules/cryptr": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/cryptr/-/cryptr-6.3.0.tgz", + "integrity": "sha512-TA4byAuorT8qooU9H8YJhBwnqD151i1rcauHfJ3Divg6HmukHB2AYMp0hmjv2873J2alr4t15QqC7zAnWFrtfQ==" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -2872,6 +2879,18 @@ "node": ">=6.0.0" } }, + "node_modules/dotenv": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", + "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", diff --git a/package.json b/package.json index 5541f2c..02d05c4 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test": "jest --passWithNoTests" }, "dependencies": { + "cryptr": "^6.3.0", "next": "14.1.0", "react": "^18", "react-dom": "^18", @@ -21,6 +22,7 @@ "@types/react": "^18", "@types/react-dom": "^18", "autoprefixer": "^10.0.1", + "dotenv": "^16.3.2", "eslint": "^8", "eslint-config-next": "14.1.0", "jest": "^29.7.0", diff --git a/src/lib/encryption.ts b/src/lib/encryption.ts new file mode 100644 index 0000000..fdc0f8f --- /dev/null +++ b/src/lib/encryption.ts @@ -0,0 +1,10 @@ +import Cryptr from 'cryptr'; +const cryptr = new Cryptr(process.env.ENCRYPTION_KEY || ''); + +export const encrypt = (string: string): string => { + return cryptr.encrypt(string); +}; + +export const decrypt = (encryptedString: string): string => { + return cryptr.decrypt(encryptedString); +}; diff --git a/tests/lib/encryption.test.ts b/tests/lib/encryption.test.ts new file mode 100644 index 0000000..5a83cba --- /dev/null +++ b/tests/lib/encryption.test.ts @@ -0,0 +1,17 @@ +import { encrypt, decrypt } from '@/lib/encryption'; + +const strings: {plain: string, encrypted: string | null} = { + plain: 'hey', + encrypted: null, +}; + +describe('Encryption module', () => { + it('Must encrypt string', () => { + strings.encrypted = encrypt(strings.plain); + expect(strings.encrypted).not.toBe(strings.plain); + }); + + it('Must decrypt string', () => { + expect(decrypt(strings.encrypted as string)).toBe(strings.plain); + }); +}); diff --git a/tests/setup.ts b/tests/setup.ts new file mode 100644 index 0000000..6e92481 --- /dev/null +++ b/tests/setup.ts @@ -0,0 +1,3 @@ +import dotenv from 'dotenv'; + +dotenv.config({ path: '.env.example' });