diff --git a/README.md b/README.md index 28bc0f3..f9f017b 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,7 @@ **Copyright (C) 2017 xdrm-brackets** - -[![Go version](https://img.shields.io/badge/go_version-1.10.3-blue.svg)](https://golang.org/doc/go1.10) - -[![Go Report Card](https://goreportcard.com/badge/git.xdrm.io/logauth/schastsp)](https://goreportcard.com/report/git.xdrm.io/logauth/schastsp) -[![Go doc](https://godoc.org/git.xdrm.io/logauth/schastsp?status.svg)](https://godoc.org/git.xdrm.io/logauth/schastsp) +[![Go version](https://img.shields.io/badge/go_version-1.10.3-blue.svg)](https://golang.org/doc/go1.10) [![Go Report Card](https://goreportcard.com/badge/git.xdrm.io/logauth/schastsp)](https://goreportcard.com/report/git.xdrm.io/logauth/schastsp) [![Go doc](https://godoc.org/git.xdrm.io/logauth/schastsp?status.svg)](https://godoc.org/git.xdrm.io/logauth/schastsp) ## Overview @@ -84,3 +80,34 @@ go install git.xdrm.io/logauth/schastsp/cmd/client; go install git.xdrm.io/logauth/schastsp/cmd/server; ``` + + +The executables are now available in your `$GOBIN` (*i.e. `$GOPATH/bin`*) folder. + + + +## Client + +---- + +### 1. Usage + +```bash +client [options] +``` + +Available commands are : + +- `-req` generates a new request into standard output +- `-res` reads and manages a response from standard input +- `-sync` generates a synchronization key into standard output (*i.e. resets the system*) + +Available options are : + +- `-file` sets the folder where the keys are (or will be) stored. + +- `-win` sets the window value (in milliseconds). Typically the maximum transmission time. +- `-min` sets the minimum cyclic-hash depth. +- `-max` sets the maximum cyclic-hash depth. +- `-thr` sets the cyclic-hash threshold. This value represents at which offset of the key's TTL the key will be generated. It also corresponds to the number of time the client can desynchronize before becoming impossible to synchronize again. + diff --git a/client/client.go b/client/client.go index d0303e1..79e7e58 100644 --- a/client/client.go +++ b/client/client.go @@ -3,8 +3,8 @@ package client import ( "errors" "fmt" - "git.xdrm.io/logauth/schastsp/internal/keyset" "git.xdrm.io/logauth/schastsp/context" + "git.xdrm.io/logauth/schastsp/internal/keyset" "git.xdrm.io/logauth/schastsp/internal/scha" "io" ) @@ -14,11 +14,11 @@ const DEBUG = false /* (1) Structure ---------------------------------------------------------*/ type T struct { - ctx *context.T // shared context - key *keyset.T // current key - sync *keyset.T // next bufferised key - fkey *config // key file management - fsync *config // sync file management + ctx *context.T // shared context + key *keyset.T // current key + sync *keyset.T // next bufferised key + fkey *config // key file management + fsync *config // sync file management } /* (2) Constructor @@ -34,16 +34,22 @@ func New(ctx *context.T, saveDir string) (*T, error) { inst := new(T) /* (1) Store context */ - if ctx == nil { return nil, errors.New("Context must not be nil"); } + if ctx == nil { + return nil, errors.New("Context must not be nil") + } inst.ctx = ctx /* (2) Get file management for KEY */ inst.fkey, err = Config(saveDir, "key") - if err != nil { return nil, err } + if err != nil { + return nil, err + } /* (3) Get file management for SYNC */ inst.fsync, err = Config(saveDir, "sync") - if err != nil { return nil, err } + if err != nil { + return nil, err + } /* (4) Restore from config */ inst.updateConfig() @@ -66,16 +72,26 @@ func (c *T) Send(w io.Writer) error { x2 := make([]byte, scha.HSIZE) err := c.generateRequest(x1, x2) - if err != nil { return err } + if err != nil { + return err + } /* (2) Write request into writer */ written, err := w.Write(x1) - if err != nil { return err } - if written != len(x1) { return errors.New("Cannot write x1") } + if err != nil { + return err + } + if written != len(x1) { + return errors.New("Cannot write x1") + } written, err = w.Write(x2) - if err != nil { return err } - if written != len(x1) { return errors.New("Cannot write x2") } + if err != nil { + return err + } + if written != len(x1) { + return errors.New("Cannot write x2") + } return nil } @@ -93,10 +109,16 @@ func (c *T) Receive(r io.Reader) error { ---------------------------------------------------------*/ errCode := make([]byte, 1) read, err := r.Read(errCode) - if err != nil { return err } - if uint16(read) != 1 { return errors.New("Cannot read error code") } + if err != nil { + return err + } + if uint16(read) != 1 { + return errors.New("Cannot read error code") + } - if DEBUG { fmt.Printf("ERROR CODE : %d\n", errCode[0]) } + if DEBUG { + fmt.Printf("ERROR CODE : %d\n", errCode[0]) + } /* (2) Manage success ---------------------------------------------------------*/ @@ -105,7 +127,9 @@ func (c *T) Receive(r io.Reader) error { /* (1) If pending migration -> migrate */ if c.key.MigrationCode() == 2 { c.migrateKey() - if DEBUG { fmt.Printf("*** VALIDATED MIGRATION\n") } + if DEBUG { + fmt.Printf("*** VALIDATED MIGRATION\n") + } } /* (2) No error anyway */ @@ -118,28 +142,37 @@ func (c *T) Receive(r io.Reader) error { /* (1) Read y1 */ y1 := make([]byte, scha.HSIZE) read, err = r.Read(y1) - if err != nil { return err } - if uint16(read) != scha.HSIZE { return errors.New("Cannot read y1") } + if err != nil { + return err + } + if uint16(read) != scha.HSIZE { + return errors.New("Cannot read y1") + } /* (2) Read y2 */ y2 := make([]byte, scha.HSIZE) read, err = r.Read(y2) - if err != nil { return err } - if uint16(read) != scha.HSIZE { return errors.New("Cannot read enough y2") } + if err != nil { + return err + } + if uint16(read) != scha.HSIZE { + return errors.New("Cannot read enough y2") + } /* (3) Manage rescue mode */ err = c.rescue(y1, y2) - if err != nil { return err } + if err != nil { + return err + } - if DEBUG { fmt.Printf("*** MIGRATION PREPARED\n") } + if DEBUG { + fmt.Printf("*** MIGRATION PREPARED\n") + } return nil } - - - /* (5) Returns a synchronisation key (first server connection) * * @return key<[]byte> Synchronisation key @@ -148,17 +181,19 @@ func (c *T) Receive(r io.Reader) error { ---------------------------------------------------------*/ func (c *T) SynchronisationKey() ([]byte, error) { - /* (1) Reset keys so no value can be guessed*/ - c.migrateKey(); // 1: copies 'sync' into 'key' - c.migrateKey(); // 2: copies random new 'sync' into 'key' (old 'sync) + /* (1) Reset keys so no value can be guessed */ + c.migrateKey() // 1: copies 'sync' into 'key' + c.migrateKey() // 2: copies random new 'sync' into 'key' (old 'sync) /* (2) Get current hash */ hash, err := c.key.CurrentHash() - if err != nil { return nil, err } + if err != nil { + return nil, err + } /* (3) Decrement key so 'hash' is valid */ c.key.Decrement() /* (4) Return key */ - return hash, nil; + return hash, nil } diff --git a/cmd/client/client.go b/cmd/client/client.go index 759cd8b..d99ab26 100644 --- a/cmd/client/client.go +++ b/cmd/client/client.go @@ -1,38 +1,38 @@ package main import ( - "time" - "os" "flag" "fmt" - "git.xdrm.io/logauth/schastsp/context" "git.xdrm.io/logauth/schastsp/client" + "git.xdrm.io/logauth/schastsp/context" + "os" + "time" ) -func main(){ +func main() { executionStart := time.Now().UnixNano() /* (1) Flag management (cli arguments) ---------------------------------------------------------*/ /* (1) Secret folder */ - clientConfigPath := flag.String("file", "/tmp/schastsp_keys", "Configuration folder, it will contain sensitive data (keys), make sure to control it properly. (default: /tmp/schastsp_keys)") + clientConfigPath := flag.String("file", "/tmp/schastsp_keys", "Configuration folder, it will contain sensitive data (keys), make sure to control it properly.") /* (2) request | response */ isRequest := flag.Bool("req", false, "Will generate a request into standard output.") isResponse := flag.Bool("res", false, "Will proceed a response management from standard input.") /* (3) Context window size */ - winSize := flag.Uint("win", 2000, "Time window value in ms. (default: 2000)") + winSize := flag.Uint("win", 2000, "Time window value in ms.") /* (4) Context minimum depth value */ - minDepth := flag.Uint("min", 0x0f0, "Minimum depth value. (default: 240)") + minDepth := flag.Uint("min", 0x0f0, "Minimum depth value.") /* (5) Context maximum depth value */ - maxDepth := flag.Uint("max", 0xfff, "Maximum depth value. (default: 4095)") + maxDepth := flag.Uint("max", 0xfff, "Maximum depth value.") /* (6) Context depth threshold */ - thrDepth := flag.Uint("thr", 0x00a, "Depth threshold protecting minimum depth to be reached. (default: 10)") + thrDepth := flag.Uint("thr", 0x00a, "Depth threshold protecting minimum depth to be reached.") /* (7) Synchronisation request (special order) */ syncRequest := flag.Bool("sync", false, "If set, proceeds a synchronisation request and outputs the synchronisation key.") @@ -40,72 +40,81 @@ func main(){ /* (8) 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("[CLIENT_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("[CLIENT_ERROR:context] %s\n", err)) + return + } /* (2) Create client */ cli, err := client.New(ctx, *clientConfigPath) - if err != nil { os.Stderr.WriteString( fmt.Sprintf("[CLIENT_ERROR:client] %s\n", err) ); return } - - + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("[CLIENT_ERROR:client] %s\n", err)) + return + } /* (3) Dispatch execution ---------------------------------------------------------*/ /* (1) If synchronisation request */ if *syncRequest { - synchronisationRequest(cli); + synchronisationRequest(cli) - /* (2) If request */ + /* (2) If request */ } else if *isRequest { err = cli.Send(os.Stdout) - if err != nil { os.Stderr.WriteString( fmt.Sprintf("[CLIENT_ERROR:request] %s\n", err) ) } + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("[CLIENT_ERROR:request] %s\n", err)) + } - /* (3) If response */ + /* (3) If response */ } else if *isResponse { err = cli.Receive(os.Stdin) - if err != nil { os.Stderr.WriteString( fmt.Sprintf("[CLIENT_ERROR:response] %s\n", err) ); return } + if err != nil { + os.Stderr.WriteString(fmt.Sprintf("[CLIENT_ERROR:response] %s\n", err)) + return + } - /* (4) Else -> nothing */ - }else { - os.Stderr.WriteString( fmt.Sprintf("Missing argument.\n\nYou must give one of the 3 available actions :\n -req to manage a request\n -res to manage a response\n -sync to get a synchronisation key\n") ) + /* (4) Else -> nothing */ + } else { + os.Stderr.WriteString(fmt.Sprintf("Missing argument.\n\nYou must give one of the 3 available actions :\n -req to manage a request\n -res to manage a response\n -sync to get a synchronisation key\n")) } - - - - 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 synchronisationRequest(cli *client.T){ +func synchronisationRequest(cli *client.T) { /* (1) Get synchronisation key */ syncKey, err := cli.SynchronisationKey() - if err != nil { fmt.Errorf("[CLIENT_ERROR:syncKey] %s\n", err); return } + if err != nil { + fmt.Errorf("[CLIENT_ERROR:syncKey] %s\n", err) + return + } /* (2) Print synchronisation key */ os.Stdout.Write(syncKey) - return; + return -} \ No newline at end of file +} diff --git a/internal/keyset/keyset.go b/internal/keyset/keyset.go index 7c9d1c7..1d7bd47 100644 --- a/internal/keyset/keyset.go +++ b/internal/keyset/keyset.go @@ -230,7 +230,9 @@ func (s *T) Rescue(lastHash []byte) error { /* (1) Process hash */ currentHash, err := scha.Hash(s.sec, i) - if err != nil { return err } + if err != nil { + return err + } /* (2) If not found -> try again */ if string(currentHash) != string(lastHash) {