2
2
mirror of https://github.com/octoleo/restic.git synced 2024-05-31 16:10:49 +00:00

Rework key.go, add Comments

This commit is contained in:
Alexander Neumann 2014-11-15 17:17:24 +01:00
parent 543c2c724c
commit 6003430eb9

45
key.go
View File

@ -20,21 +20,24 @@ import (
) )
var ( var (
ErrUnauthenticated = errors.New("Ciphertext verification failed") // ErrUnauthenticated is returned when ciphertext verification has failed.
ErrNoKeyFound = errors.New("No key could be found") ErrUnauthenticated = errors.New("ciphertext verification failed")
// ErrNoKeyFound is returned when no key for the repository could be decrypted.
ErrNoKeyFound = errors.New("no key could be found")
) )
// TODO: figure out scrypt values on the fly depending on the current // TODO: figure out scrypt values on the fly depending on the current
// hardware. // hardware.
const ( const (
scrypt_N = 65536 scryptN = 65536
scrypt_r = 8 scryptR = 8
scrypt_p = 1 scryptP = 1
scrypt_saltsize = 64 scryptSaltsize = 64
aesKeysize = 32 // for AES256 aesKeysize = 32 // for AES256
hmacKeysize = 32 // for HMAC with SHA256 hmacKeysize = 32 // for HMAC with SHA256
) )
// Key represents an encrypted master key for a repository.
type Key struct { type Key struct {
Created time.Time `json:"created"` Created time.Time `json:"created"`
Username string `json:"username"` Username string `json:"username"`
@ -52,19 +55,22 @@ type Key struct {
master *keys master *keys
} }
// keys is a JSON structure that holds signing and encryption keys.
type keys struct { type keys struct {
Sign []byte Sign []byte
Encrypt []byte Encrypt []byte
} }
// CreateKey initializes a master key in the given backend and encrypts it with
// the password.
func CreateKey(be backend.Server, password string) (*Key, error) { func CreateKey(be backend.Server, password string) (*Key, error) {
// fill meta data about key // fill meta data about key
k := &Key{ k := &Key{
Created: time.Now(), Created: time.Now(),
KDF: "scrypt", KDF: "scrypt",
N: scrypt_N, N: scryptN,
R: scrypt_r, R: scryptR,
P: scrypt_p, P: scryptP,
} }
hn, err := os.Hostname() hn, err := os.Hostname()
@ -78,9 +84,9 @@ func CreateKey(be backend.Server, password string) (*Key, error) {
} }
// generate random salt // generate random salt
k.Salt = make([]byte, scrypt_saltsize) k.Salt = make([]byte, scryptSaltsize)
n, err := rand.Read(k.Salt) n, err := rand.Read(k.Salt)
if n != scrypt_saltsize || err != nil { if n != scryptSaltsize || err != nil {
panic("unable to read enough random bytes for salt") panic("unable to read enough random bytes for salt")
} }
@ -119,6 +125,7 @@ func CreateKey(be backend.Server, password string) (*Key, error) {
return k, nil return k, nil
} }
// OpenKey tries do decrypt the key specified by id with the given password.
func OpenKey(be backend.Server, id backend.ID, password string) (*Key, error) { func OpenKey(be backend.Server, id backend.ID, password string) (*Key, error) {
// extract data from repo // extract data from repo
data, err := be.Get(backend.Key, id) data, err := be.Get(backend.Key, id)
@ -160,6 +167,8 @@ func OpenKey(be backend.Server, id backend.ID, password string) (*Key, error) {
return k, nil return k, nil
} }
// SearchKey tries to decrypt all keys in the backend with the given password.
// If none could be found, ErrNoKeyFound is returned.
func SearchKey(be backend.Server, password string) (*Key, error) { func SearchKey(be backend.Server, password string) (*Key, error) {
// list all keys // list all keys
ids, err := be.List(backend.Key) ids, err := be.List(backend.Key)
@ -187,18 +196,18 @@ func (k *Key) scrypt(password string) (*keys, error) {
} }
keybytes := hmacKeysize + aesKeysize keybytes := hmacKeysize + aesKeysize
scrypt_keys, err := scrypt.Key([]byte(password), k.Salt, k.N, k.R, k.P, keybytes) scryptKeys, err := scrypt.Key([]byte(password), k.Salt, k.N, k.R, k.P, keybytes)
if err != nil { if err != nil {
return nil, fmt.Errorf("error deriving keys from password: %v", err) return nil, fmt.Errorf("error deriving keys from password: %v", err)
} }
if len(scrypt_keys) != keybytes { if len(scryptKeys) != keybytes {
return nil, fmt.Errorf("invalid numbers of bytes expanded from scrypt(): %d", len(scrypt_keys)) return nil, fmt.Errorf("invalid numbers of bytes expanded from scrypt(): %d", len(scryptKeys))
} }
ks := &keys{ ks := &keys{
Encrypt: scrypt_keys[:aesKeysize], Encrypt: scryptKeys[:aesKeysize],
Sign: scrypt_keys[aesKeysize:], Sign: scryptKeys[aesKeysize:],
} }
return ks, nil return ks, nil
} }