Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time



Lock your program's config file


  • Needs security audit, code review.
  • Will most likely have breaking, backwards-incompatible-changes until stable.
  • It is up to your application to retrieve user input and handle hashing.
  • Key size must be 32 bytes. You can use the provided hash package to achieve this.
  • Probably not safe to use yet. Pull requests welcome.


Step One

Create and initialize a config struct with data. You make your own Config type with its own fields.

Sorry, no func or chan fields, limited by json package. (how would you even marshal these?)

type Config struct {
  Interface string,
  Port int,
  Name string,
config := Config{
  Interface: "",
  Port:      8080,
  Name:      "my server",

Step Two


Marshal and encrypt the config struct into a slice of encrypted bytes.

Key needs to be 32 bytes, either generate random 32 bytes (and store as key file somewhere), or hash a password to achieve 32 bytes.

// pick a salt. not []byte{0,4,2,8}.
password := GetUserInput()
hashed := hash.Scrypt([]byte(password), []byte("my salt 010"))

Implement your own Hashing:

keyBytes := Hash(GetUserInput()) // somehow read stdin and hash it, getting 32 byte key
b, err := seconfig.Key(keyBytes)).Marshal(config)

Or, use Padding, probably not good:

b, err := seconfig.Pad("12341234123412341234123412341234").Key(GetUserInput()).Marshal(config)

Step Three


Unmarshal the data into a config struct using Unlock():

myconfig := new(Config)
err := seconfig.Key(keyBytes).Unlock(b, &myconfig)

or, decrypt using Raw():

locked := seconfig.Key(keyBytes).RawLock(b)
unlocked := seconfig.Key(keyBytes).Raw(b)