Hacker News new | ask | show | jobs
by schmrz 3908 days ago
> [Rust] allows me to realize my vision of a secure password manager which is not possible with Python.

Not trying to debunk this or anything, but could anyone expand on this (eg. what does secure mean in this context)? Has the author written somewhere about his decision (I couldn't find anything)?

4 comments

I love Rust, but it's important to understand what it promises and what it doesn't.

While Rust is considered a "safe" language, I think the term is a little misleading. I prefer "memory-safe." There are plenty of ways to mess up something like a password manager that don't involve failures of memory safety.

Additionally, Rust is only memory-safe to the extent that you do not use unsafe code and that includes the libraries that your project depends on.

That said, I am not qualified to evaluate the security of this project. It may very well be that this password manager is very secure.

In this context, it's also typesafe. A lot of bugs in python can come from mixing up types in cold paths or nulls. Rust doesn't have these issues.
> Additionally, Rust is only memory-safe to the extent that you do not use unsafe code and that includes the libraries that your project depends on.

In much the same way other languages are only memory-safe to the extent that you don't use an FFI (or make sure you're using theme safely). You can trivially segfault CPython with ctypes.

Though unsafe code is probably more common in Rust than native code is in Ruby or Python owing to it being in closer reach and not requiring language switch and great complexity increase in distribution.

  > probably more common
It depends. The idea with unsafe is to wrap it up inside of a library, and expose a safe interface, keeping the surface area as small as possible. So libraries will sometimes use unsafe code, but application code generally doesn't. Cargo, for example, has no unsafe in it. Regex, currently at the top of the benchmarks game, has no unsafe in it, even as a library.
I am not the author, so I don't speak for him, but I feel that I could write much more secure code in Rust than in Python mainly because in Python the onus of making sure everything is okay falls 100% on me. In Rust, the compiler with the type checker and the borrow checker can take a lot of load off my mind.
I am also curious, because this makes very little sense to me. Is the author worried that he'll get pwned when opening random Keepass files he found on the internet?
More likely a page getting swapped out and password remaining somewhere. Indeed, Python doesn't have builtin[1] means to do, say, mlock(2) on str objects, or assure their contents will be zeroed after variable's not used anymore.

[1] upd: besides ctypes, but not sure if we can consider this builtin or not...

My guesses:

- ability to reliably erase memory that held passwords/keys with assurance it wasn't copied accidentally. AFAIK Python doesn't guarantee zeroing of freed memory.

- type safety, error handling enforced by the type system, and race-condition-free concurrency might be an extra assurance.

Can you reliably erase memory? You can't even do that in pure C in a cross platform way currently. I'd be surprised if rust offered this...

http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buf...

Hey,

I'm the author of KeePassC and yes these are the main reasons to write KeePassC new in Rust. I had a private repo with a C implementation, however after a friend pointed me to Rust I decided to give it a try and was immediately fascinated. The reason for the rewrite in Rust is _not_ that I'm unconvinced with the original project.

There are some problems though, as stated in another post, especially with this write_bytes-thing. But I'm working on this.

What makes you think there's a reliable way to zero memory in Rust?
The fact that a systems programming language must have a way to do this, and Rust sort-of has: (it'd be better if it was a stable API though)

https://doc.rust-lang.org/core/intrinsics/fn.volatile_set_me...

I know it's very tricky in presence of an optimizer. The current implementation in KeePassC uses the pointer after memset in Drop, so it might be just lucky (https://github.com/raymontag/rust-keepass/issues/4).

I think you could just use black_box to get around the optimizer:

http://doc.rust-lang.org/1.1.0/test/fn.black_box.html

I've never actually tried it outside of tests, so I don't know if it applies here.

There is no such way in _C_.

C only promises the behavior of the C abstract machine. Data will randomly get spilled from registers into random places on the stack where you may be completely unable to reach them to zeroize them.

All you can do is best effort, in C-- I wouldn't expect rust to be better here.

Is this such a thing:

https://github.com/raymontag/rust-keepass/blob/2b7b701b69541...

    unsafe { ptr::write_bytes(self.encrypted_string.as_ptr() as *mut c_void, 0u8, self.encrypted_string.len()) };

?
Python has ctypes, which allows one to access (almost) any OS-specific API for secured memory storage, like gcry_malloc_secure or CryptProtectMemory.