Recently I've been setting up libsodium
in one of my projects by using cgo, in order to use the crypto_pwhash_str
and crypto_pwhash_str_verify
functions.
This has all gone very smoothly and I now have a small collection of functions that receive a []byte
in the form of a plain-text password and either hash it, or compare it against another []byte
to verify it.
My reason for using a []byte
instead of a string
is because, from what I've learnt so far about Go, I can at least loop over the plain-text password and zero all of the bytes, or even pass a pointer into libsodium
's sodium_memzero
function, in order to not leave it hanging around in memory longer than it needs to.
This is fine for applications where I have the ability to read input directly as bytes, but I'm now trying to use it in a small web application where I need to read passwords from a form using the POST
method.
From what I can see in the Go source code and documentation, using r.ParseForm
in a request handler will parse all of the form values into a map
of string
s.
The problem is that because string
s in Go are immutable I don't think I can do anything about zeroing the memory of a password that was POST
ed in the form; at least, using only Go.
So it seems like my only (easy) option would be to pass an unsafe.Pointer
into a function in C along with the number of bytes and let C zero the memory for me instead (for example, passing it to the aforementioned sodium_memzero
function).
I have tried this, and unsurprisingly it does of course work, but then I'm left with an unsafe string
in Go, which, if used in a function like fmt.Println
will crash the program.
My questions are as follows:
- Should I just accept that passwords will be
POST
ed and parsed as strings and that I shouldn't mess with it and just wait for the GC to kick in? (not ideal) - Is zeroing the memory of a
string
using cgo ok, provided it's obviously documented in the code that the string variable should not be used again? - Will zeroing the memory of a
string
using cgo ever do something like crashing the GC? - Is it worth writing a sort of decorator for
http.Request
that adds a function to parse form values directly as[]byte
so I have complete control over the values when they arrive?
Edit: To clarify, the web app and form POST
is just a convenient example of a case where I might be handed sensitive data just from using Go's standard library in the form of a string
. I'm more just interested in whether all of my questions are possible/worthwhile in some case were cleaning up data in memory as quickly as possible was more of a security concern.