diff --git a/backend/src/server/routes/v1/admin-router.ts b/backend/src/server/routes/v1/admin-router.ts index 3f3b58b5e..ea3726c22 100644 --- a/backend/src/server/routes/v1/admin-router.ts +++ b/backend/src/server/routes/v1/admin-router.ts @@ -583,16 +583,7 @@ export const registerAdminRouter = async (server: FastifyZodProvider) => { email: z.string().email().trim(), password: z.string().trim(), firstName: z.string().trim(), - lastName: z.string().trim().optional(), - protectedKey: z.string().trim(), - protectedKeyIV: z.string().trim(), - protectedKeyTag: z.string().trim(), - publicKey: z.string().trim(), - encryptedPrivateKey: z.string().trim(), - encryptedPrivateKeyIV: z.string().trim(), - encryptedPrivateKeyTag: z.string().trim(), - salt: z.string().trim(), - verifier: z.string().trim() + lastName: z.string().trim().optional() }), response: { 200: z.object({ diff --git a/backend/src/services/super-admin/super-admin-service.ts b/backend/src/services/super-admin/super-admin-service.ts index 93ac5cadb..154197155 100644 --- a/backend/src/services/super-admin/super-admin-service.ts +++ b/backend/src/services/super-admin/super-admin-service.ts @@ -11,7 +11,7 @@ import { validateOverrides } from "@app/lib/config/env"; import { crypto } from "@app/lib/crypto/cryptography"; -import { generateUserSrpKeys, getUserPrivateKey } from "@app/lib/crypto/srp"; +import { generateUserSrpKeys } from "@app/lib/crypto/srp"; import { BadRequestError, NotFoundError } from "@app/lib/errors"; import { logger } from "@app/lib/logger"; import { TIdentityDALFactory } from "@app/services/identity/identity-dal"; @@ -465,43 +465,15 @@ export const superAdminServiceFactory = ({ return updatedServerCfg; }; - const adminSignUp = async ({ - lastName, - firstName, - email, - salt, - password, - verifier, - publicKey, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - ip, - userAgent - }: TAdminSignUpDTO) => { + const adminSignUp = async ({ lastName, firstName, email, password, ip, userAgent }: TAdminSignUpDTO) => { const appCfg = getConfig(); const sanitizedEmail = email.trim().toLowerCase(); const existingUser = await userDAL.findOne({ username: sanitizedEmail }); if (existingUser) throw new BadRequestError({ name: "Admin sign up", message: "User already exists" }); - const privateKey = await getUserPrivateKey(password, { - encryptionVersion: 2, - salt, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag - }); - const hashedPassword = await crypto.hashing().createHash(password, appCfg.SALT_ROUNDS); - const { iv, tag, ciphertext, encoding } = crypto.encryption().symmetric().encryptWithRootEncryptionKey(privateKey); const userInfo = await userDAL.transaction(async (tx) => { const newUser = await userDAL.create( { @@ -519,25 +491,13 @@ export const superAdminServiceFactory = ({ ); const userEnc = await userDAL.createUserEncryption( { - salt, encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag, - verifier, userId: newUser.id, - hashedPassword, - serverEncryptedPrivateKey: ciphertext, - serverEncryptedPrivateKeyIV: iv, - serverEncryptedPrivateKeyTag: tag, - serverEncryptedPrivateKeyEncoding: encoding + hashedPassword }, tx ); + return { user: newUser, enc: userEnc }; }); diff --git a/backend/src/services/super-admin/super-admin-types.ts b/backend/src/services/super-admin/super-admin-types.ts index b57a015a4..919b0541c 100644 --- a/backend/src/services/super-admin/super-admin-types.ts +++ b/backend/src/services/super-admin/super-admin-types.ts @@ -3,17 +3,8 @@ import { TEnvConfig } from "@app/lib/config/env"; export type TAdminSignUpDTO = { email: string; password: string; - publicKey: string; - salt: string; lastName?: string; - verifier: string; firstName: string; - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; ip: string; userAgent: string; }; diff --git a/frontend/src/helpers/key.ts b/frontend/src/helpers/key.ts deleted file mode 100644 index c516826f1..000000000 --- a/frontend/src/helpers/key.ts +++ /dev/null @@ -1,84 +0,0 @@ -import Aes256Gcm from "@app/components/utilities/cryptography/aes-256-gcm"; -import { deriveArgonKey } from "@app/components/utilities/cryptography/crypto"; - -/** - * @param {Object} obj - * @param {Number} obj.encryptionVersion - * @param {String} obj.encryptedPrivateKey - * @param {String} obj.iv - * @param {String} obj.tag - * @param {String} obj.password - * @param {String} obj.salt - * @param {String} obj.protectedKey - * @param {String} obj.protectedKeyIV - * @param {String} obj.protectedKeyTag - */ -const decryptPrivateKeyHelper = async ({ - encryptionVersion, - encryptedPrivateKey, - iv, - tag, - password, - salt, - protectedKey, - protectedKeyIV, - protectedKeyTag -}: { - encryptionVersion: number; - encryptedPrivateKey: string; - iv: string; - tag: string; - password: string; - salt: string; - protectedKey?: string; - protectedKeyIV?: string; - protectedKeyTag?: string; -}) => { - let privateKey; - try { - if (encryptionVersion === 1) { - privateKey = Aes256Gcm.decrypt({ - ciphertext: encryptedPrivateKey, - iv, - tag, - secret: password - .slice(0, 32) - .padStart(32 + (password.slice(0, 32).length - new Blob([password]).size), "0") - }); - } else if (encryptionVersion === 2 && protectedKey && protectedKeyIV && protectedKeyTag) { - const derivedKey = await deriveArgonKey({ - password, - salt, - mem: 65536, - time: 3, - parallelism: 1, - hashLen: 32 - }); - - if (!derivedKey) throw new Error("Failed to generate derived key"); - - const key = Aes256Gcm.decrypt({ - ciphertext: protectedKey, - iv: protectedKeyIV, - tag: protectedKeyTag, - secret: Buffer.from(derivedKey.hash) - }); - - // decrypt back the private key - privateKey = Aes256Gcm.decrypt({ - ciphertext: encryptedPrivateKey, - iv, - tag, - secret: Buffer.from(key, "hex") - }); - } else { - throw new Error("Insufficient details to decrypt private key"); - } - } catch { - throw new Error("Failed to decrypt private key"); - } - - return privateKey; -}; - -export { decryptPrivateKeyHelper }; diff --git a/frontend/src/hooks/api/admin/types.ts b/frontend/src/hooks/api/admin/types.ts index fe2cc3eed..aca8b5bb3 100644 --- a/frontend/src/hooks/api/admin/types.ts +++ b/frontend/src/hooks/api/admin/types.ts @@ -74,15 +74,6 @@ export type TCreateAdminUserDTO = { password: string; firstName: string; lastName?: string; - protectedKey: string; - protectedKeyTag: string; - protectedKeyIV: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; - publicKey: string; - verifier: string; - salt: string; }; export type AdminGetOrganizationsFilters = { diff --git a/frontend/src/lib/crypto/index.ts b/frontend/src/lib/crypto/index.ts deleted file mode 100644 index d722b68ea..000000000 --- a/frontend/src/lib/crypto/index.ts +++ /dev/null @@ -1,77 +0,0 @@ -import crypto from "crypto"; - -import jsrp from "jsrp"; - -import Aes256Gcm from "@app/components/utilities/cryptography/aes-256-gcm"; -import { deriveArgonKey, generateKeyPair } from "@app/components/utilities/cryptography/crypto"; - -export const generateUserPassKey = async ( - email: string, - password: string, - fipsEnabled: boolean -) => { - // eslint-disable-next-line new-cap - const client = new jsrp.client(); - - const { publicKey, privateKey } = await generateKeyPair(fipsEnabled); - - await new Promise((resolve) => { - client.init({ username: email, password }, () => resolve(null)); - }); - const { salt, verifier } = await new Promise<{ salt: string; verifier: string }>( - (resolve, reject) => { - client.createVerifier((err, res) => { - if (err) return reject(err); - return resolve(res); - }); - } - ); - - const derivedKey = await deriveArgonKey({ - password, - salt, - mem: 65536, - time: 3, - parallelism: 1, - hashLen: 32 - }); - - if (!derivedKey) throw new Error("Failed to derive key from password"); - - const key = crypto.randomBytes(32); - - // create encrypted private key by encrypting the private - // key with the symmetric key [key] - const { - ciphertext: encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag - } = Aes256Gcm.encrypt({ - text: privateKey, - secret: key - }); - - // create the protected key by encrypting the symmetric key - // [key] with the derived key - const { - ciphertext: protectedKey, - iv: protectedKeyIV, - tag: protectedKeyTag - } = Aes256Gcm.encrypt({ - text: key.toString("hex"), - secret: Buffer.from(derivedKey.hash) - }); - - return { - protectedKey, - protectedKeyTag, - protectedKeyIV, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - publicKey, - verifier, - salt, - privateKey - }; -}; diff --git a/frontend/src/pages/admin/SignUpPage/SignUpPage.tsx b/frontend/src/pages/admin/SignUpPage/SignUpPage.tsx index 19c1537a2..f7f3649ca 100644 --- a/frontend/src/pages/admin/SignUpPage/SignUpPage.tsx +++ b/frontend/src/pages/admin/SignUpPage/SignUpPage.tsx @@ -12,7 +12,6 @@ import SecurityClient from "@app/components/utilities/SecurityClient"; import { Button, ContentLoader, FormControl, Input } from "@app/components/v2"; import { useServerConfig } from "@app/context"; import { useCreateAdminUser, useSelectOrganization } from "@app/hooks/api"; -import { generateUserPassKey } from "@app/lib/crypto"; const formSchema = z .object({ @@ -48,17 +47,11 @@ export const SignUpPage = () => { // avoid multi submission if (isSubmitting) return; try { - const { privateKey, ...userPass } = await generateUserPassKey( - email, - password, - config.fipsEnabled - ); const res = await createAdminUser({ email, password, firstName, - lastName, - ...userPass + lastName }); SecurityClient.setToken(res.token);