[client:client] implemented 'Send(io.Writer)' [client:client.internal] implemented 'generateRequest', 'generateKeyWithConstraints', 'migrate'
This commit is contained in:
parent
fdab12841c
commit
3b282e397b
|
@ -6,6 +6,8 @@ import (
|
|||
"git.xdrm.io/schastsp/client/keyset"
|
||||
)
|
||||
|
||||
const DEBUG = false
|
||||
|
||||
|
||||
/* (1) Structure
|
||||
---------------------------------------------------------*/
|
||||
|
@ -58,7 +60,22 @@ func New(ctx *context.T, saveDir string) (*T, error) {
|
|||
* @return err<error> Error
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
func (c *T) Send(w io.Writer) error { return nil }
|
||||
func (c *T) Send(w io.Writer) error {
|
||||
|
||||
/* (1) Generate the request */
|
||||
var x1, x2 []byte;
|
||||
|
||||
err := c.generateRequest(x1, x2);
|
||||
if err != nil { return err }
|
||||
|
||||
/* (2) Write request into writer */
|
||||
_, err = w.Write(x1)
|
||||
if err != nil { return err }
|
||||
_, err = w.Write(x2)
|
||||
if err != nil { return err }
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
/* (4) Receives and processes a response
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
package client;
|
||||
|
||||
import "git.xdrm.io/schastsp/client/keyset"
|
||||
import (
|
||||
"fmt"
|
||||
"encoding/binary"
|
||||
"git.xdrm.io/schastsp/lib/scha"
|
||||
"git.xdrm.io/schastsp/lib/xor"
|
||||
"git.xdrm.io/schastsp/lib/timeid"
|
||||
"git.xdrm.io/schastsp/client/keyset"
|
||||
)
|
||||
|
||||
/* (1) Updates 'key' and 'sync' with files
|
||||
*
|
||||
|
@ -63,3 +70,200 @@ func (c *T) update(){
|
|||
if err != nil { panic("Cannot store sync") }
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (2) Migrate current key
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
func (c *T) migrateKey(){
|
||||
|
||||
var err error;
|
||||
|
||||
/* (1) Copy sync into key */
|
||||
c.key = c.sync
|
||||
|
||||
/* (2) Regenerate sync */
|
||||
c.sync, err = keyset.Create(c.ctx);
|
||||
if err != nil { panic(err) }
|
||||
|
||||
/* (3) Store keysets to files */
|
||||
c.update();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (3) Generate a new key respecting mod constraints (timeid + migration)
|
||||
*
|
||||
* @return newKey<*keyset.T> New key if found
|
||||
* NIL on error
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
func (c *T) generateKeyWithConstraints(){
|
||||
|
||||
/* Get current hash */
|
||||
keyHash, err := c.key.Hash();
|
||||
if err != nil { panic(err) }
|
||||
|
||||
|
||||
/* Search key one is respects contraints */
|
||||
for true {
|
||||
|
||||
/* (1) Get current time id
|
||||
---------------------------------------------------------*/
|
||||
_, timeMod := timeid.Generate(c.ctx.Window())
|
||||
|
||||
|
||||
/* (2) Generate a new sync
|
||||
---------------------------------------------------------*/
|
||||
newKey, _ := keyset.Create(c.ctx);
|
||||
|
||||
|
||||
/* (3) Check constraints
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Get next hash */
|
||||
syncHash, err := newKey.Hash()
|
||||
if err != nil { continue }
|
||||
|
||||
if DEBUG { fmt.Printf("+ hash is '%x'\n", keyHash); }
|
||||
if DEBUG { fmt.Printf("+ next hash is '%x'\n", syncHash); }
|
||||
|
||||
/* (2) Get time mod difference (first byte) */
|
||||
timeConstraintValue := xor.Byte(keyHash[0], syncHash[0]);
|
||||
|
||||
if DEBUG { fmt.Printf(" %.2x ^ %.2x = %.2x[%d] %% 2 = %d == %d ? %t\n", keyHash[0], syncHash[0], timeConstraintValue, timeConstraintValue, uint32(timeConstraintValue) % 2, timeMod, uint32(timeConstraintValue) % 2 == timeMod ) }
|
||||
|
||||
/* (4) Retry if invalid time constraint */
|
||||
if uint32(timeConstraintValue) % 2 != timeMod {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* (5) Get migration mod difference (second byte) */
|
||||
migrationConstraintValue := xor.Byte(keyHash[1], syncHash[2]);
|
||||
|
||||
if DEBUG { fmt.Printf(" %.2x ^ %.2x = %.2x[%d] %% 3 = %d == %d ? %t\n", keyHash[1], syncHash[1], migrationConstraintValue, migrationConstraintValue, uint8(migrationConstraintValue) % 3, c.key.MigrationCode(), uint8(migrationConstraintValue) % 3 == c.key.MigrationCode() ) }
|
||||
|
||||
/* (6) Retry if invalid time constraint */
|
||||
if uint8(migrationConstraintValue) % 3 != c.key.MigrationCode() {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* (7) Store new sync */
|
||||
c.sync = newKey;
|
||||
|
||||
/* (8) Store keysets to files */
|
||||
c.update()
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (4) Generate the client request
|
||||
*
|
||||
* @x1<[]byte> Byte array to write into
|
||||
* @x2<[]byte> Byte array to write into
|
||||
*
|
||||
* @return err<error> The error or NIL if not
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
func (c *T) generateRequest(x1 []byte, x2 []byte) error {
|
||||
|
||||
|
||||
/* (1) Migrate if validated migration
|
||||
---------------------------------------------------------*/
|
||||
if c.key.MigrationCode() == 3 {
|
||||
c.migrateKey();
|
||||
}
|
||||
|
||||
/* (2) Decrement and get useful hashes
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Decrement hash */
|
||||
remainingHashes := c.key.Decrement()
|
||||
c.update()
|
||||
|
||||
if DEBUG {
|
||||
fmt.Printf("Remaining %x[%d] hashes\n", remainingHashes, remainingHashes)
|
||||
fmt.Printf("Migration code is %d\n", c.key.MigrationCode())
|
||||
}
|
||||
|
||||
/* (2) Store current hash */
|
||||
h0, err := c.key.Hash();
|
||||
if err != nil { return err }
|
||||
|
||||
/* (3) Copy into next hash (same value) */
|
||||
h1, err := c.key.Hash();
|
||||
if err != nil { return err }
|
||||
|
||||
|
||||
/* (3) New sync hash if key consumed
|
||||
---------------------------------------------------------*/
|
||||
if c.key.MigrationCode() > 0 {
|
||||
|
||||
/* (1) Generate sync with constraints */
|
||||
c.generateKeyWithConstraints();
|
||||
|
||||
/* (2) Notify key need for renewal */
|
||||
c.key.MigrationCode(2);
|
||||
|
||||
/* (3) Store config */
|
||||
c.update();
|
||||
}
|
||||
|
||||
|
||||
/* (4) Manage time id
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Get current time id */
|
||||
timeId, timeMod := timeid.Generate(c.ctx.Window())
|
||||
|
||||
/* (2) Convert time id to byte array */
|
||||
timeIdBytes := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(timeIdBytes, timeId)
|
||||
|
||||
/* (2) Get digest of time id */
|
||||
hashedTimeId, err := scha.Hash(timeIdBytes, 1, nil, nil)
|
||||
|
||||
|
||||
|
||||
/* (5) Calculate x1 and x2
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Calculate x1 = h ^ h(timeId) */
|
||||
x1 = xor.ByteArray(h0, hashedTimeId)
|
||||
|
||||
if DEBUG {
|
||||
fmt.Printf("\n=== x1 ===\n");
|
||||
fmt.Printf(" hash is h0 = %x\n", h0)
|
||||
fmt.Printf(" time id is n = %x[%d]\n", timeIdBytes, timeId)
|
||||
fmt.Printf(" h(t) = %x\n", hashedTimeId)
|
||||
fmt.Printf(" ---\n");
|
||||
fmt.Printf(" x1 is h0+h(t) = %x\n", x1)
|
||||
fmt.Printf(" ---\n");
|
||||
fmt.Printf(" check x1+h(t) eq h0 = %x\n", xor.ByteArray(x1, hashedTimeId))
|
||||
fmt.Printf(" check x1+h0 eq h(t) = %x\n", xor.ByteArray(x1, h0));
|
||||
}
|
||||
|
||||
/* (2) Calculate x2 = h ^ h(timeId) ^ timeMod */
|
||||
x2 = xor.ByteArray(h1, hashedTimeId)
|
||||
|
||||
// do not add time mod if not code = 0
|
||||
if c.key.MigrationCode() != 0 {
|
||||
return nil;
|
||||
}
|
||||
|
||||
x2[0] = xor.Byte(x2[0], byte(timeMod))
|
||||
|
||||
if DEBUG {
|
||||
fmt.Printf("\n=== x2 ===\n");
|
||||
fmt.Printf(" next is h1 = %x\n", h1)
|
||||
fmt.Printf(" time mod is m = %x[%d]\n", timeMod, timeMod)
|
||||
fmt.Printf(" h(t) = %x\n", hashedTimeId)
|
||||
fmt.Printf(" ---\n");
|
||||
fmt.Printf(" x2 is h1+h(t)+m = %x\n", x2)
|
||||
fmt.Printf(" ---\n");
|
||||
fmt.Printf(" check x2+x1 %% 2 eq m = %d (%t)\n", uint8(xor.ByteArray(x1,x2)[0] % 2), xor.ByteArray(x1,x2)[0] % 2 == byte(timeMod))
|
||||
fmt.Printf(" check x2+x1 %% 3 eq o = %d (%t)\n", uint8(xor.ByteArray(x1,x2)[1] % 3), uint8(xor.ByteArray(x1,x2)[1] % 3) == c.key.MigrationCode());
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
Loading…
Reference in New Issue