From eae17147e143094e48050494b2da570f42d21986 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Mon, 1 May 2017 16:57:53 +0200 Subject: Reorder package --- signify/keys.go | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 signify/keys.go (limited to 'signify/keys.go') diff --git a/signify/keys.go b/signify/keys.go new file mode 100644 index 0000000..b489385 --- /dev/null +++ b/signify/keys.go @@ -0,0 +1,148 @@ +package signify + +import ( + "bytes" + "crypto/rand" + "crypto/sha512" + "encoding/binary" + "errors" + + "dim13.org/signify/bhash" + + "golang.org/x/crypto/ed25519" +) + +const DefaultRounds = 42 + +var ( + ErrInvalidPK = errors.New("unsupported format") + ErrInvalidKDF = errors.New("unsupported KDF") + ErrPassphrase = errors.New("incorrect passphrase") + ErrInvalidKey = errors.New("invalid key") + ErrKeyNum = errors.New("verification failed: checked against wrong key") + ErrInvalidSig = errors.New("signature verfication failed") +) + +var ( + pkAlg = [2]byte{'E', 'd'} + kdfAlg = [2]byte{'B', 'K'} +) + +type Sig struct { + PKAlg [2]byte + KeyNum [8]byte + Sig [ed25519.SignatureSize]byte +} + +type PubKey struct { + PKAlg [2]byte + KeyNum [8]byte + PubKey [ed25519.PublicKeySize]byte +} + +type EncKey struct { + PKAlg [2]byte + KDFAlg [2]byte + KDFRounds uint32 + Salt [16]byte + Checksum [8]byte + KeyNum [8]byte + SecKey [ed25519.PrivateKeySize]byte +} + +func (v *Sig) Check() error { + if v.PKAlg != pkAlg { + return ErrInvalidPK + } + return nil +} + +func (v *PubKey) Check() error { + if v.PKAlg != pkAlg { + return ErrInvalidPK + } + return nil +} + +func (v *PubKey) Verify(message []byte, sig *Sig) error { + if v.KeyNum != sig.KeyNum { + return ErrKeyNum + } + if !ed25519.Verify(ed25519.PublicKey(v.PubKey[:]), message, sig.Sig[:]) { + return ErrInvalidSig + } + return nil +} + +func (v *EncKey) Sign(message []byte) *Sig { + sig := &Sig{PKAlg: v.PKAlg, KeyNum: v.KeyNum} + copy(sig.Sig[:], ed25519.Sign(ed25519.PrivateKey(v.SecKey[:]), message)) + return sig +} + +func (v *EncKey) Check() error { + if v.PKAlg != pkAlg { + return ErrInvalidPK + } + if v.KDFAlg != kdfAlg { + return ErrInvalidKDF + } + sum := sha512.Sum512(v.SecKey[:]) + if !bytes.Equal(sum[:len(v.Checksum)], v.Checksum[:]) { + return ErrInvalidKey + } + return nil +} + +func (e *EncKey) Kdf(ask func() (string, error)) error { + if e.KDFRounds == 0 { + return nil + } + pass, err := ask() + if err != nil { + return err + } + xorkey := bhash.Pbkdf([]byte(pass), e.Salt[:], int(e.KDFRounds), len(e.SecKey)) + for i := range xorkey { + e.SecKey[i] ^= xorkey[i] + } + return e.Check() +} + +func Unmarshal(b []byte, v interface{}) error { + buf := bytes.NewReader(b) + if err := binary.Read(buf, binary.BigEndian, v); err != nil { + return err + } + return nil +} + +func Marshal(v interface{}) ([]byte, error) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, v); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func NewKey() (PubKey, EncKey, error) { + pub, sec, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + return PubKey{}, EncKey{}, err + } + + pubKey := PubKey{PKAlg: pkAlg} + encKey := EncKey{PKAlg: pkAlg, KDFAlg: kdfAlg, KDFRounds: DefaultRounds} + + copy(pubKey.PubKey[:], pub) + copy(encKey.SecKey[:], sec) + + checkSum := sha512.Sum512(sec) + copy(encKey.Checksum[:], checkSum[:len(encKey.Checksum)]) + + rand.Read(encKey.Salt[:]) + rand.Read(encKey.KeyNum[:]) + pubKey.KeyNum = encKey.KeyNum + + return pubKey, encKey, nil +} -- cgit v1.2.3