aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <sina@snix.ir>2022-02-02 19:55:50 +0000
committerroot <sina@snix.ir>2022-02-02 19:55:50 +0000
commitf464a924ce181f3e02767402e95701ac800d9df8 (patch)
tree4d7747970b322a4a3f414cf03aad07a9d684770e
fix issue
-rw-r--r--ec_test.go64
-rw-r--r--ecookie.go126
-rw-r--r--go.mod10
-rw-r--r--go.sum12
4 files changed, 212 insertions, 0 deletions
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=

Snix LLC Git Repository Holder Copyright(C) 2022 All Rights Reserved Email To Snix.IR