Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle backup key error and success feedback #2730

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 68 additions & 70 deletions frontend/src/components/utilities/cryptography/issueBackupKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { issueBackupPrivateKey, srp1 } from "@app/hooks/api/auth/queries";
import generateBackupPDF from "../generateBackupPDF";
import Aes256Gcm from "./aes-256-gcm";

const clientPassword = new jsrp.client();
const clientKey = new jsrp.client();
const ClientPassword = new jsrp.client();
const ClientKey = new jsrp.client();

interface BackupKeyProps {
email: string;
Expand All @@ -20,95 +20,93 @@ interface BackupKeyProps {
}

/**
* This function issue a backup key for a user
* @param {obkect} obj
* This function issues a backup key for a user
* @param {object} obj
* @param {string} obj.email - email of a user issuing a backup key
* @param {string} obj.password - password of a user issuing a backup key
* @param {string} obj.personalName - name of a user issuing a backup key
* @param {function} obj.setBackupKeyError - state function that turns true if there is an erorr with a backup key
* @param {function} obj.setBackupKeyIssued - state function that turns true if a backup key was issued correctly
* @returns
* @param {function} obj.setBackupKeyError - state function to indicate an error
* @param {function} obj.setBackupKeyIssued - state function to indicate success
* @returns {Promise<void>}
*/

const issueBackupKey = async ({
email,
password,
personalName,
setBackupKeyError,
setBackupKeyIssued
}: BackupKeyProps) => {
}: BackupKeyProps): Promise<void> => {
try {
setBackupKeyError(false);
setBackupKeyIssued(false);
clientPassword.init(
{
username: email,
password
},
async () => {
const clientPublicKey = clientPassword.getPublicKey();

let serverPublicKey;
let salt;

ClientPassword.init({ username: email, password }, async () => {
const clientPublicKey = ClientPassword.getPublicKey();

let serverPublicKey: string | undefined;
let salt: string | undefined;

try {
const res = await srp1({ clientPublicKey });
serverPublicKey = res.serverPublicKey;
salt = res.salt;
} catch (err) {
setBackupKeyError(true);
console.error("Error during SRP exchange:", err);
}

ClientPassword.setSalt(salt as string);
ClientPassword.setServerPublicKey(serverPublicKey as string);
const clientProof = ClientPassword.getProof(); // M1

const generatedKey = crypto.randomBytes(16).toString("hex");

ClientKey.init({ username: email, password: generatedKey }, async () => {
try {
const res = await srp1({
clientPublicKey
ClientKey.createVerifier(async (createVerifierErr: any, result: { salt: string; verifier: string }) => {
if (createVerifierErr) {
setBackupKeyError(true);
console.error("Error during verifier creation:", createVerifierErr);
}

const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
text: String(localStorage.getItem("PRIVATE_KEY")),
secret: generatedKey
});

try {
await issueBackupPrivateKey({
encryptedPrivateKey: ciphertext,
iv,
tag,
salt: result.salt,
verifier: result.verifier,
clientProof
});

await generateBackupPDF({
personalName,
personalEmail: email,
generatedKey
});

setBackupKeyIssued(true);
} catch (err) {
setBackupKeyError(true);
console.error("Error issuing backup private key:", err);
}
});
serverPublicKey = res.serverPublicKey;
salt = res.salt;
} catch (err) {
setBackupKeyError(true);
console.log("Wrong current password", err, 1);
console.error("Error creating verifier:", err);
}

clientPassword.setSalt(salt as string);
clientPassword.setServerPublicKey(serverPublicKey as string);
const clientProof = clientPassword.getProof(); // called M1

const generatedKey = crypto.randomBytes(16).toString("hex");

clientKey.init(
{
username: email,
password: generatedKey
},
async () => {
clientKey.createVerifier(
async (err: any, result: { salt: string; verifier: string }) => {
const { ciphertext, iv, tag } = Aes256Gcm.encrypt({
text: String(localStorage.getItem("PRIVATE_KEY")),
secret: generatedKey
});

try {
await issueBackupPrivateKey({
encryptedPrivateKey: ciphertext,
iv,
tag,
salt: result.salt,
verifier: result.verifier,
clientProof
});

generateBackupPDF({
personalName,
personalEmail: email,
generatedKey
});
setBackupKeyIssued(true);
} catch {
setBackupKeyError(true);
}
}
);
}
);
}
);
});
});
} catch (error) {
setBackupKeyError(true);
console.log("Failed to issue a backup key");
console.error("Failed to issue a backup key:", error);
}
return true;
};

export default issueBackupKey;
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ const schema = yup
export type FormData = yup.InferType<typeof schema>;

export const EmergencyKitSection = () => {

const { user } = useUser();
const { reset, control, handleSubmit } = useForm({
defaultValues: {
Expand All @@ -33,17 +32,32 @@ export const EmergencyKitSection = () => {
email: user.email,
password,
personalName: `${user.firstName} ${user.lastName}`,
setBackupKeyError: () => {},
setBackupKeyIssued: () => {}
setBackupKeyError: (value) => {
if (value) {
createNotification({
text: "Failed to download emergency kit",
type: "error"
});
}
},
setBackupKeyIssued: (value) => {
if (value) {
createNotification({
text: "Emergency kit successfully downloaded",
type: "success"
});
}
}
});

reset();
} catch (err) {
console.error(err);
createNotification({
text: "Failed to download emergency kit",
text: "An unexpected error occurred",
type: "error"
});
} finally {
reset();
}
};

Expand Down Expand Up @@ -78,4 +92,4 @@ export const EmergencyKitSection = () => {
</Button>
</form>
);
};
};