From f464a924ce181f3e02767402e95701ac800d9df8 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 2 Feb 2022 19:55:50 +0000 Subject: fix issue --- ec_test.go | 64 +++++++++++++++++++++++++++++++ ecookie.go | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 10 +++++ go.sum | 12 ++++++ 4 files changed, 212 insertions(+) create mode 100644 ec_test.go create mode 100644 ecookie.go create mode 100644 go.mod create mode 100644 go.sum diff --git a/ec_test.go b/ec_test.go new file mode 100644 index 0000000..b0874c6 --- /dev/null +++ b/ec_test.go @@ -0,0 +1,64 @@ +package ecookie + +import ( + "encoding/json" + "testing" +) + +type test struct { + Foo string + Bar string +} + +const pattr string = "ecookie: --- %v --" + +const ( + foo = "foo string" + bar = "bar string" +) + +var key = []byte{ + 0x11, 0x12, 0x13, 0x14, + 0x11, 0x12, 0x13, 0x14, + 0x11, 0x12, 0x13, 0x14, + 0x11, 0x12, 0x13, 0x14, +} + +func TestEcookie(t *testing.T) { + enc, err := NewEncryptor(key) + if err != nil { + t.Fatal(err) + } + + tx := &test{Foo: foo, Bar: bar} + bx := new(test) + bt, err := json.Marshal(tx) + if err != nil { + t.Fatal(err) + } + + ct, err := enc.Encrypt(bt) + if err != nil { + t.Fatal(err) + } + + t.Logf(pattr, string(ct)) + + dec, err := NewDecryptor(key) + if err != nil { + t.Fatal(err) + } + + pt, err := dec.Decrypt(ct) + if err != nil { + t.Fatal(err) + } + + if err := json.Unmarshal(pt, bx); err != nil { + t.Fatal(err) + } + + if !(*tx == *bx) { + t.Error("error: tx != bx.. test failed") + } +} diff --git a/ecookie.go b/ecookie.go new file mode 100644 index 0000000..767091e --- /dev/null +++ b/ecookie.go @@ -0,0 +1,126 @@ +package ecookie + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "errors" + "io" + + "golang.org/x/crypto/blake2b" + "snix.ir/rabbitio" +) + +var ( + ErrAUTHCOK = errors.New("ecookie: cookie is corrupted") + ErrENDDATA = errors.New("ecookie: cookie length is too short") + ErrNotVlid = errors.New("ecookie: data is not validated") + + ErrBadKlen = errors.New("ecookie: key must be 16 byte len") +) + +const ( + lenhashfnc = 32 + lenkrabbit = 16 + lenivahash = lenhashfnc + lenivforkt + lenivforkt = 8 +) + +type Encryptor struct { + key []byte +} + +type Decryptor struct { + key []byte +} + +func NewEncryptor(key []byte) (*Encryptor, error) { + if len(key) != lenkrabbit { + return nil, ErrBadKlen + } + copyKey := make([]byte, lenkrabbit) + copy(copyKey, key) + return &Encryptor{key: copyKey}, nil +} + +func NewDecryptor(key []byte) (*Decryptor, error) { + if len(key) != lenkrabbit { + return nil, ErrBadKlen + } + copyKey := make([]byte, lenkrabbit) + copy(copyKey, key) + return &Decryptor{key: copyKey}, nil +} + +func randomIVGen() ([]byte, error) { + iv := make([]byte, lenivforkt) + if _, err := rand.Read(iv); err != nil { + return nil, err + } + return iv, nil +} + +func (h *Encryptor) Encrypt(src []byte) ([]byte, error) { + ivx, err := randomIVGen() + if err != nil { + return nil, err + } + + cip, _ := rabbitio.NewCipher(h.key, ivx) + dst := make([]byte, len(src)) + cip.XORKeyStream(dst, src) + hash, err := blake2bHash(multiReader(h.key, ivx, dst)) + if err != nil { + return nil, err + } + + buff := new(bytes.Buffer) + _, err = io.Copy(hex.NewEncoder(buff), multiReader(hash, ivx, dst)) + return buff.Bytes(), err +} + +func multiReader(vs ...[]byte) io.Reader { + + var rds []io.Reader + for _, x := range vs { + r := bytes.NewReader(x) + rds = append(rds, r) + } + + return io.MultiReader(rds...) +} + +func blake2bHash(r io.Reader) ([]byte, error) { + hasher, _ := blake2b.New256(nil) + if _, err := io.Copy(hasher, r); err != nil { + return nil, err + } + return hasher.Sum(nil), nil +} + +func (h *Decryptor) Decrypt(raw []byte) ([]byte, error) { + bf := new(bytes.Buffer) + if _, err := io.Copy(bf, + hex.NewDecoder(bytes.NewReader(raw))); err != nil { + return nil, err + } + + if bf.Len() < lenivahash { + return nil, ErrENDDATA + } + + u := bf.Bytes() + cl, err := blake2bHash(multiReader(h.key, u[lenhashfnc:])) + if err != nil { + return nil, err + } + + if !bytes.Equal(cl, u[:lenhashfnc]) { + return nil, ErrAUTHCOK + } + + cip, _ := rabbitio.NewCipher(h.key, u[lenhashfnc:lenivahash]) + pln := make([]byte, bf.Len()-lenivahash) + cip.XORKeyStream(pln, u[lenivahash:]) + return pln, err +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..610e44a --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module snix.ir/ecookie + +go 1.17 + +require ( + golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 + snix.ir/rabbitio v0.0.0-20220123060014-f8c9838efbd6 +) + +require golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..16e9b2b --- /dev/null +++ b/go.sum @@ -0,0 +1,12 @@ +golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 h1:71vQrMauZZhcTVK6KdYM+rklehEEwb3E+ZhaE5jrPrE= +golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +snix.ir/rabbitio v0.0.0-20220123060014-f8c9838efbd6 h1:LYGzvcaDnb0d6ZGWpG3j0qJjEIseRJaFwLN8gbIZ+Io= +snix.ir/rabbitio v0.0.0-20220123060014-f8c9838efbd6/go.mod h1:fGdJrOtVK0uqEI8x6SBI/NPAAQmtQi/4sjwQPShasEA= -- cgit v1.2.3