Private key in RAM

In sn_api there is a function keys_balance_from_sk. It consumes the private key passed; it takes ownership of it. A while ago I found the function problematic to use due to this ‘move semantic’. Sometimes you want to do more things with a value than calling a function once (and thus have the value destroyed).

My first solution was to clone the key. But, this is where it starts to smell. The key can not be cloned easily. SecretKey does not implement Clone. And for good reason.

The idea is that cloning a private key is unsecure due to leaving traces in memory. A few years ago, @madadam introduced secure cloning where the underlying data is actually shared instead of cloned. I’m not sure if the codebase has changed too much for that implementation to be relevant, but I am curious about the possibilities from an API user perspective.

My first suggestion was to change the function to accept the key as reference by making a pull request. But, when I paid closer attention I saw the function actually makes a new copy so it can be passed to another function that also takes ownership. Which instantiates a Client, which also takes ownership.

One question I can’t really answer is whether we should worry about cloning too much at all. Are two copies in memory worse than one? Or three, or four? To use these values they have to live in RAM at some point.

1 Like

Yes, there is also a crate for secure keys. Here is another one too GitHub - stouset/secrets: Secure storage for cryptographic secrets in Rust

A good idea is to not have copy for sure, Arc is also not great. The best thing is to reduce where keys are required. So an object that can sign held by as top level as possible and call methods in that object (that has exclusive ownership of the keys), perhaps?

1 Like

This is also what I came across when inspecting the history of the function. Arc was used and removed so it piqued my interest to investigate further.

1 Like

I came across the issue while I was working on the JS bindings. JS uses garbage collection. One can’t manually destroy values. I bound (wrap) the private key to a JS object, and because of that I could not move/transfer ownership out of JS to the Rust function. This is why I had to fall back to copying the key in a hacky way.

I would think this problem is not really specific to my use case. I can imagine more developers would have problems with moving the private key…

1 Like