From 4865ac3532b1d54cfe99209e5e430182313cc9a9 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 5 Aug 2017 14:58:31 +0200 Subject: kiss --- key/gen.go | 66 +++++++++++++++++++++++++++++++++++++++++++ key/gen_test.go | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ key/key.go | 84 ------------------------------------------------------ key/key_test.go | 88 --------------------------------------------------------- key/pub.go | 26 ++++++++++++++--- key/sec.go | 20 +++++++++++-- key/sig.go | 26 ++++++++++++++--- 7 files changed, 215 insertions(+), 183 deletions(-) create mode 100644 key/gen.go create mode 100644 key/gen_test.go delete mode 100644 key/key.go delete mode 100644 key/key_test.go diff --git a/key/gen.go b/key/gen.go new file mode 100644 index 0000000..39436a1 --- /dev/null +++ b/key/gen.go @@ -0,0 +1,66 @@ +// Package key implements signify key format +package key + +import ( + "crypto/rand" + "crypto/sha512" + "errors" + + "golang.org/x/crypto/ed25519" +) + +const kdfRounds = 42 + +var ( + ErrInvalidPK = errors.New("unsupported format") + ErrInvalidKDF = errors.New("unsupported KDF") + 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'} +) + +// Deriver returns a derived encryption key +type Deriver interface { + Derive(salt []byte, rounds int, length int) ([]byte, error) +} + +// Generate a new key pair +func Generate(der Deriver) (*Pub, *Sec, error) { + pubKey, secKey, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + return nil, nil, err + } + + // secret key + sec := &Sec{PKAlg: pkAlg, KDFAlg: kdfAlg} + copy(sec.Key[:], secKey) + + checkSum := sha512.Sum512(secKey) + copy(sec.Checksum[:], checkSum[:len(sec.Checksum)]) + + if _, err := rand.Read(sec.Salt[:]); err != nil { + return nil, nil, err + } + if _, err := rand.Read(sec.KeyNum[:]); err != nil { + return nil, nil, err + } + + // Pbdkf + if der != nil { + sec.KDFRounds = kdfRounds + } + if err := sec.Crypt(der); err != nil { + return nil, nil, err + } + + // public key + pub := &Pub{PKAlg: pkAlg, KeyNum: sec.KeyNum} + copy(pub.Key[:], pubKey) + + return pub, sec, nil +} diff --git a/key/gen_test.go b/key/gen_test.go new file mode 100644 index 0000000..7f86b4e --- /dev/null +++ b/key/gen_test.go @@ -0,0 +1,88 @@ +package key + +import ( + "bytes" + "encoding" + "encoding/base64" + "testing" +) + +type testInterface interface { + encoding.BinaryUnmarshaler + encoding.BinaryMarshaler + Validate() error +} + +func TestKeys(t *testing.T) { + var testCases = []struct { + caption string + key testInterface + rawValue string + }{ + { + caption: "sig", + key: new(Sig), + rawValue: "RWRbOC0bBf7abaGwGtq45KLDK63tgcF7CO4qTZSlTKCSbZTYlDfFm/DISQ60u+/jEzrk22suvXXAEsxQTe2xUOfV90get1YRGQo=", + }, + { + caption: "pub", + key: new(Pub), + rawValue: "RWRbOC0bBf7abfanaXuTYfCa6+YO69Kxyz8RD5nL/3Ta7umY6iOwnBrG", + }, + { + caption: "sec", + key: new(Sec), + rawValue: "RWRCSwAAAACzJBN2gC5//jVvDiV76rs4m2aKXkljqDpbOC0bBf7abZhV/Zygr6b0KIbSI56JQutwzsQeouxnnHuVTZp3IW4M9qdpe5Nh8Jrr5g7r0rHLPxEPmcv/dNru6ZjqI7CcGsY=", + }, + } + for _, tc := range testCases { + t.Run(tc.caption, func(t *testing.T) { + raw, err := base64.StdEncoding.DecodeString(tc.rawValue) + if err != nil { + t.Fatal(err) + } + if err := tc.key.UnmarshalBinary(raw); err != nil { + t.Fatal(err) + } + if err := tc.key.Validate(); err != nil { + t.Fatal(err) + } + out, err := tc.key.MarshalBinary() + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(raw, out) { + t.Errorf("want %v, got %v", raw, out) + } + }) + } +} + +type mocDeriver struct{} + +func (mocDeriver) Derive(_ []byte, _, length int) ([]byte, error) { + return make([]byte, length), nil +} + +func TestPublic(t *testing.T) { + pub, sec, err := Generate(mocDeriver{}) + if err != nil { + t.Fatal(err) + } + p := sec.Public() + if *p != *pub { + t.Errorf("got %v, want %v", p, pub) + } +} + +func TestSign(t *testing.T) { + pub, sec, err := Generate(mocDeriver{}) + if err != nil { + t.Fatal(err) + } + msg := []byte{} + sig := sec.Sign(msg) + if err := sig.Verify(msg, pub); err != nil { + t.Error(err) + } +} diff --git a/key/key.go b/key/key.go deleted file mode 100644 index 57bf301..0000000 --- a/key/key.go +++ /dev/null @@ -1,84 +0,0 @@ -// Package key implements signify key format -package key - -import ( - "bytes" - "crypto/rand" - "crypto/sha512" - "encoding/binary" - "errors" - - "golang.org/x/crypto/ed25519" -) - -const kdfRounds = 42 - -var ( - ErrInvalidPK = errors.New("unsupported format") - ErrInvalidKDF = errors.New("unsupported KDF") - 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'} -) - -// Deriver returns a derived encryption key -type Deriver interface { - Derive(salt []byte, rounds int, length int) ([]byte, error) -} - -// Generate a new key pair -func Generate(der Deriver) (*Pub, *Sec, error) { - pubKey, secKey, err := ed25519.GenerateKey(rand.Reader) - if err != nil { - return nil, nil, err - } - - // secret key - sec := &Sec{PKAlg: pkAlg, KDFAlg: kdfAlg} - copy(sec.Key[:], secKey) - - checkSum := sha512.Sum512(secKey) - copy(sec.Checksum[:], checkSum[:len(sec.Checksum)]) - - if _, err := rand.Read(sec.Salt[:]); err != nil { - return nil, nil, err - } - if _, err := rand.Read(sec.KeyNum[:]); err != nil { - return nil, nil, err - } - - // Pbdkf - if der != nil { - sec.KDFRounds = kdfRounds - } - if err := sec.Crypt(der); err != nil { - return nil, nil, err - } - - // public key - pub := &Pub{PKAlg: pkAlg, KeyNum: sec.KeyNum} - copy(pub.Key[:], pubKey) - - return pub, sec, nil -} - -func Unmarshal(data []byte, v interface{}) error { - buf := bytes.NewReader(data) - 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 -} diff --git a/key/key_test.go b/key/key_test.go deleted file mode 100644 index 7f86b4e..0000000 --- a/key/key_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package key - -import ( - "bytes" - "encoding" - "encoding/base64" - "testing" -) - -type testInterface interface { - encoding.BinaryUnmarshaler - encoding.BinaryMarshaler - Validate() error -} - -func TestKeys(t *testing.T) { - var testCases = []struct { - caption string - key testInterface - rawValue string - }{ - { - caption: "sig", - key: new(Sig), - rawValue: "RWRbOC0bBf7abaGwGtq45KLDK63tgcF7CO4qTZSlTKCSbZTYlDfFm/DISQ60u+/jEzrk22suvXXAEsxQTe2xUOfV90get1YRGQo=", - }, - { - caption: "pub", - key: new(Pub), - rawValue: "RWRbOC0bBf7abfanaXuTYfCa6+YO69Kxyz8RD5nL/3Ta7umY6iOwnBrG", - }, - { - caption: "sec", - key: new(Sec), - rawValue: "RWRCSwAAAACzJBN2gC5//jVvDiV76rs4m2aKXkljqDpbOC0bBf7abZhV/Zygr6b0KIbSI56JQutwzsQeouxnnHuVTZp3IW4M9qdpe5Nh8Jrr5g7r0rHLPxEPmcv/dNru6ZjqI7CcGsY=", - }, - } - for _, tc := range testCases { - t.Run(tc.caption, func(t *testing.T) { - raw, err := base64.StdEncoding.DecodeString(tc.rawValue) - if err != nil { - t.Fatal(err) - } - if err := tc.key.UnmarshalBinary(raw); err != nil { - t.Fatal(err) - } - if err := tc.key.Validate(); err != nil { - t.Fatal(err) - } - out, err := tc.key.MarshalBinary() - if err != nil { - t.Fatal(err) - } - if !bytes.Equal(raw, out) { - t.Errorf("want %v, got %v", raw, out) - } - }) - } -} - -type mocDeriver struct{} - -func (mocDeriver) Derive(_ []byte, _, length int) ([]byte, error) { - return make([]byte, length), nil -} - -func TestPublic(t *testing.T) { - pub, sec, err := Generate(mocDeriver{}) - if err != nil { - t.Fatal(err) - } - p := sec.Public() - if *p != *pub { - t.Errorf("got %v, want %v", p, pub) - } -} - -func TestSign(t *testing.T) { - pub, sec, err := Generate(mocDeriver{}) - if err != nil { - t.Fatal(err) - } - msg := []byte{} - sig := sec.Sign(msg) - if err := sig.Verify(msg, pub); err != nil { - t.Error(err) - } -} diff --git a/key/pub.go b/key/pub.go index a9e6390..aa23685 100644 --- a/key/pub.go +++ b/key/pub.go @@ -1,6 +1,11 @@ package key -import "golang.org/x/crypto/ed25519" +import ( + "bytes" + "encoding/binary" + + "golang.org/x/crypto/ed25519" +) type Pub struct { PKAlg [2]byte @@ -15,9 +20,6 @@ func (v *Pub) Validate() error { return nil } -func (v *Pub) MarshalBinary() ([]byte, error) { return Marshal(v) } -func (v *Pub) UnmarshalBinary(data []byte) error { return Unmarshal(data, v) } - // NewPub returns a parsed public key func NewPub(data []byte) (*Pub, error) { pub := new(Pub) @@ -26,3 +28,19 @@ func NewPub(data []byte) (*Pub, error) { } return pub, pub.Validate() } + +func (v *Pub) MarshalBinary() ([]byte, error) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, v); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (v *Pub) UnmarshalBinary(data []byte) error { + buf := bytes.NewReader(data) + if err := binary.Read(buf, binary.BigEndian, v); err != nil { + return err + } + return nil +} diff --git a/key/sec.go b/key/sec.go index 6ae8c83..19b0e85 100644 --- a/key/sec.go +++ b/key/sec.go @@ -3,6 +3,7 @@ package key import ( "bytes" "crypto/sha512" + "encoding/binary" "golang.org/x/crypto/ed25519" ) @@ -38,9 +39,6 @@ func (v *Sec) Validate() error { return nil } -func (v *Sec) MarshalBinary() ([]byte, error) { return Marshal(v) } -func (v *Sec) UnmarshalBinary(data []byte) error { return Unmarshal(data, v) } - // Public key of secret key func (v *Sec) Public() *Pub { key := ed25519.PrivateKey(v.Key[:]).Public().(ed25519.PublicKey) @@ -74,3 +72,19 @@ func NewSec(data []byte, der Deriver) (*Sec, error) { } return sec, sec.Validate() } + +func (v *Sec) MarshalBinary() ([]byte, error) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, v); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (v *Sec) UnmarshalBinary(data []byte) error { + buf := bytes.NewReader(data) + if err := binary.Read(buf, binary.BigEndian, v); err != nil { + return err + } + return nil +} diff --git a/key/sig.go b/key/sig.go index 378a0cf..649133e 100644 --- a/key/sig.go +++ b/key/sig.go @@ -1,6 +1,11 @@ package key -import "golang.org/x/crypto/ed25519" +import ( + "bytes" + "encoding/binary" + + "golang.org/x/crypto/ed25519" +) type Sig struct { PKAlg [2]byte @@ -26,9 +31,6 @@ func (v *Sig) Verify(message []byte, pub *Pub) error { return nil } -func (v *Sig) MarshalBinary() ([]byte, error) { return Marshal(v) } -func (v *Sig) UnmarshalBinary(data []byte) error { return Unmarshal(data, v) } - // NewSig return parsed signature func NewSig(data []byte) (*Sig, error) { sig := new(Sig) @@ -37,3 +39,19 @@ func NewSig(data []byte) (*Sig, error) { } return sig, sig.Validate() } + +func (v *Sig) MarshalBinary() ([]byte, error) { + buf := new(bytes.Buffer) + if err := binary.Write(buf, binary.BigEndian, v); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (v *Sig) UnmarshalBinary(data []byte) error { + buf := bytes.NewReader(data) + if err := binary.Read(buf, binary.BigEndian, v); err != nil { + return err + } + return nil +} -- cgit v1.2.3