Skip to content

Instantly share code, notes, and snippets.

@chilts

chilts/ReadMe.md

Last active Oct 18, 2016
Embed
What would you like to do?
"How Dropbox securely stores your passwords" in terrible, insecure, horrible GoLang (GoLang is not terrible, my code is).

+++ WARNING +++

This is just a little test. It should NOT be used for your passwords unless you know what you're doing. I (on the other hand) do NOT know what I'm doing, so please, don't trust this code.

+++ WARNING +++

How Dropbox securely stores your passwords

From : https://blogs.dropbox.com/tech/2016/09/how-dropbox-securely-stores-your-passwords/

The Challenge

All I wanted to do was try and copy what Dropbox did for their passwords, in Go. Whether this is correct or not, I have no idea. It was a coding challenge only.

But ... I'd love it if you could fork this and make it better and more correct. Ping me at @andychilton.

Example Runs

$ go run pw.go 
2016/10/03 22:48:09 Hashed = 6bd54875a5abdc46ab6b871e7271b1174239422f55416965364b76364f61687439485762616f4863545a6b31763734556d6d55715276496267744f53

$ go run pw.go 
2016/10/03 23:01:04 Hashed = 439903360a1292949e1eb7e29d8b9d8d724953655a4344506d446e55754d59435556314962494f6e2f6e664932382f797a71726d71354b6f58494875

$ go run pw.go 
2016/10/03 23:01:07 Hashed = 8955d598ed168fa7e6df501cc30dd80e6a53566d36425955506f4534755667525152574f46674f734d6c3262764d3358416462337743495679426869

Author

Andrew Chilton. (Yes, I know my website is currently not serving on https. Go figure.)

License

I know this is Dropbox's idea but they blogged about it publicly, so I tried it. Everything I've put here is the following license:

(Ends)

package main
import (
"crypto/aes"
"crypto/sha512"
"encoding/hex"
"io"
"log"
"golang.org/x/crypto/bcrypt"
)
// Dropbox performs password hashing, bcrypting, and encryption as described in
// https://blogs.dropbox.com/tech/2016/09/how-dropbox-securely-stores-your-passwords/
func Dropbox(pw string, key []byte) ([]byte, error) {
// SHA512
h := sha512.New()
io.WriteString(h, pw)
sha512Bytes := h.Sum(nil)
// log.Printf("SHA512 = %x\n", sha512Bytes)
// now base64 encode this, since bcrypt stops at null bytes
base64 := hex.EncodeToString(sha512Bytes)
// now bcrypt it
bcryptBytes, err := bcrypt.GenerateFromPassword([]byte(base64), 10)
if err != nil {
return nil, err
}
// log.Printf("bcrypt = %x\n", bcryptBytes)
// AES256
cipher, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
cipher.Encrypt(bcryptBytes, bcryptBytes)
// log.Printf("aes256 = %x\n", bcryptBytes)
// all good
return bcryptBytes, nil
}
func main() {
// This is the silliest password ever, choose something better.
password := "password"
// This is the silliest key ever, choose something better.
// ToDo: I'm not sure if this is of the correct length for AES256?
key := []byte("ABCDEFGHIJKLMNOP")
// hash the password
bytes, err := Dropbox(password, key)
if err != nil {
log.Fatal(err)
}
log.Printf("Hashed = %x\n", bytes)
}
@devd

This comment has been minimized.

Copy link

@devd devd commented Oct 3, 2016

cool!

For ease of elucidation, the blogpost elided a couple of details. We base64 encode the output of SHA512 since bcrypt will stop at a null byte. We also use a versioned encryption scheme to help with key rotation etc. Also, we use an authenticated encryption scheme over plain AES (so something like seal from aes_gcm package is closer to what we do). These might be worth adding here, IMO. thanks!

@chilts

This comment has been minimized.

Copy link
Owner Author

@chilts chilts commented Oct 18, 2016

Cool, thanks @devd. I have base64 encoded the output of the sha512. I'm still grokking a few things related to what you mean by the AES stuff, seal and ars_gcm. :)

I've been thinking about the versioned scheme. I guess it could be something like a type which knows about every scheme you've ever done, and essentially loops through each to check if the password is correct. Also, the same type, if given a password always encodes for the latest version. By version, that not only includes how, but also valid keys too. I dunno ... am just thinking out loud.

@chilts

This comment has been minimized.

Copy link
Owner Author

@chilts chilts commented Oct 18, 2016

And I've been thinking about how to have multiple password schemes and upgrading if needed. Looks like this package does that qutie well : https://godoc.org/gopkg.in/hlandau/passlib.v1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment