diff options
author | siddharth <s@ricketyspace.net> | 2021-09-04 16:57:14 -0400 |
---|---|---|
committer | siddharth <s@ricketyspace.net> | 2021-09-04 16:57:14 -0400 |
commit | 823471e97d03d0f2c020c344e941668ea7e7769d (patch) | |
tree | a7579f7a85e8bca4044ac6142162360d86674028 | |
parent | fbf74bd2d84db61a68b181b8923335b1f2d501fa (diff) |
lib: add MTXORStream
-rw-r--r-- | lib/rng.go | 49 |
1 files changed, 49 insertions, 0 deletions
@@ -93,3 +93,52 @@ func (r *MTRand) UnTemper(y uint32) uint32 { y = 0xFFFFFFFF & y return y } + +// Returns a stream function. The stream function returns a random +// byte when invoked. +// +// The `seed` argument must be exactly bytes. +func keystream(seed []byte) func() byte { + if len(seed) != 2 { + return nil + } + + // Pack seed into a uint32 + s := (uint32(seed[0]) << 8) ^ uint32(seed[1]) + + // Init MT19937. + mtR := new(MTRand) + mtR.Seed(s) + + // Stream func. + n := uint32(0) + return func() byte { + if n == uint32(0) { + n = mtR.Extract() + } + r := byte(n & 0xFF) // Extract last 8 bits. + n = n >> 8 // Get rid of the last 8 bits. + + return r + } +} + +// XORs `stream` with the MT19937 keystream seeded with `seed`. +func MTXORStream(stream, seed []byte) []byte { + if len(stream) == 0 { + return []byte{} + } + if len(seed) != 2 { + return nil + } + + ks := keystream(seed) + if ks == nil { + return nil + } + s := make([]byte, 0) + for i := 0; i < len(stream); i++ { + s = append(s, stream[i]^ks()) + } + return s +} |