From cd6f888802f217ca0cd0509a999696f6c4235c20 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Mon, 17 Jul 2017 23:55:23 +0200 Subject: Refactor ask --- ask/ask.go | 41 +++++++++++++++++++++++++++++------ generate.go | 14 ++++++------ kdf.go | 22 ------------------- key/key.go | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++----------- sign.go | 12 +---------- verify.go | 16 +++----------- 6 files changed, 104 insertions(+), 73 deletions(-) delete mode 100644 kdf.go diff --git a/ask/ask.go b/ask/ask.go index 7d87e83..d554d32 100644 --- a/ask/ask.go +++ b/ask/ask.go @@ -6,6 +6,8 @@ import ( "io" "os" + "dim13.org/signify/bhash" + "golang.org/x/crypto/ssh/terminal" ) @@ -14,18 +16,43 @@ var ( ErrNoMatch = errors.New("passwords don't match") ) -// Confirmed asks for password twice -func Confirmed() (string, error) { +const ( + promtPassphrase = "passphrase: " + promtConfirmed = "confirm passphrase: " +) + +type Passphrase struct{} + +func (Passphrase) DeriveKey(salt []byte, rounds int, length int) ([]byte, error) { + pass, err := passphrase() + if err != nil { + return nil, err + } + return bhash.Pbkdf([]byte(pass), salt, rounds, length), nil +} + +type Confirmed struct{} + +func (Confirmed) DeriveKey(salt []byte, rounds int, length int) ([]byte, error) { + pass, err := confirmed() + if err != nil { + return nil, err + } + return bhash.Pbkdf([]byte(pass), salt, rounds, length), nil +} + +// confirmed asks for password twice +func confirmed() (string, error) { restore, err := makeRaw(os.Stdin) if err != nil { return "", err } defer restore() - pass, err := ask(os.Stdin, "passphrase: ") + pass, err := ask(os.Stdin, promtPassphrase) if err != nil { return "", err } - pass2, err := ask(os.Stdin, "confirm passphrase: ") + pass2, err := ask(os.Stdin, promtConfirmed) if err != nil { return "", err } @@ -35,14 +62,14 @@ func Confirmed() (string, error) { return pass, nil } -// Password asks for password once -func Password() (string, error) { +// passphrase asks for passphrase once +func passphrase() (string, error) { restore, err := makeRaw(os.Stdin) if err != nil { return "", err } defer restore() - return ask(os.Stdin, "passphrase: ") + return ask(os.Stdin, promtPassphrase) } func ask(rw io.ReadWriter, prompt string) (string, error) { diff --git a/generate.go b/generate.go index e1406bd..66fe734 100644 --- a/generate.go +++ b/generate.go @@ -27,16 +27,14 @@ func generate(args []string) error { if err := file.CheckNames(*pubFile, *encFile); err != nil { return err } - pubKey, encKey, err := key.NewKey() - if err != nil { - return err - } - askFn := ask.Confirmed - if *nopass { - askFn = nil + var deriver key.KeyDeriver + if !*nopass { + deriver = ask.Confirmed{} } - if err := Kdf(encKey, askFn); err != nil { + + pubKey, encKey, err := key.NewKey(deriver) + if err != nil { return err } diff --git a/kdf.go b/kdf.go deleted file mode 100644 index ad40a1b..0000000 --- a/kdf.go +++ /dev/null @@ -1,22 +0,0 @@ -package main - -import ( - "dim13.org/signify/bhash" - "dim13.org/signify/key" -) - -func Kdf(enc *key.Enc, ask func() (string, error)) error { - if enc.KDFRounds == 0 || ask == nil { - enc.KDFRounds = 0 - return nil - } - pass, err := ask() - if err != nil { - return err - } - xor := bhash.Pbkdf([]byte(pass), enc.Salt[:], int(enc.KDFRounds), len(enc.Key)) - for i := range xor { - enc.Key[i] ^= xor[i] - } - return nil -} diff --git a/key/key.go b/key/key.go index 54e4615..cb1e2b7 100644 --- a/key/key.go +++ b/key/key.go @@ -108,24 +108,72 @@ func Marshal(v interface{}) ([]byte, error) { return buf.Bytes(), nil } -func NewKey() (*Pub, *Enc, error) { - pub, sec, err := ed25519.GenerateKey(rand.Reader) +func ParseSig(data []byte) (*Sig, error) { + var sig *Sig + if err := Unmarshal(data, sig); err != nil { + return nil, err + } + return sig, sig.Check() +} + +func ParsePub(data []byte) (*Pub, error) { + var pub *Pub + if err := Unmarshal(data, pub); err != nil { + return nil, err + } + return pub, pub.Check() +} + +func ParseEnc(data []byte, d KeyDeriver) (*Enc, error) { + var enc *Enc + if err := Unmarshal(data, enc); err != nil { + return nil, err + } + if d != nil && enc.KDFRounds > 0 { + xor, err := d.DeriveKey(enc.Salt[:], int(enc.KDFRounds), len(enc.Key)) + if err != nil { + return nil, err + } + for i := range xor { + enc.Key[i] ^= xor[i] + } + } + return enc, enc.Check() +} + +func NewKey(d KeyDeriver) (*Pub, *Enc, error) { + pubKey, encKey, err := ed25519.GenerateKey(rand.Reader) if err != nil { return nil, nil, err } - pubKey := &Pub{PKAlg: pkAlg} - encKey := &Enc{PKAlg: pkAlg, KDFAlg: kdfAlg, KDFRounds: DefaultRounds} + pub := &Pub{PKAlg: pkAlg} + enc := &Enc{PKAlg: pkAlg, KDFAlg: kdfAlg} - copy(pubKey.Key[:], pub) - copy(encKey.Key[:], sec) + copy(pub.Key[:], pubKey) + copy(enc.Key[:], encKey) - checkSum := sha512.Sum512(sec) - copy(encKey.Checksum[:], checkSum[:len(encKey.Checksum)]) + checkSum := sha512.Sum512(encKey) + copy(enc.Checksum[:], checkSum[:len(enc.Checksum)]) - rand.Read(encKey.Salt[:]) - rand.Read(encKey.KeyNum[:]) - pubKey.KeyNum = encKey.KeyNum + rand.Read(enc.Salt[:]) + rand.Read(enc.KeyNum[:]) + pub.KeyNum = enc.KeyNum + + if d != nil { + xor, err := d.DeriveKey(enc.Salt[:], DefaultRounds, len(enc.Key)) + if err != nil { + return nil, nil, err + } + for i := range xor { + enc.Key[i] ^= xor[i] + } + enc.KDFRounds = DefaultRounds + } + + return pub, enc, nil +} - return pubKey, encKey, nil +type KeyDeriver interface { + DeriveKey(salt []byte, rounds int, length int) ([]byte, error) } diff --git a/sign.go b/sign.go index 571ee5a..77c008d 100644 --- a/sign.go +++ b/sign.go @@ -65,15 +65,5 @@ func OpenEnc(fname string) (*key.Enc, error) { if err != nil { return nil, err } - encKey := new(key.Enc) - if err := key.Unmarshal(block.Bytes, encKey); err != nil { - return nil, err - } - if err := Kdf(encKey, ask.Password); err != nil { - return nil, err - } - if err := encKey.Check(); err != nil { - return nil, err - } - return encKey, nil + return key.ParseEnc(block.Bytes, ask.Passphrase{}) } diff --git a/verify.go b/verify.go index b76a8fa..bbfaba7 100644 --- a/verify.go +++ b/verify.go @@ -67,14 +67,7 @@ func OpenPub(fname string) (*key.Pub, error) { if err != nil { return nil, err } - pubKey := new(key.Pub) - if err := key.Unmarshal(block.Bytes, pubKey); err != nil { - return nil, err - } - if err := pubKey.Check(); err != nil { - return nil, err - } - return pubKey, nil + return key.ParsePub(block.Bytes) } func OpenSig(fname string) (*key.Sig, []byte, string, error) { @@ -82,11 +75,8 @@ func OpenSig(fname string) (*key.Sig, []byte, string, error) { if err != nil { return nil, nil, "", err } - sig := new(key.Sig) - if err := key.Unmarshal(block.Bytes, sig); err != nil { - return nil, nil, "", err - } - if err := sig.Check(); err != nil { + sig, err := key.ParseSig(block.Bytes) + if err != nil { return nil, nil, "", err } pubKey, _ := file.PubFile(block.Comment) -- cgit v1.2.3