tricrypt/tlep/chaos/main.go
2024-06-04 19:19:11 +03:00

159 lines
3.0 KiB
Go

package chaos
import (
"crypto/rand"
"encoding/binary"
"log"
)
// Define parameters for the Lorenz attractor.
const sigma = 10
const rho = 28
const beta = 8.0 / 3.0
// The function that represents the Lorenz system of equations.
func lorenz(x, y, z float64) (float64, float64, float64) {
dx := sigma * (y - x)
dy := x*(rho-z) - y
dz := x*y - beta*z
return dx, dy, dz
}
// The Runge-Kutta method (4th order) for a single step.
func (c *ChaosSystem) step() (float64, float64, float64) {
x := c.X
y := c.Y
z := c.Z
if c.Debug {
log.Printf("In stepping Old vals : x = %f ; y = %f ; z = %f\n", x, y, z)
}
h := c.H
k1x, k1y, k1z := lorenz(x, y, z)
k2x, k2y, k2z := lorenz(x+h*k1x/2, y+h*k1y/2, z+h*k1z/2)
k3x, k3y, k3z := lorenz(x+h*k2x/2, y+h*k2y/2, z+h*k2z/2)
k4x, k4y, k4z := lorenz(x+h*k3x, y+h*k3y, z+h*k3z)
// Combine the slopes and update the positions.
newX := x + h*(k1x+2*k2x+2*k3x+k4x)/6
newY := y + h*(k1y+2*k2y+2*k3y+k4y)/6
newZ := z + h*(k1z+2*k2z+2*k3z+k4z)/6
if c.Debug {
log.Printf("In stepping New vals : x = %f ; y = %f ; z = %f\n", newX, newY, newZ)
}
c.X = newX
c.Y = newY
c.Z = newZ
return newX, newY, newZ
}
type ChaosSystem struct {
Version int
X float64
Y float64
Z float64
H float64
Debug bool
XMult float64
YMult float64
ZMult float64
}
func CreateNewChaosSystem() *ChaosSystem {
var _c ChaosSystem
_c.Version = LATEST_VERSION
return &_c
}
func (c *ChaosSystem) Init(x, y, z, h float64) {
c.X = x
c.Y = y
c.Z = z
c.H = h
c.Debug = false
c.Version = LATEST_VERSION
}
func randomFloat64() (float64, error) {
var b [8]byte
if _, err := rand.Read(b[:]); err != nil {
return 0, err
}
return float64(binary.LittleEndian.Uint64(b[:])) / (1 << 64), nil
}
func (c *ChaosSystem) InitRandom() error {
x, err := randomFloat64()
if err != nil {
return err
}
y, err := randomFloat64()
if err != nil {
return err
}
z, err := randomFloat64()
if err != nil {
return err
}
c.Init(x, y, z, 0.1)
return nil
}
func (c *ChaosSystem) Burn(h uint) {
var i uint
for i = 0; i < h; i++ {
c.step()
}
}
func (c *ChaosSystem) SetMults(xM, yM, zM float64) {
c.XMult = xM
c.YMult = yM
c.ZMult = zM
}
func (c *ChaosSystem) ToggleDebug() {
c.Debug = !c.Debug
}
func (c *ChaosSystem) getByteVal() uint8 {
var xM, yM, zM float64
if c.XMult != 0 {
xM = c.XMult
} else {
xM = 13
}
if c.YMult != 0 {
yM = c.YMult
} else {
yM = 19
}
if c.ZMult != 0 {
zM = c.ZMult
} else {
zM = 11
}
hash := func(val float64, mult float64) uint8 {
scaledVal := val * mult * mult
// Convert to an int and take the bits we're interested in
intVal := int(scaledVal * scaledVal * scaledVal)
// XOR the parts of the integer to spread out the impact
return uint8((intVal>>8)^intVal) & 0xFF
}
xVal := hash(c.X, xM)
yVal := hash(c.Y, yM)
zVal := hash(c.Z, zM)
return xVal ^ yVal ^ zVal
}
func (c *ChaosSystem) GetPassword(lenght uint) []byte {
var i uint
var ret []byte
for i = 0; i < lenght; i++ {
c.step()
ret = append(ret, c.getByteVal())
}
return ret
}