diff --git a/client/client.internal.go b/client/client.internal.go index 39295cc..cfe8d10 100644 --- a/client/client.internal.go +++ b/client/client.internal.go @@ -27,7 +27,9 @@ func (c *T) updateConfig() { err = c.fkey.Fetch(c.key) /* (3) On error -> set key to NIL */ - if err != nil { c.key = nil } + if err != nil { + c.key = nil + } /* (4) Create default sync */ c.sync, err = keyset.Create(c.ctx) @@ -36,7 +38,9 @@ func (c *T) updateConfig() { err = c.fsync.Fetch(c.sync) /* (6) On error -> set sync to NIL */ - if err != nil { c.sync = nil } + if err != nil { + c.sync = nil + } /* (7) Exit if all keysets have been fetched */ if c.key != nil && c.sync != nil { @@ -45,7 +49,6 @@ func (c *T) updateConfig() { } - /* (2) If cannot fetch -> create new keysets ---------------------------------------------------------*/ if c.key == nil { @@ -56,16 +59,19 @@ func (c *T) updateConfig() { c.sync, _ = keyset.Create(c.ctx) } - /* (3) Store current value ---------------------------------------------------------*/ /* (1) Store key */ err = c.fkey.Store(c.key) - if err != nil { panic("Cannot store key") } + if err != nil { + panic("Cannot store key") + } /* (2) Store sync */ err = c.fsync.Store(c.sync) - if err != nil { panic("Cannot store sync") } + if err != nil { + panic("Cannot store sync") + } } @@ -81,7 +87,9 @@ func (c *T) migrateKey() { /* (2) Regenerate sync */ c.sync, err = keyset.Create(c.ctx) - if err != nil { panic(err) } + if err != nil { + panic(err) + } /* (3) Store keysets to files */ c.updateConfig() @@ -95,7 +103,9 @@ func (c *T) generateKeyWithConstraints() { /* Get current hash */ keyHash, err := c.key.CurrentHash() - if err != nil { panic(err) } + if err != nil { + panic(err) + } /* Search key one is respects contraints */ for true { @@ -111,19 +121,21 @@ func (c *T) generateKeyWithConstraints() { /* (3) Hash time id */ hashedTimeID, err := scha.Hash(timeIDBytes, 1) - if err != nil { continue } - + if err != nil { + continue + } /* (2) Generate a new sync ---------------------------------------------------------*/ newKey, _ := keyset.Create(c.ctx) - /* (3) Check constraints ---------------------------------------------------------*/ /* (1) Get next hash */ syncHash, err := newKey.CurrentHash() - if err != nil { continue } + if err != nil { + continue + } /* (2) Get x1 */ x1 := make([]byte, scha.HSIZE) @@ -145,18 +157,26 @@ func (c *T) generateKeyWithConstraints() { /* (2) Get time mod difference (first byte) */ timeConstraintValue := x[0]%2 == byte(timeMod) - if DEBUG { fmt.Printf(" %.2x ^ %.2x = %.2x[%d] %% 2 = %d == %d ? %t\n", x1[0], x2[0], x[0], x[0], x[0]%2, timeMod, timeConstraintValue) } + if DEBUG { + fmt.Printf(" %.2x ^ %.2x = %.2x[%d] %% 2 = %d == %d ? %t\n", x1[0], x2[0], x[0], x[0], x[0]%2, timeMod, timeConstraintValue) + } /* (4) Retry if invalid time constraint */ - if !timeConstraintValue { continue } + if !timeConstraintValue { + continue + } /* (5) Get migration mod difference (second byte) */ migrationConstraintValue := x[1]%3 == byte(c.key.MigrationCode()) - if DEBUG { fmt.Printf(" %.2x ^ %.2x = %.2x[%d] %% 3 = %d == %d ? %t\n", x1[1], x2[1], x[1], x[1], x[1]%3, c.key.MigrationCode(), migrationConstraintValue) } + if DEBUG { + fmt.Printf(" %.2x ^ %.2x = %.2x[%d] %% 3 = %d == %d ? %t\n", x1[1], x2[1], x[1], x[1], x[1]%3, c.key.MigrationCode(), migrationConstraintValue) + } /* (6) Retry if invalid time constraint */ - if !migrationConstraintValue { continue } + if !migrationConstraintValue { + continue + } /* (7) Store new sync */ c.sync = newKey @@ -215,7 +235,9 @@ func (c *T) generateRequest(x1 []byte, x2 []byte) error { ---------------------------------------------------------*/ /* (1) Store current hash */ h0, err := c.key.CurrentHash() - if err != nil { return err } + if err != nil { + return err + } /* (2) Copy into next hash (same value) */ h1 := make([]byte, scha.HSIZE) @@ -226,7 +248,9 @@ func (c *T) generateRequest(x1 []byte, x2 []byte) error { // 2. Else -> use 'sync' if c.key.MigrationCode() > 0 { h1, err = c.sync.CurrentHash() - if err != nil { return err } + if err != nil { + return err + } } /* (5) Manage time id @@ -302,14 +326,18 @@ func (c *T) rescue(y1 []byte, y2 []byte) error { /* (3) Hash timeId */ hashedTimeID, err := scha.Hash(timeIDBytes, 1) - if err != nil { return err } + if err != nil { + return err + } /* (4) Get the received hash */ receivedHash := xor.ByteArray(y1, hashedTimeID) /* (5) Try to rescue the key */ err = c.key.Rescue(receivedHash) - if err != nil { return err } + if err != nil { + return err + } /* (6) Store updated key */ c.updateConfig() diff --git a/client/config.go b/client/config.go index 5f1e33d..0ec9693 100644 --- a/client/config.go +++ b/client/config.go @@ -1,14 +1,13 @@ -package client; +package client import ( - "git.xdrm.io/logauth/schastsp/internal/keyset" - "fmt" - "path/filepath" "errors" + "fmt" + "git.xdrm.io/logauth/schastsp/internal/keyset" "os" + "path/filepath" ) - type config struct { path string // absolute configuration file path } @@ -21,47 +20,54 @@ type config struct { ---------------------------------------------------------*/ func Config(dir string, name string) (*config, error) { - inst := new(config); + inst := new(config) /* (1) Build full path */ - absoluteDir, err := filepath.Abs(dir); - if err != nil { return nil, err; } - - basename := filepath.Base(name); - fullpath := fmt.Sprintf("%s/%s", absoluteDir, basename); + absoluteDir, err := filepath.Abs(dir) + if err != nil { + return nil, err + } + basename := filepath.Base(name) + fullpath := fmt.Sprintf("%s/%s", absoluteDir, basename) /* (2) Check directory */ if info, err := os.Stat(absoluteDir); err != nil { // Unknown error - if !os.IsNotExist(err) { return nil, err } + if !os.IsNotExist(err) { + return nil, err + } // not exists -> try to create dir - err2 := os.MkdirAll(absoluteDir, 0755); - if err2 != nil { return nil, err2 } + err2 := os.MkdirAll(absoluteDir, 0755) + if err2 != nil { + return nil, err2 + } - // fail if not a directory + // fail if not a directory } else if !info.Mode().IsDir() { - return nil, errors.New("Configuration dir is not a directory"); + return nil, errors.New("Configuration dir is not a directory") } - /* (3) Check file */ - info, err := os.Stat(fullpath); + info, err := os.Stat(fullpath) if err != nil { // Unknown error - if !os.IsNotExist(err) { return nil, err } + if !os.IsNotExist(err) { + return nil, err + } // File does not exist -> try to create file - _, err2 := os.Create(fullpath); - if err2 != nil { return nil, err2 } + _, err2 := os.Create(fullpath) + if err2 != nil { + return nil, err2 + } - - // fail if exists but not regular file + // fail if exists but not regular file } else if !info.Mode().IsRegular() { - return nil, errors.New("Configuration file is not a regular file"); + return nil, errors.New("Configuration file is not a regular file") } inst.path = fullpath @@ -70,7 +76,6 @@ func Config(dir string, name string) (*config, error) { } - /* (2) Fetches a keyset from a file * * @ks<*keyset.T> Set to fetch into @@ -83,20 +88,23 @@ func (c config) Fetch(ks *keyset.T) (err error) { /* (1) Open file */ file, err := os.Open(c.path) - if err != nil { return err } + if err != nil { + return err + } /* (2) Defer close */ defer file.Close() /* (3) Fetch from file */ - err = ks.Fetch(file); - if err != nil { return err } + err = ks.Fetch(file) + if err != nil { + return err + } return nil } - /* (3) Stores a keyset into file * * @ks<*keyset.T> Set to store @@ -108,16 +116,20 @@ func (c config) Fetch(ks *keyset.T) (err error) { func (c config) Store(ks *keyset.T) error { /* (1) Open file */ - file, err := os.OpenFile(c.path, os.O_RDWR|os.O_CREATE, 0755); - if err != nil { return err } + file, err := os.OpenFile(c.path, os.O_RDWR|os.O_CREATE, 0755) + if err != nil { + return err + } /* (2) Defer close */ defer file.Close() /* (3) Store into file */ err = ks.Store(file) - if err != nil { return err } + if err != nil { + return err + } return nil -} \ No newline at end of file +} diff --git a/cmd/server/server.go b/cmd/server/server.go index ca5329d..f06b8bd 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -1,16 +1,16 @@ package main import ( - "git.xdrm.io/logauth/schastsp/internal/scha" - "time" - "os" "flag" "fmt" "git.xdrm.io/logauth/schastsp/context" + "git.xdrm.io/logauth/schastsp/internal/scha" "git.xdrm.io/logauth/schastsp/server" + "os" + "time" ) -func main(){ +func main() { executionStart := time.Now().UnixNano() @@ -37,69 +37,81 @@ func main(){ /* (7) Parse flags */ flag.Parse() - /* (2) Create context + client ---------------------------------------------------------*/ /* (1) Create context */ - ctx, err := context.Create( float64(*winSize) / 1e3, uint16(*minDepth), uint16(*thrDepth), uint16(*maxDepth) ); - if err != nil { os.Stderr.WriteString( fmt.Sprintf("[SERVER_ERROR:context] %s\n", err) ); return } + ctx, err := context.Create(float64(*winSize)/1e3, uint16(*minDepth), uint16(*thrDepth), uint16(*maxDepth)) + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("[SERVER_ERROR:context] %s\n", err)) + return + } /* (2) Create server */ ser, err := server.New(ctx, *serverConfigPath) - if err != nil { os.Stderr.WriteString( fmt.Sprintf("[SERVER_ERROR:server] %s\n", err) ); return } - - + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("[SERVER_ERROR:server] %s\n", err)) + return + } /* (3) Dispatch execution ---------------------------------------------------------*/ /* (1) If synchronisation request */ if *syncRequest { - synchronisationCommit(ser); + synchronisationCommit(ser) - /* (2) If request handling */ + /* (2) If request handling */ } else { err = ser.HandleRequest(os.Stdin, os.Stdout) - if err != nil { os.Stderr.WriteString( fmt.Sprintf("[SERVER_ERROR:request] %s\n", err) ) } + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("[SERVER_ERROR:request] %s\n", err)) + } } - - - - executionStop := time.Now().UnixNano() - nsElapsed := float64(executionStop - executionStart) - usElapsed := float64(nsElapsed / 1e3) - msElapsed := float64(usElapsed / 1e3) - sElapsed := float64(msElapsed / 1e3) + nsElapsed := float64(executionStop - executionStart) + usElapsed := float64(nsElapsed / 1e3) + msElapsed := float64(usElapsed / 1e3) + sElapsed := float64(msElapsed / 1e3) - if sElapsed >= 1 { os.Stderr.WriteString( fmt.Sprintf("executed in %.3f s\n", sElapsed) ) - } else if msElapsed >= 1 { os.Stderr.WriteString( fmt.Sprintf("executed in %.3f ms\n", msElapsed) ) - } else if usElapsed >= 1 { os.Stderr.WriteString( fmt.Sprintf("executed in %.3f us\n", usElapsed) ) - } else if nsElapsed >= 1 { os.Stderr.WriteString( fmt.Sprintf("executed in %.3f ns\n", nsElapsed) ) } + if sElapsed >= 1 { + os.Stderr.WriteString(fmt.Sprintf("executed in %.3f s\n", sElapsed)) + } else if msElapsed >= 1 { + os.Stderr.WriteString(fmt.Sprintf("executed in %.3f ms\n", msElapsed)) + } else if usElapsed >= 1 { + os.Stderr.WriteString(fmt.Sprintf("executed in %.3f us\n", usElapsed)) + } else if nsElapsed >= 1 { + os.Stderr.WriteString(fmt.Sprintf("executed in %.3f ns\n", nsElapsed)) + } return } - - - -func synchronisationCommit(ser *server.T){ +func synchronisationCommit(ser *server.T) { /* (1) Try to read key from standard input */ syncKey := make([]byte, scha.HSIZE) read, err := os.Stdin.Read(syncKey) - if err != nil { os.Stderr.WriteString( fmt.Sprintf("[SERVER_ERROR:syncKey] %s\n", err) ); return } - if uint16(read) != scha.HSIZE { os.Stderr.WriteString( fmt.Sprintf("[SERVER_ERROR:syncKey] Cannot read proper key size\n") ); return } + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("[SERVER_ERROR:syncKey] %s\n", err)) + return + } + if uint16(read) != scha.HSIZE { + os.Stderr.WriteString(fmt.Sprintf("[SERVER_ERROR:syncKey] Cannot read proper key size\n")) + return + } /* (2) Store synchronisation key */ err = ser.SynchronisationKey(syncKey) - if err != nil { os.Stderr.WriteString( fmt.Sprintf("[SERVER_ERROR:syncKey] %s\n", err) ); return } + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("[SERVER_ERROR:syncKey] %s\n", err)) + return + } /* (3) Debug */ os.Stdout.WriteString("Synchronisation key successfully written\n") - return; + return -} \ No newline at end of file +} diff --git a/cmd/simple/simple.go b/cmd/simple/simple.go index d902e93..c0685c5 100644 --- a/cmd/simple/simple.go +++ b/cmd/simple/simple.go @@ -1,41 +1,41 @@ package main import ( - "time" "bytes" - "os" "flag" "fmt" - "git.xdrm.io/logauth/schastsp/context" "git.xdrm.io/logauth/schastsp/client" + "git.xdrm.io/logauth/schastsp/context" "git.xdrm.io/logauth/schastsp/server" + "os" + "time" ) /* Store target config paths */ -var clientConfigPath = "/tmp/cyclichash/client/"; -var serverConfigPath = "/tmp/cyclichash/server/lastkey"; +var clientConfigPath = "/tmp/cyclichash/client/" +var serverConfigPath = "/tmp/cyclichash/server/lastkey" - -func main(){ +func main() { executionStart := time.Now().UnixNano() - /* (1) Create context ---------------------------------------------------------*/ /* (1) Create it */ - ctx, err := context.Create(2, 0x0f0, 0x0a, 0xfff); - if err != nil { fmt.Printf("[ERROR:context] %s\n", err); return } - + ctx, err := context.Create(2, 0x0f0, 0x0a, 0xfff) + if err != nil { + fmt.Printf("[ERROR:context] %s\n", err) + return + } /* (2) Manage flags (cli arguments) ---------------------------------------------------------*/ /* (1) Define 'sync' mode */ - var sync bool; + var sync bool flag.BoolVar(&sync, "sync", false, "If set, a new synchronisation key will be outputed\nNote: it will break existing systems") /* (2) Define connection 'latency' */ - var latency int64; + var latency int64 flag.Int64Var(&latency, "t", 0, "Connection latency in ms") /* (3) Parse cli arguments */ @@ -48,86 +48,106 @@ func main(){ testCommunication(ctx, latency) } - - executionStop := time.Now().UnixNano() - nsElapsed := float64(executionStop - executionStart) - usElapsed := float64(nsElapsed / 1e3) - msElapsed := float64(usElapsed / 1e3) - sElapsed := float64(msElapsed / 1e3) - - if sElapsed >= 1 { fmt.Printf("executed in %.3f s\n", sElapsed) - } else if msElapsed >= 1 { fmt.Printf("executed in %.3f ms\n", msElapsed) - } else if usElapsed >= 1 { fmt.Printf("executed in %.3f us\n", usElapsed) - } else if nsElapsed >= 1 { fmt.Printf("executed in %.3f ns\n", nsElapsed) } + nsElapsed := float64(executionStop - executionStart) + usElapsed := float64(nsElapsed / 1e3) + msElapsed := float64(usElapsed / 1e3) + sElapsed := float64(msElapsed / 1e3) + if sElapsed >= 1 { + fmt.Printf("executed in %.3f s\n", sElapsed) + } else if msElapsed >= 1 { + fmt.Printf("executed in %.3f ms\n", msElapsed) + } else if usElapsed >= 1 { + fmt.Printf("executed in %.3f us\n", usElapsed) + } else if nsElapsed >= 1 { + fmt.Printf("executed in %.3f ns\n", nsElapsed) + } return } - - - -func synchronise(ctx *context.T){ +func synchronise(ctx *context.T) { /* (1) Create client */ - client, err := client.New(ctx, clientConfigPath); - if err != nil { fmt.Printf("[ERROR:client] %s\n", err); return } + client, err := client.New(ctx, clientConfigPath) + if err != nil { + fmt.Printf("[ERROR:client] %s\n", err) + return + } /* (2) Get synchronisation key */ syncKey, err := client.SynchronisationKey() - if err != nil { fmt.Printf("[ERROR:syncKey] %s\n", err); return } + if err != nil { + fmt.Printf("[ERROR:syncKey] %s\n", err) + return + } /* (3) Store synchronisation key */ conf, err := os.OpenFile(serverConfigPath, os.O_RDWR|os.O_CREATE, 0775) - if err != nil { fmt.Printf("[ERROR:syncKey:storage] %s\n", err); return } + if err != nil { + fmt.Printf("[ERROR:syncKey:storage] %s\n", err) + return + } defer conf.Close() conf.Write(syncKey) - fmt.Printf("Synchronisation Key stored\n"); + fmt.Printf("Synchronisation Key stored\n") - return; + return } - -func testCommunication(ctx *context.T, latency int64){ +func testCommunication(ctx *context.T, latency int64) { /* (1) Setup ---------------------------------------------------------*/ /* (1) Create client */ - client, err := client.New(ctx, clientConfigPath); - if err != nil { fmt.Printf("[ERROR:client] %s\n", err); return } + client, err := client.New(ctx, clientConfigPath) + if err != nil { + fmt.Printf("[ERROR:client] %s\n", err) + return + } /* (2) Create server */ server, err := server.New(ctx, serverConfigPath) - if err != nil { fmt.Printf("[ERROR:server] %s\n", err); return } + if err != nil { + fmt.Printf("[ERROR:server] %s\n", err) + return + } /* (3) Create emulation buffers */ requestSocket, responseSocket := new(bytes.Buffer), new(bytes.Buffer) - - /* (2) REAL STUFF HAPPENS HERE ---------------------------------------------------------*/ /* (1) Request | client send */ err = client.Send(requestSocket) - if err != nil { fmt.Printf("[ERROR:request:send] %s\n", err); return } + if err != nil { + fmt.Printf("[ERROR:request:send] %s\n", err) + return + } /* (2) Emulate latency */ - time.Sleep( time.Duration(latency) * time.Second / 1e3) + time.Sleep(time.Duration(latency) * time.Second / 1e3) /* (3) Request | server receive */ /* Response | server send */ err = server.HandleRequest(requestSocket, responseSocket) - if err != nil { fmt.Printf("[ERROR:request:receive] %s\n", err); return } + if err != nil { + fmt.Printf("[ERROR:request:receive] %s\n", err) + return + } /* (4) Response | client receive */ err = client.Receive(responseSocket) - if err != nil { fmt.Printf("[ERROR:response:receive] %s\n", err); return } + if err != nil { + fmt.Printf("[ERROR:response:receive] %s\n", err) + return + } - return; + return -} \ No newline at end of file +} diff --git a/context/context.go b/context/context.go index 221bb9f..dbfb60c 100644 --- a/context/context.go +++ b/context/context.go @@ -11,13 +11,12 @@ const DefaultMin = 0x00f0 const DefaultMax = 0x0fff const DefaultThr = 0x000a - /* (2) Struct attributes */ type T struct { - win float64; // 'timeid' window size - min uint16; // minimum scha depth - max uint16; // maximum scha depth - thr uint16; // scha depth threshold + win float64 // 'timeid' window size + min uint16 // minimum scha depth + max uint16 // maximum scha depth + thr uint16 // scha depth threshold } /* (3) Constructor @@ -30,13 +29,15 @@ type T struct { * @return outName outDesc * ---------------------------------------------------------*/ -func Create(win float64, optional... uint16) (*T, error) { +func Create(win float64, optional ...uint16) (*T, error) { - var inst = new(T); + var inst = new(T) /* (1) Window size error */ - if win < 0 { return nil, errors.New("Window size must be positive and is negative") } - inst.win = win; + if win < 0 { + return nil, errors.New("Window size must be positive and is negative") + } + inst.win = win /* (2) Default values */ inst.min = DefaultMin @@ -49,13 +50,13 @@ func Create(win float64, optional... uint16) (*T, error) { if optional[0] < 0x0f { return nil, errors.New("Minimum depth must be greater than 0x0f (decimal 15) for consistency issues") } - inst.min = optional[0]; + inst.min = optional[0] } /* (4) Optional 'thr' */ if len(optional) > 1 { - inst.thr = optional[1]; + inst.thr = optional[1] } /* (5) Optional 'max' */ @@ -64,7 +65,7 @@ func Create(win float64, optional... uint16) (*T, error) { if optional[2] <= inst.min+inst.thr { return nil, errors.New("Minimum depth must be greater than 0x0f (decimal 15) for consistency issues") } - inst.max = optional[2]; + inst.max = optional[2] } @@ -72,7 +73,7 @@ func Create(win float64, optional... uint16) (*T, error) { } /* (4) Getters */ -func (c T) Window() float64 { return c.win } -func (c T) MinDepth() uint16 { return c.min } -func (c T) MaxDepth() uint16 { return c.max } -func (c T) DepthThreshold() uint16 { return c.thr } \ No newline at end of file +func (c T) Window() float64 { return c.win } +func (c T) MinDepth() uint16 { return c.min } +func (c T) MaxDepth() uint16 { return c.max } +func (c T) DepthThreshold() uint16 { return c.thr } diff --git a/context/context_test.go b/context/context_test.go index 3111f67..e7f8e96 100644 --- a/context/context_test.go +++ b/context/context_test.go @@ -4,14 +4,13 @@ import ( "testing" ) - func TestDefaultArguments(t *testing.T) { - ctx, err := Create(2.2); + ctx, err := Create(2.2) if err != nil { - t.Errorf("[Unexpected error]: %s", err); - return; + t.Errorf("[Unexpected error]: %s", err) + return } // check all optional arguments if ctx.Window() != 2.2 { @@ -38,34 +37,34 @@ func TestDefaultArguments(t *testing.T) { func TestOptionalMinConstraint(t *testing.T) { - ctx, err := Create(2.2, 0x0f); + ctx, err := Create(2.2, 0x0f) if err != nil { - t.Errorf("[Unexpected error]: %s", err); - return; + t.Errorf("[Unexpected error]: %s", err) + return } - ctx, err = Create(2.2, 0x0f-1); + ctx, err = Create(2.2, 0x0f-1) if err == nil { - t.Errorf("Expected an error with 'min' < %d ; got min=%d", 0x0f, ctx.MinDepth()); - return; + t.Errorf("Expected an error with 'min' < %d ; got min=%d", 0x0f, ctx.MinDepth()) + return } } func TestOptionalMaxConstraint(t *testing.T) { - ctx, err := Create(2.2, 0xf1, 0x02, 0xf1+0x02+1); + ctx, err := Create(2.2, 0xf1, 0x02, 0xf1+0x02+1) if err != nil { - t.Errorf("[Unexpected error]: %s", err); - return; + t.Errorf("[Unexpected error]: %s", err) + return } - ctx, err = Create(2.2, 0xf1, 0x02, 0xf1+0x02); + ctx, err = Create(2.2, 0xf1, 0x02, 0xf1+0x02) if err == nil { - t.Errorf("Expected an error with 'max' > 'min'+'thr' ; got max=%d, min=%d, thr=%d", ctx.MinDepth(), ctx.MaxDepth(), ctx.DepthThreshold()); - return; + t.Errorf("Expected an error with 'max' > 'min'+'thr' ; got max=%d, min=%d, thr=%d", ctx.MinDepth(), ctx.MaxDepth(), ctx.DepthThreshold()) + return } -} \ No newline at end of file +} diff --git a/internal/keyset/keyset.internal.go b/internal/keyset/keyset.internal.go index 9991bb1..bedef30 100644 --- a/internal/keyset/keyset.internal.go +++ b/internal/keyset/keyset.internal.go @@ -5,7 +5,6 @@ import ( "time" ) - /* (2) Generates a pseudo-random KeySet * ---------------------------------------------------------*/ @@ -27,7 +26,7 @@ func (s *T) generate() { /* (2) Manage other attributes ---------------------------------------------------------*/ /* (1) Random depth pick init */ - var randMin, randMax = s.ctx.MinDepth() + (s.ctx.MaxDepth()-s.ctx.MinDepth()) / 2, s.ctx.MaxDepth() + var randMin, randMax = s.ctx.MinDepth() + (s.ctx.MaxDepth()-s.ctx.MinDepth())/2, s.ctx.MaxDepth() /* (2) Select "random" depth */ s.depth = randMin + uint16(rand.Intn(int(randMax+1-randMin))) @@ -35,4 +34,4 @@ func (s *T) generate() { /* (3) Reset comsumption level */ s.mcode = 0 -} \ No newline at end of file +} diff --git a/internal/scha/hash.go b/internal/scha/hash.go index fb099b7..a5b44d4 100644 --- a/internal/scha/hash.go +++ b/internal/scha/hash.go @@ -1,19 +1,16 @@ package scha import ( - "errors" "crypto/sha512" + "errors" "git.xdrm.io/logauth/schastsp/internal/xor" ) /* (0) Static ---------------------------------------------------------*/ /* (1) Constants */ -const HSIZE uint16 = sha512.Size; -const HBITSIZE uint32 = uint32(HSIZE) * 8; - - - +const HSIZE uint16 = sha512.Size +const HBITSIZE uint32 = uint32(HSIZE) * 8 /* (1) Basic hash function * @@ -22,23 +19,22 @@ const HBITSIZE uint32 = uint32(HSIZE) * 8; * @return digest<[]byte]> Byte array digest * ---------------------------------------------------------*/ -func hash(input []byte) []byte{ +func hash(input []byte) []byte { /* (1) Create sha512 hasher */ - hasher := sha512.New(); + hasher := sha512.New() /* (2) Defer memory cleanup */ - defer hasher.Reset(); + defer hasher.Reset() /* (3) Set input to be hashed */ - hasher.Write(input); + hasher.Write(input) /* (4) Extract digest */ - return hasher.Sum(nil); + return hasher.Sum(nil) } - /* (2) Public hashing interface * * @input<[]byte> Byte array input @@ -50,32 +46,33 @@ func hash(input []byte) []byte{ * @return err If consistence error * ---------------------------------------------------------*/ -func Hash(input []byte, depth uint16, options... []byte) ([]byte, error) { - +func Hash(input []byte, depth uint16, options ...[]byte) ([]byte, error) { /* (1) Manage errors errors ---------------------------------------------------------*/ /* (1) Avoid no depth (no hash at all) */ - if( depth < 1 ){ - return nil, errors.New("Cannot use a 'depth' of zero. This is inconsistent and means that no hash will be processed"); + if depth < 1 { + return nil, errors.New("Cannot use a 'depth' of zero. This is inconsistent and means that no hash will be processed") } /* (2) Avoir empty input */ - if( len(input) < 1 ){ - return nil, errors.New("Cannot use an empty 'input'. This is inconsistent"); + if len(input) < 1 { + return nil, errors.New("Cannot use an empty 'input'. This is inconsistent") } - /* (2) Extract optional arguments ---------------------------------------------------------*/ /* (1) Optional salt */ salt := make([]byte, 0) - if len(options) > 0 { salt = options[0] } + if len(options) > 0 { + salt = options[0] + } /* (2) Optional pepper */ pepper := make([]byte, 0) - if len(options) > 0 { pepper = options[0] } - + if len(options) > 0 { + pepper = options[0] + } /* (3) Process cyclic hash ---------------------------------------------------------*/ @@ -83,14 +80,14 @@ func Hash(input []byte, depth uint16, options... []byte) ([]byte, error) { digest := make([]byte, 0, HSIZE) /* (2) Process first hash + salt */ - digest = hash( xor.ByteArray(input, salt) ) + digest = hash(xor.ByteArray(input, salt)) /* (3) Iterate @depth times */ for depth--; depth > 0; depth-- { // Add Pepper only for last time - if( depth == 1 ){ - digest = hash( xor.ByteArray(digest, pepper) ) + if depth == 1 { + digest = hash(xor.ByteArray(digest, pepper)) } else { digest = hash(digest) } @@ -98,4 +95,4 @@ func Hash(input []byte, depth uint16, options... []byte) ([]byte, error) { } return digest, nil -} \ No newline at end of file +} diff --git a/internal/scha/hash_test.go b/internal/scha/hash_test.go index 65c50b2..f44bb03 100644 --- a/internal/scha/hash_test.go +++ b/internal/scha/hash_test.go @@ -2,155 +2,147 @@ package scha import "testing" -func TestSimpleHash(t *testing.T){ +func TestSimpleHash(t *testing.T) { - input := []byte("somePlainText"); + input := []byte("somePlainText") expected := []byte{ 0x4c, 0xcb, 0x0e, 0xf6, 0x81, 0x99, 0x2e, 0xd6, 0xb8, 0x17, 0x52, 0x1d, 0x09, 0x6e, 0x99, 0x19, 0xe7, 0xda, 0x50, 0xc8, 0xbf, 0x64, 0xae, 0xc1, 0x4f, 0xaa, 0x47, 0x06, 0xf3, 0x49, 0x30, 0x8a, 0x90, 0x8e, 0xd2, 0xff, 0xc2, 0x6d, 0xee, 0xaa, 0xd6, 0x45, 0xd8, 0xb3, 0x17, 0xe3, 0xb9, 0x45, 0x29, 0x26, 0xe2, 0x8e, - 0x99, 0x50, 0x94, 0x49, 0x90, 0x02, 0xa5, 0x61, 0x4a, 0x3f, 0x5e, 0xfa}; - got, err := Hash(input, 1); - digestLength := uint(len(got)); + 0x99, 0x50, 0x94, 0x49, 0x90, 0x02, 0xa5, 0x61, 0x4a, 0x3f, 0x5e, 0xfa} + got, err := Hash(input, 1) + digestLength := uint(len(got)) /* (2) Fail on errors */ if err != nil { - t.Errorf("Expected no errors, got: %s", err); + t.Errorf("Expected no errors, got: %s", err) } /* (2) Fail on wrong size */ - if uint16(digestLength) != HSIZE { - t.Errorf("Expected hash digest of %d bytes ; %d bytes received", HSIZE, digestLength); + if uint16(digestLength) != HSIZE { + t.Errorf("Expected hash digest of %d bytes ; %d bytes received", HSIZE, digestLength) } /* (3) Check each byte */ - for k, v := range got{ + for k, v := range got { if v != expected[k] { - t.Errorf("Expected sha[%d] of '%x' to be '%x' ; received '%x'", HSIZE, input, expected, got); - return; + t.Errorf("Expected sha[%d] of '%x' to be '%x' ; received '%x'", HSIZE, input, expected, got) + return } } } +func TestDepth1Plus1Equals2(t *testing.T) { - -func TestDepth1Plus1Equals2(t *testing.T){ - - input := []byte("someOtherPlainText"); + input := []byte("someOtherPlainText") /* (1) Calculate H1 */ h1, err := Hash(input, 1) if err != nil { - t.Errorf("Expected no error"); - return; + t.Errorf("Expected no error") + return } /* (2) Calculate H1(H1) */ - h11, err := Hash(h1, 1); + h11, err := Hash(h1, 1) if err != nil { - t.Errorf("Expected no error"); - return; + t.Errorf("Expected no error") + return } /* (3) Calculate H2 */ - h2, err := Hash(input, 1+1); + h2, err := Hash(input, 1+1) if err != nil { - t.Errorf("Expected no error"); - return; + t.Errorf("Expected no error") + return } /* (4) Manage different length */ if len(h11) != len(h2) || len(h11) != int(HSIZE) { - t.Errorf("Expected digest lengths to be %d, got %d and %d", HSIZE, len(h11), len(h2)); - return; + t.Errorf("Expected digest lengths to be %d, got %d and %d", HSIZE, len(h11), len(h2)) + return } /* (5) Compare the 2 strings */ for k, v := range h11 { if v != h2[k] { t.Errorf("Expected h2() to be equal to h1(h1())\n got '%x'\n expected '%x'", h2, h11) - return; + return } } } +func TestDepth52Plus64Equals116(t *testing.T) { - -func TestDepth52Plus64Equals116(t *testing.T){ - - input := []byte("someOtherPlainText"); + input := []byte("someOtherPlainText") /* (1) Calculate H52 */ h52, err := Hash(input, 52) if err != nil { - t.Errorf("Expected no error"); - return; + t.Errorf("Expected no error") + return } /* (2) Calculate H52(H64) */ - h5264, err := Hash(h52, 64); + h5264, err := Hash(h52, 64) if err != nil { - t.Errorf("Expected no error"); - return; + t.Errorf("Expected no error") + return } /* (3) Calculate H116 */ - h116, err := Hash(input, 52+64); + h116, err := Hash(input, 52+64) if err != nil { - t.Errorf("Expected no error"); - return; + t.Errorf("Expected no error") + return } /* (4) Manage different length */ if len(h5264) != len(h116) || len(h5264) != int(HSIZE) { - t.Errorf("Expected digest lengths to be %d, got %d and %d", HSIZE, len(h5264), len(h116)); - return; + t.Errorf("Expected digest lengths to be %d, got %d and %d", HSIZE, len(h5264), len(h116)) + return } /* (5) Compare the 2 strings */ for k, v := range h5264 { if v != h116[k] { t.Errorf("Expected h116() to be equal to h52(h64())\n got '%x'\n expected '%x'", h116, h5264) - return; + return } } } +func TestDepthError(t *testing.T) { - -func TestDepthError(t *testing.T){ - - input := []byte("somePlainText"); - _, err := Hash(input, 0); + input := []byte("somePlainText") + _, err := Hash(input, 0) /* (2) Fail on errors */ if err == nil { - t.Errorf("Expected an error for depth of 0"); + t.Errorf("Expected an error for depth of 0") } } +func TestEmptyInputError(t *testing.T) { - -func TestEmptyInputError(t *testing.T){ - - _, err := Hash(nil, 1); + _, err := Hash(nil, 1) /* (2) Fail on errors */ if err == nil { - t.Errorf("Expected an error for empty input"); + t.Errorf("Expected an error for empty input") } -} \ No newline at end of file +} diff --git a/internal/timeid/timeid.go b/internal/timeid/timeid.go index d82d506..5f7f7dd 100644 --- a/internal/timeid/timeid.go +++ b/internal/timeid/timeid.go @@ -5,7 +5,6 @@ import ( "time" ) - /* (1) Generates the current time id * * @wsize Window Size in seconds @@ -14,24 +13,25 @@ import ( * @return parity Current time parity * ---------------------------------------------------------*/ -func Generate(wsize float64) (uint32, uint32){ +func Generate(wsize float64) (uint32, uint32) { /* (1) If wsize is 0 (div by zero possible error) */ - if wsize == 0 { return 0, 0 } + if wsize == 0 { + return 0, 0 + } /* (2) Get current timestamp */ - timestamp := float64( time.Now().Unix() ); + timestamp := float64(time.Now().Unix()) /* (3) Calculate the time id */ - var id = uint32( timestamp / wsize ); + var id = uint32(timestamp / wsize) /* (4) Calculate parity */ - var parity = id % 2; + var parity = id % 2 - return id, parity; + return id, parity } - /* (2) Try to guess a previous time id from its parity * * @wsize Window Size in seconds @@ -40,12 +40,12 @@ func Generate(wsize float64) (uint32, uint32){ * @return id The guessed time id * ---------------------------------------------------------*/ -func Guess(wsize float64, parity uint32) uint32{ +func Guess(wsize float64, parity uint32) uint32 { /* (1) Get current time id */ - var idNow, parityNow = Generate(wsize); + var idNow, parityNow = Generate(wsize) /* (2) Update ID with tidNow parity difference */ - return idNow - uint32(math.Abs( float64(parityNow) - float64(parity) )); + return idNow - uint32(math.Abs(float64(parityNow)-float64(parity))) -} \ No newline at end of file +} diff --git a/internal/timeid/timeid_test.go b/internal/timeid/timeid_test.go index 651b14f..d6568d4 100644 --- a/internal/timeid/timeid_test.go +++ b/internal/timeid/timeid_test.go @@ -1,23 +1,22 @@ package timeid import ( - "time" "testing" + "time" ) +func TestGuessing(t *testing.T) { -func TestGuessing(t *testing.T){ + var windowSize float64 = .5 - var windowSize float64 = .5; + id, parity := Generate(windowSize) - id, parity := Generate(windowSize); + time.Sleep(time.Duration(windowSize) * time.Second) - time.Sleep( time.Duration(windowSize) * time.Second); - - var guessedId = Guess(windowSize, parity); + var guessedId = Guess(windowSize, parity) if id != guessedId { - t.Errorf("Wrong guessed id, expected '%d' ; got '%d'", id, guessedId); + t.Errorf("Wrong guessed id, expected '%d' ; got '%d'", id, guessedId) } -} \ No newline at end of file +} diff --git a/internal/xor/xor.go b/internal/xor/xor.go index cc7f1ab..ec93858 100644 --- a/internal/xor/xor.go +++ b/internal/xor/xor.go @@ -12,11 +12,10 @@ import "math" ---------------------------------------------------------*/ func Byte(_left byte, _right byte) byte { - return _left ^ _right; + return _left ^ _right } - /* (2) bitwise XOR between Byte arrays * * @_left Left operand @@ -43,16 +42,16 @@ func ByteArray(_left []byte, _right []byte) []byte { out := make([]byte, l, l) /* (2) Process bitwise XOR */ - for i := 0 ; i < l ; i++ { + for i := 0; i < l; i++ { // 1. Out of range for _left if i >= ll { - out[i] = _right[i]; + out[i] = _right[i] } else if i >= lr { - out[i] = _left[i]; + out[i] = _left[i] } else { diff --git a/server/server.go b/server/server.go index 0f6a02e..4330fee 100644 --- a/server/server.go +++ b/server/server.go @@ -1,13 +1,13 @@ package server import ( + "errors" "fmt" + "git.xdrm.io/logauth/schastsp/context" "git.xdrm.io/logauth/schastsp/internal/scha" "io" "os" "path/filepath" - "errors" - "git.xdrm.io/logauth/schastsp/context" ) const DEBUG = false @@ -15,12 +15,11 @@ const DEBUG = false /* (1) Structure ---------------------------------------------------------*/ type T struct { - ctx *context.T // shared context - hash []byte // current key - conf string // configuration file path + ctx *context.T // shared context + hash []byte // current key + conf string // configuration file path } - /* (2) Constructor * * @ctx Shared context @@ -32,43 +31,49 @@ func New(ctx *context.T, savePath string) (*T, error) { inst := new(T) /* (1) Store context */ - if ctx == nil { return nil, errors.New("Context must not be nil"); } - inst.ctx = ctx; + if ctx == nil { + return nil, errors.New("Context must not be nil") + } + inst.ctx = ctx /* (2) Get absolute file path */ - absolutePath, err := filepath.Abs(savePath); - if err != nil { return nil, err; } + absolutePath, err := filepath.Abs(savePath) + if err != nil { + return nil, err + } /* (3) Check file */ - info, err := os.Stat(absolutePath); + info, err := os.Stat(absolutePath) if err != nil { // Unknown error - if !os.IsNotExist(err) { return nil, err } + if !os.IsNotExist(err) { + return nil, err + } // File does not exist -> try to create file - _, err2 := os.Create(absolutePath); - if err2 != nil { return nil, err2 } + _, err2 := os.Create(absolutePath) + if err2 != nil { + return nil, err2 + } - // fail if exists but not regular file + // fail if exists but not regular file } else if !info.Mode().IsRegular() { - return nil, errors.New("Configuration file is not a regular file"); + return nil, errors.New("Configuration file is not a regular file") } /* (4) Store file path */ - inst.conf = absolutePath; + inst.conf = absolutePath /* (5) Try to fetch hash from conf */ inst.hash = make([]byte, scha.HSIZE) - err = inst.fetch(); + err = inst.fetch() // if err != nil { return nil, err } - return inst, nil; + return inst, nil } - - /* (3) Handle request and send response * * @req Request reader @@ -82,33 +87,44 @@ func (s *T) HandleRequest(req io.Reader, res io.Writer) error { /* (1) Manage request ---------------------------------------------------------*/ /* (1) Read x1 */ - x1 := make([]byte, scha.HSIZE); - read, err := req.Read(x1); - if err != nil { return fmt.Errorf("Reading x1 : %s", err) } - if uint16(read) != scha.HSIZE { return fmt.Errorf("Cannot read x1 : %d / %d bytes available", read, scha.HSIZE) } + x1 := make([]byte, scha.HSIZE) + read, err := req.Read(x1) + if err != nil { + return fmt.Errorf("Reading x1 : %s", err) + } + if uint16(read) != scha.HSIZE { + return fmt.Errorf("Cannot read x1 : %d / %d bytes available", read, scha.HSIZE) + } /* (2) Read x2 */ - x2 := make([]byte, scha.HSIZE); - read, err = req.Read(x2); - if err != nil { return fmt.Errorf("Reading x2 : %s", err) } - if uint16(read) != scha.HSIZE { return fmt.Errorf("Cannot read x2 : %d / %d bytes available", read, scha.HSIZE) } + x2 := make([]byte, scha.HSIZE) + read, err = req.Read(x2) + if err != nil { + return fmt.Errorf("Reading x2 : %s", err) + } + if uint16(read) != scha.HSIZE { + return fmt.Errorf("Cannot read x2 : %d / %d bytes available", read, scha.HSIZE) + } /* (3) Manage request */ errCode, err := s.manageRequest(x1, x2) - if err != nil { return err } + if err != nil { + return err + } /* (4) Valid authentication */ if errCode == 0 { response := []byte{0x00} written, err := res.Write(response) - if written != 1 || err != nil { return err } + if written != 1 || err != nil { + return err + } - return nil; + return nil } - /* (2) If not authenticated -> build resynchronisation response ---------------------------------------------------------*/ /* (1) Init y1 + y2 */ @@ -117,29 +133,41 @@ func (s *T) HandleRequest(req io.Reader, res io.Writer) error { /* (2) Generate response */ err = s.generateResynchronisationResponse(y1, y2) - if err != nil { return err } + if err != nil { + return err + } /* (3) Write error code */ responseCode := []byte{errCode} - written, err := res.Write(responseCode); - if err != nil { return err } - if written != len(responseCode) { return errors.New("Cannot write response code") } + written, err := res.Write(responseCode) + if err != nil { + return err + } + if written != len(responseCode) { + return errors.New("Cannot write response code") + } /* (4) Write y1 into response */ written, err = res.Write(y1) - if err != nil { return err } - if written != len(y1) { return errors.New("Cannot write y1") } + if err != nil { + return err + } + if written != len(y1) { + return errors.New("Cannot write y1") + } /* (5) Write y2 into response */ written, err = res.Write(y2) - if err != nil { return err } - if written != len(y1) { return errors.New("Cannot write y2") } + if err != nil { + return err + } + if written != len(y1) { + return errors.New("Cannot write y2") + } return nil } - - /* (4) Apply a synchronisation key * * @syncKey<[]byte> Synchronisation key from client @@ -162,4 +190,4 @@ func (s *T) SynchronisationKey(syncKey []byte) error { return nil -} \ No newline at end of file +} diff --git a/server/server.internal.go b/server/server.internal.go index 08c53af..78250b2 100644 --- a/server/server.internal.go +++ b/server/server.internal.go @@ -19,14 +19,18 @@ func (s T) store() error { /* (1) Try to open file for writing */ file, err := os.OpenFile(s.conf, os.O_RDWR|os.O_CREATE, 0755) - if err != nil { return err } + if err != nil { + return err + } /* (2) Defer close */ defer file.Close() /* (3) Write hash into file */ err = binary.Write(file, binary.BigEndian, s.hash) - if err != nil { return err } + if err != nil { + return err + } return nil @@ -41,7 +45,9 @@ func (s *T) fetch() error { /* (1) Try to open file for reading */ file, err := os.Open(s.conf) - if err != nil { return err } + if err != nil { + return err + } /* (2) Defer close */ defer file.Close() @@ -49,7 +55,9 @@ func (s *T) fetch() error { /* (3) Try to fetch hash from file */ fetchedHash := make([]byte, scha.HSIZE) err = binary.Read(file, binary.BigEndian, fetchedHash) - if err != nil { return err } + if err != nil { + return err + } /* (4) Fail if wrong size */ if uint16(len(fetchedHash)) != scha.HSIZE { @@ -77,7 +85,9 @@ func (s *T) fetch() error { ---------------------------------------------------------*/ func (s *T) manageRequest(x1 []byte, x2 []byte) (byte, error) { - if DEBUG { fmt.Printf(" stored hash is H = %x\n", s.hash) } + if DEBUG { + fmt.Printf(" stored hash is H = %x\n", s.hash) + } /* (1) Extract meta data ---------------------------------------------------------*/ @@ -86,19 +96,22 @@ func (s *T) manageRequest(x1 []byte, x2 []byte) (byte, error) { /* (2) Extract migration code */ mcode := uint8(x[1]) % 3 - if DEBUG { fmt.Printf(" extracted code is o = %d\n", mcode) } + if DEBUG { + fmt.Printf(" extracted code is o = %d\n", mcode) + } /* (3) Fail if no migration but different hashes */ if mcode == 0 && string(x1[2:]) != string(x2[2:]) { return 1, nil } - /* (2) TimeID management ---------------------------------------------------------*/ /* (1) Extract time mod */ timeMod := uint32(x[0]) % 2 - if DEBUG { fmt.Printf(" extracted time mod m = %d\n", timeMod) } + if DEBUG { + fmt.Printf(" extracted time mod m = %d\n", timeMod) + } /* (2) Try to guess time id */ timeID := timeid.Guess(s.ctx.Window(), timeMod) @@ -107,35 +120,43 @@ func (s *T) manageRequest(x1 []byte, x2 []byte) (byte, error) { /* (3) Hash guessed time id */ hashedTimeID, err := scha.Hash(timeIDBytes, 1) - if err != nil { return 2, err } - + if err != nil { + return 2, err + } /* (3) Extract hashes ---------------------------------------------------------*/ /* (1) Extract hash from x0 */ h0 := xor.ByteArray(x1, hashedTimeID) - if DEBUG { fmt.Printf(" supposing hash is h0 = %x\n", h0) } + if DEBUG { + fmt.Printf(" supposing hash is h0 = %x\n", h0) + } /* (2) Extract next hash from x1 */ h1 := xor.ByteArray(x2, hashedTimeID) - if DEBUG { fmt.Printf(" supposing next is h1 = %x\n", h1) } + if DEBUG { + fmt.Printf(" supposing next is h1 = %x\n", h1) + } /* (3) Only remove timeMod if migration code = 0 */ if mcode == 0 { h1[0] = xor.Byte(h1[0], byte(timeMod)) } - /* (4) Hash h0 to compare with stored hash 's.hash' ---------------------------------------------------------*/ /* (1) Hash 1 time to check if matches */ hashedH0, err := scha.Hash(h0, 1) - if err != nil { return 2, err } + if err != nil { + return 2, err + } /* (2) If migration code = 2 (Rescue mode) -> hash MIN times */ if mcode == 2 { hashedH0, err = scha.Hash(h0, s.ctx.MinDepth()) - if err != nil { return 2, err } + if err != nil { + return 2, err + } if DEBUG { fmt.Printf(" hashed is h(min) = %x\n", hashedH0) @@ -149,7 +170,6 @@ func (s *T) manageRequest(x1 []byte, x2 []byte) (byte, error) { return 1, nil } - /* (5) Store next hash ---------------------------------------------------------*/ copy(s.hash, h1) @@ -177,7 +197,9 @@ func (s *T) generateResynchronisationResponse(y1 []byte, y2 []byte) error { binary.BigEndian.PutUint32(timeIDBytes, timeID) hashedTimeID, err := scha.Hash(timeIDBytes, 1) - if err != nil { return err } + if err != nil { + return err + } /* (4) Process y1 = H ^ h(timeId) */ copy(y1, xor.ByteArray(s.hash, hashedTimeID))