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

Improve error message when giving the wrong password for a local token #4339

Merged
merged 4 commits into from
Mar 23, 2025

Conversation

scristobal
Copy link
Contributor

Adds a new error variant Error::FailedToDecryptApiKey specifically to handle the case when the decryption of the Hex API token fails.

Hopefully, the changes will make the error message a bit more friendly and possibly more useful.

resolves #4317

Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

It looks like the FailedToDecrypt is no longer used. Let's remove that error variant because of this.

let unencrypted = encryption::decrypt_with_passphrase(encrypted.as_bytes(), &password)?;
let unencrypted = encryption::decrypt_with_passphrase(encrypted.as_bytes(), &password)
.map_err(|e| Error::FailedToDecryptApiKey {
detail: e.to_string(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not call to_string on our error type please.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I modified decrypt_with_passphrase to return a more generic DecryptError

) -> Result<String, DecryptError> {

Unfortunately some extra boilerplate is required as decrypt_with_passphrase can fail in two different ways

// the function `decrypt_with_passphrase` has two possible failure cases:
// - when decryption fails
// - when the data was decrypted succesfully but the result is not UTF-8 valid
#[derive(Error, Debug)]
pub enum DecryptError {
#[error("unable to decrypt message: {0}")]
Decrypt(#[from] age::DecryptError),
#[error("decrypted message is not UTF-8 valid: {0}")]
Io(#[from] std::string::FromUtf8Error),
}

I would love to use thiserror's #[from] macro to automatically convert a DecryptError into a FailedToDecryptApiKey but it is not possible because of Eq and PartialEq derive macros here and those not being implemented by DecryptError variants...

Hence the manual map_err and the .to_string call.


An alternative will be to return directly a FailedToDecryptApiKey from decrypt_with_passphrase instead of a DecryptError.

That approach would be more direct and simple, but also would make decrypt_with_passphrase a bit less flexible.

I would be happy to refactor if you think simplicity is a better trade-off.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!! Thank you!!

@@ -321,6 +321,9 @@ file_names.iter().map(|x| x.as_str()).join(", "))]

#[error("Failed to decrypt data")]
FailedToDecrypt { detail: String },

#[error("Failed to decrypt API key")]
FailedToDecryptApiKey { detail: String },
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be any API key! FailedToDecryptLocalHexApiKey or such? The error attribute needs to say this info also.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified both, the error variant name and the error attribute

#[error("Failed to decrypt local Hex API key")]
FailedToDecryptLocalHexApiKey { detail: String },

@@ -1487,6 +1490,21 @@ The error from the encryption library was:
}]
}

Error::FailedToDecryptApiKey { detail } => {
let text = wrap_format!("Unable to decrypt the local Hex token with the given password.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We call it an API key, not a token 🙏

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified token -> API key

let text = wrap_format!("Unable to decrypt the local Hex API key with the given password.

{detail}"
);
vec![Diagnostic {
title: "Failed to decrypt Hex token".into(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified Hex token -> local Hex API key

title: "Failed to decrypt local Hex API key".into(),

@lpil lpil marked this pull request as draft March 20, 2025 12:29
@scristobal
Copy link
Contributor Author

Thank you!

It looks like the FailedToDecrypt is no longer used. Let's remove that error variant because of this.

I removed that error variant and in exchange introduced DecryptError local to encryption:: decrypt_with_passphrase see my comment here

In a similar fashion, I also went out on a limb and replaced the generic encryption "data" error

#[error("Failed to encrypt data")]
FailedToEncrypt { detail: String },

with a narrower version, similar to FailedToDecryptLocalHexApiKey

#[error("Failed to encrypt local Hex APIT key")]
FailedToEncryptLocalHexApiKey { detail: String },

Let me know what do you think!

Thank you for your patience 🙏🏻

@scristobal scristobal requested a review from lpil March 21, 2025 15:51
@lpil
Copy link
Member

lpil commented Mar 22, 2025

Is this ready for review? Press the button if so! :)

@scristobal scristobal marked this pull request as ready for review March 22, 2025 12:27

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonderful! Thank you very much!

let unencrypted = encryption::decrypt_with_passphrase(encrypted.as_bytes(), &password)?;
let unencrypted = encryption::decrypt_with_passphrase(encrypted.as_bytes(), &password)
.map_err(|e| Error::FailedToDecryptApiKey {
detail: e.to_string(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great!! Thank you!!

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
@lpil lpil enabled auto-merge (rebase) March 22, 2025 19:49
auto-merge was automatically disabled March 22, 2025 19:53

Head branch was pushed to by a user without write access

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
@scristobal scristobal requested a review from lpil March 23, 2025 06:56
@scristobal
Copy link
Contributor Author

@lpil unfortunately I accepted your suggestion before seeing your commit, that invalidated auto-merge. I tried to remove the commit by force pushing, but that didn't help either.

Anyway, hopefully everything is in order now.

Copy link
Member

@lpil lpil left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again!

@lpil lpil merged commit 9bedc27 into gleam-lang:main Mar 23, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unclear error message when giving the wrong password for a local token
2 participants