This repository has been archived by the owner on Nov 9, 2017. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathspritz.go
123 lines (109 loc) · 1.98 KB
/
spritz.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Package spritz provides a pure Go implementation of the Spritz stream cipher
// and hash.
//
// More details on the Spritz family of algorithms can be found here:
// http://people.csail.mit.edu/rivest/pubs/RS14.pdf.
package spritz
import "math"
type state struct {
// these are all ints instead of bytes to allow for states > 256
n, d int // state size and nibble size
s []int
a, i, j, k, w, z int
}
func (s *state) initialize(n int) {
*s = state{
s: make([]int, n),
w: 1,
n: n,
d: int(math.Ceil(math.Sqrt(float64(n)))),
}
for i := range s.s {
s.s[i] = i
}
}
func (s *state) update() {
s.i = (s.i + s.w) % s.n
y := (s.j + s.s[s.i]) % s.n
s.j = (s.k + s.s[y]) % s.n
s.k = (s.i + s.k + s.s[s.j]) % s.n
t := s.s[s.i]
s.s[s.i] = s.s[s.j]
s.s[s.j] = t
}
func (s *state) output() int {
y1 := (s.z + s.k) % s.n
x1 := (s.i + s.s[y1]) % s.n
y2 := (s.j + s.s[x1]) % s.n
s.z = s.s[y2]
return s.z
}
func (s *state) crush() {
for i := 0; i < s.n/2; i++ {
y := (s.n - 1) - i
x1 := s.s[i]
x2 := s.s[y]
if x1 > x2 {
s.s[i] = x2
s.s[y] = x1
} else {
s.s[i] = x1
s.s[y] = x2
}
}
}
func (s *state) whip() {
r := s.n * 2
for i := 0; i < r; i++ {
s.update()
}
s.w = (s.w + 2) % s.n
}
func (s *state) shuffle() {
s.whip()
s.crush()
s.whip()
s.crush()
s.whip()
s.a = 0
}
func (s *state) absorbStop() {
if s.a == s.n/2 {
s.shuffle()
}
s.a = (s.a + 1) % s.n
}
func (s *state) absorbNibble(x int) {
if s.a == s.n/2 {
s.shuffle()
}
y := (s.n/2 + x) % s.n
t := s.s[s.a]
s.s[s.a] = s.s[y]
s.s[y] = t
s.a = (s.a + 1) % s.n
}
func (s *state) absorbByte(b int) {
s.absorbNibble(b % s.d) // LOW
s.absorbNibble(b / s.d) // HIGH
}
func (s *state) absorb(msg []byte) {
for _, v := range msg {
s.absorbByte(int(v))
}
}
func (s *state) drip() int {
if s.a > 0 {
s.shuffle()
}
s.update()
return s.output()
}
func (s *state) squeeze(out []byte) {
if s.a > 0 {
s.shuffle()
}
for i := range out {
out[i] = byte(s.drip())
}
}