Use secure_string for more secure Password and SecretKey#328
Use secure_string for more secure Password and SecretKey#328eibrahim95 wants to merge 21 commits into
Conversation
- Updated struct to use SecureString for enhanced security. - Implemented PartialEq and Eq to be able to compare 2 Password instances - Added tests for equality comparison of instances.
…curity - Updated SecretKey struct to use SecureBytes for improved security handling. - Adjusted implementations of PartialEq and Debug to align with SecureBytes. - Implemented serialization for SecretKey since we cannot derive Serialize since SecureBytes doesn't implement it . - Included tests for JSON serialization of SecretKey.
Codecov Report❌ Patch coverage is
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
@seqre What do you think about the miri thing, because that is a blocker for this PR? |
Hey, thanks for your patience! Can you share more details on mocking a syscall for Miri? I didn't know it was possible. Otherwise, I think the only option is to ignore all the failing tests. Which would be kind of a sad thing to do, given how many there are. |
- Refactored Password and SecretKey structs to provide Miri-compatible versions, using String and Box<[u8]> respectively. - Adjusted methods for creating and accessing passwords and secret keys to ensure compatibility with Miri's limitations.
I realize I didn't fully think through the mock idea - it's beyond my current skill level anyway.
I kept a normal implementation for miri, all should be good now, please have a look. |
|
I'm not sure if creating a special implementation just for Miri is the best approach. It forces us to maintain twice as much code. However, getting rid of it would force us to ignore a lot of only partially related tests from Miri testing, which is also not a good end result. I think that for now, we can leave that implementation be, and we can always reassess the situation in the future if it becomes a hassle. Would you agree @m4tx? @eibrahim95, on a side note, please add |
seqre
left a comment
There was a problem hiding this comment.
One last request from me and it should be good in my eyes!
|
Hey Guys, I'm seeing some activity here, although i totally forgot what we we were doing here :D but let me know if i can help. Thanks |
|
Hey @eibrahim95, it's nice to hear from you again! We're going back to all old PRs and trying to get them working and merge them. So far, I've only updated this PR to the newest changes on the |
# Conflicts: # cot/src/common_types.rs
|
Hey @eibrahim95, we finished working on https://github.com/cot-rs/securer-string, so I took the liberty of updating the PR's code to use it. @eibrahim95, @m4tx, and @Kijewski I'd appreciate if you guys could take a peek and see if it's in good shape now! |
|
That's nitpicking from me, feel free to ignore. :) In https://github.com/cot-rs/securer-string/blob/1995c9dc687bd6fc24da8a1e0ba4ae5e51381e75/src/serde.rs#L38, I would not print the underlying error, because some deserializing library might print the password string or parts of it. It could be something simple as "string contains an unescaped apostrophe", which would weaken the user's security at least a tiny bit. Same with the other instances of In https://github.com/cot-rs/securer-string/blob/1995c9dc687bd6fc24da8a1e0ba4ae5e51381e75/src/secure_utils.rs#L6, no error is reported to the caller, which is mostly okay I guess, but if the mlock failed, the munlock call must be skipped. This does not look right to me: https://github.com/cot-rs/securer-string/blob/1995c9dc687bd6fc24da8a1e0ba4ae5e51381e75/src/secure_types/array.rs#L34-L35. The compiler is free to move The If the password length is less than page sized (which is somewhat ensured, as macOS uses 16k pages if I'm not mistaken), and two passwords get allocated in the same page, then dropping one password will munlock the other password. Fixing this problem would be difficult, I think. Either allocate pages manually for every password or have some sort of arena that stores all passwords. I hate the latter option, though, because that arena would be treasure chest for any evil-doer . |
|
Thanks @Kijewski, I appreciate your review a lot! I've made a PR with the first 4 fixes and left the last point as an issue in the repo to handle at some other time as it's a bit harder to tackle right away. |
m4tx
left a comment
There was a problem hiding this comment.
A couple minor things still, but with the securer-string almost in place, we should be able to merge this very soon!
| } | ||
| } | ||
|
|
||
| impl Debug for Password { |
There was a problem hiding this comment.
Do we still need/want this if SecureString hides the content in the debug impl anyway? Same for other types (such as SecretKey).
There was a problem hiding this comment.
I'd say yes, because then instead of Password(..) you'll get Password(SecureString { .. }) if you just do plain #[derive(Debug)].
| /// where the security tradeoff is understood, e.g., when you're creating a | ||
| /// user registration form with the "retype your password" field, where both | ||
| /// passwords come from the same source anyway. | ||
| /// 2. An alternative is to compare 2 instances of the [`Password`] type |
There was a problem hiding this comment.
Now this sounds like option 2 and 1 are essentially the same. It feels like we should explain in more detail the differences between the two - e.g. the first calculates hashes of passwords and compares that, making it computationally expensive and very difficult to make any timing attacks, vs. just comparing the passwords with constant-time comparison which can still leak the length of the password. I don't know how to put this in words in a short way.
This implements #47
cot::common_types::Passwordstruct to use SecureString for enhanced security.cot::common_types::Passwordto be able to compare 2 Password instances