{ "name": "elithrar/simple-scrypt", "version": "0.1.4", "libraries": { "xv": "^1.1.25" }, "title": "simple-scrypt", "branch": "", "style": { "name": "Williamsburg", "componentSet": { "nav": "nav/BasicNav", "header": "header/LightBannerHeader", "article": "article/ReaderArticle", "footer": "footer/BasicFooter" }, "fontFamily": "Montserrat, sans-serif", "heading": { "fontWeight": 600, "letterSpacing": "0.1em" }, "colors": { "text": "#666666", "background": "#fff", "primary": "#0099e0", "secondary": "#ab61ff", "highlight": "#f7b", "muted": "#2b2d70", "border": "#ccd" } }, "content": [ { "component": "nav", "links": [ { "href": "https://github.com/elithrar/simple-scrypt", "text": "GitHub" } ] }, { "component": "header", "heading": "simple-scrypt", "subhead": "A convenience library for generating, comparing and inspecting password hashes using the scrypt KDF in Go.", "children": [ { "component": "ui/TweetButton", "text": "simple-scrypt: A convenience library for generating, comparing and inspecting password hashes using the scrypt KDF in Go.", "url": null }, { "component": "ui/GithubButton", "user": "elithrar", "repo": "simple-scrypt" } ] }, { "component": "article", "metadata": { "source": "github.readme" }, "html": "\n

\n

simple-scrypt provides a convenience wrapper around Go's existing\nscrypt package that makes it easier to\nsecurely derive strong keys ("hash user passwords"). This library allows you to:

\n\n

The API closely mirrors Go's bcrypt\nlibrary in an effort to make it easy to migrate—and because it's an easy to grok\nAPI.

\n

Installation

\n

With a working Go toolchain:

\n
go get -u github.com/elithrar/simple-scrypt

Example

\n

simple-scrypt doesn't try to re-invent the wheel or do anything "special". It\nwraps the scrypt.Key function as thinly as possible, generates a\ncrytographically secure salt for you using Go's crypto/rand package, and\nreturns the derived key with the parameters prepended:

\n
package main\n\nimport(\n    "fmt"\n    "log"\n\n    "github.com/elithrar/simple-scrypt"\n)\n\nfunc main() {\n    // e.g. r.PostFormValue("password")\n    passwordFromForm := "prew8fid9hick6c"\n\n    // Generates a derived key of the form "N$r$p$salt$dk" where N, r and p are defined as per\n    // Colin Percival's scrypt paper: http://www.tarsnap.com/scrypt/scrypt.pdf\n    // scrypt.Defaults (N=16384, r=8, p=1) makes it easy to provide these parameters, and\n    // (should you wish) provide your own values via the scrypt.Params type.\n    hash, err := scrypt.GenerateFromPassword([]byte(passwordFromForm), scrypt.DefaultParams)\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Print the derived key with its parameters prepended.\n    fmt.Printf("%s\\n", hash)\n\n    // Uses the parameters from the existing derived key. Return an error if they don't match.\n    err := scrypt.CompareHashAndPassword(hash, []byte(passwordFromForm))\n    if err != nil {\n        log.Fatal(err)\n    }\n}

Upgrading Parameters

\n

Upgrading derived keys from a set of parameters to a "stronger" set of parameters\nas hardware improves, or as you scale (and move your auth process to separate\nhardware), can be pretty useful. Here's how to do it with simple-scrypt:

\n
func main() {\n    // SCENE: We've successfully authenticated a user, compared their submitted\n    // (cleartext) password against the derived key stored in our database, and\n    // now want to upgrade the parameters (more rounds, more parallelism) to\n    // reflect some shiny new hardware we just purchased. As the user is logging\n    // in, we can retrieve the parameters used to generate their key, and if\n    // they don't match our "new" parameters, we can re-generate the key while\n    // we still have the cleartext password in memory\n    // (e.g. before the HTTP request ends).\n    current, err := scrypt.Cost(hash)\n    if err != nil {\n        log.Fatal(err)\n    }\n\n    // Now to check them against our own Params struct (e.g. using reflect.DeepEquals)\n    // and determine whether we want to generate a new key with our "upgraded" parameters.\n    slower := scrypt.Params{\n        N: 32768,\n        R: 8,\n        P: 2,\n        SaltLen: 16,\n        DKLen: 32,\n    }\n\n    if !reflect.DeepEqual(current, slower) {\n        // Re-generate the key with the slower parameters\n        // here using scrypt.GenerateFromPassword\n    }\n}

Automatically Determining Parameters

\n

Thanks to the work by tgulacsi, you can have simple-scrypt\nautomatically determine the optimal parameters for you (time vs. memory). You should run this once\non program startup, as calibrating parameters can be an expensive operation.

\n
var params scrypt.Params\n\nfunc main() {\n    var err error\n    // 500ms, 64MB of RAM per hash.\n    params, err = scrypt.Calibrate(500*time.Millisecond, 64, Params{})\n    if err != nil {\n        return nil, err\n    }\n\n    ...\n}\n\nfunc RegisterUserHandler(w http.ResponseWriter, r *http.Request) {\n    err := r.ParseForm()\n    if err != nil {\n        http.Error(w, err.Error(), http.StatusBadRequest)\n        return\n    }\n\n    // Make sure you validate: not empty, not too long, etc.\n    email := r.PostFormValue("email")\n    pass := r.PostFormValue("password")\n\n    // Use our calibrated parameters\n    hash, err := scrypt.GenerateFromPassword([]byte(pass), params)\n    if err != nil {\n        http.Error(w, err.Error(), http.StatusBadRequest)\n        return\n    }\n\n    // Save to DB, etc.\n}

Be aware that increasing these, whilst making it harder to brute-force the resulting hash, also\nincreases the risk of a denial-of-service attack against your server. A surge in authenticate\nattempts (even if legitimate!) could consume all available resources.

\n

License

\n

MIT Licensed. See LICENSE file for details.

\n" }, { "component": "footer", "links": [ { "href": "https://github.com/elithrar/simple-scrypt", "text": "GitHub" }, { "href": "https://github.com/elithrar", "text": "elithrar" } ] } ] }