v2 / vlib / crypto / blowfish / block.v
135 lines · 126 sloc · 4.25 KB · 387a01fcb50549913af9ad378104cdc40ed80b2a
Raw
1module blowfish
2
3// expand_key performs a key expansion on the given Blowfish cipher.
4@[direct_array_access]
5pub fn expand_key(key []u8, mut bf Blowfish) {
6 mut j := 0
7 for i := 0; i < 18; i++ {
8 mut d := u32(0)
9 for k := 0; k < 4; k++ {
10 d = d << 8 | u32(key[j])
11 j++
12 if j >= key.len {
13 j = 0
14 }
15 }
16 bf.p[i] ^= d
17 }
18
19 mut l := u32(0)
20 mut r := u32(0)
21 for i := 0; i < 18; i += 2 {
22 l, r = setup_tables(l, r, mut bf)
23 bf.p[i], bf.p[i + 1] = l, r
24 }
25
26 for i := 0; i < 256; i += 2 {
27 l, r = setup_tables(l, r, mut bf)
28 bf.s[0][i], bf.s[0][i + 1] = l, r
29 }
30 for i := 0; i < 256; i += 2 {
31 l, r = setup_tables(l, r, mut bf)
32 bf.s[1][i], bf.s[1][i + 1] = l, r
33 }
34 for i := 0; i < 256; i += 2 {
35 l, r = setup_tables(l, r, mut bf)
36 bf.s[2][i], bf.s[2][i + 1] = l, r
37 }
38 for i := 0; i < 256; i += 2 {
39 l, r = setup_tables(l, r, mut bf)
40 bf.s[3][i], bf.s[3][i + 1] = l, r
41 }
42}
43
44// expand_key_with_salt using salt to expand the key.
45@[direct_array_access]
46pub fn expand_key_with_salt(key []u8, salt []u8, mut bf Blowfish) {
47 mut j := 0
48 for i := 0; i < 18; i++ {
49 bf.p[i] ^= get_next_word(key, &j)
50 }
51
52 j = 0
53
54 mut l := u32(0)
55 mut r := u32(0)
56 for i := 0; i < 18; i += 2 {
57 l ^= get_next_word(salt, &j)
58 r ^= get_next_word(salt, &j)
59 l, r = setup_tables(l, r, mut bf)
60 bf.p[i], bf.p[i + 1] = l, r
61 }
62
63 for i := 0; i < 256; i += 2 {
64 l ^= get_next_word(salt, &j)
65 r ^= get_next_word(salt, &j)
66 l, r = setup_tables(l, r, mut bf)
67 bf.s[0][i], bf.s[0][i + 1] = l, r
68 }
69 for i := 0; i < 256; i += 2 {
70 l ^= get_next_word(salt, &j)
71 r ^= get_next_word(salt, &j)
72 l, r = setup_tables(l, r, mut bf)
73 bf.s[1][i], bf.s[1][i + 1] = l, r
74 }
75 for i := 0; i < 256; i += 2 {
76 l ^= get_next_word(salt, &j)
77 r ^= get_next_word(salt, &j)
78 l, r = setup_tables(l, r, mut bf)
79 bf.s[2][i], bf.s[2][i + 1] = l, r
80 }
81 for i := 0; i < 256; i += 2 {
82 l ^= get_next_word(salt, &j)
83 r ^= get_next_word(salt, &j)
84 l, r = setup_tables(l, r, mut bf)
85 bf.s[3][i], bf.s[3][i + 1] = l, r
86 }
87}
88
89// setup_tables sets up the Blowfish cipher's pi and substitution tables.
90@[direct_array_access]
91fn setup_tables(l u32, r u32, mut bf Blowfish) (u32, u32) {
92 mut xl := l
93 mut xr := r
94 xl ^= bf.p[0]
95 xr ^= ((bf.s[0][u8(xl >> 24)] + bf.s[1][u8(xl >> 16)]) ^ bf.s[2][u8(xl >> 8)]) + bf.s[3][u8(xl)] ^ bf.p[1]
96 xl ^= ((bf.s[0][u8(xr >> 24)] + bf.s[1][u8(xr >> 16)]) ^ bf.s[2][u8(xr >> 8)]) + bf.s[3][u8(xr)] ^ bf.p[2]
97 xr ^= ((bf.s[0][u8(xl >> 24)] + bf.s[1][u8(xl >> 16)]) ^ bf.s[2][u8(xl >> 8)]) + bf.s[3][u8(xl)] ^ bf.p[3]
98 xl ^= ((bf.s[0][u8(xr >> 24)] + bf.s[1][u8(xr >> 16)]) ^ bf.s[2][u8(xr >> 8)]) + bf.s[3][u8(xr)] ^ bf.p[4]
99 xr ^= ((bf.s[0][u8(xl >> 24)] + bf.s[1][u8(xl >> 16)]) ^ bf.s[2][u8(xl >> 8)]) + bf.s[3][u8(xl)] ^ bf.p[5]
100 xl ^= ((bf.s[0][u8(xr >> 24)] + bf.s[1][u8(xr >> 16)]) ^ bf.s[2][u8(xr >> 8)]) + bf.s[3][u8(xr)] ^ bf.p[6]
101 xr ^= ((bf.s[0][u8(xl >> 24)] + bf.s[1][u8(xl >> 16)]) ^ bf.s[2][u8(xl >> 8)]) + bf.s[3][u8(xl)] ^ bf.p[7]
102 xl ^= ((bf.s[0][u8(xr >> 24)] + bf.s[1][u8(xr >> 16)]) ^ bf.s[2][u8(xr >> 8)]) + bf.s[3][u8(xr)] ^ bf.p[8]
103 xr ^= ((bf.s[0][u8(xl >> 24)] + bf.s[1][u8(xl >> 16)]) ^ bf.s[2][u8(xl >> 8)]) + bf.s[3][u8(xl)] ^ bf.p[9]
104 xl ^= ((bf.s[0][u8(xr >> 24)] + bf.s[1][u8(xr >> 16)]) ^ bf.s[2][u8(xr >> 8)]) + bf.s[3][u8(xr)] ^ bf.p[10]
105 xr ^= ((bf.s[0][u8(xl >> 24)] + bf.s[1][u8(xl >> 16)]) ^ bf.s[2][u8(xl >> 8)]) + bf.s[3][u8(xl)] ^ bf.p[11]
106 xl ^= ((bf.s[0][u8(xr >> 24)] + bf.s[1][u8(xr >> 16)]) ^ bf.s[2][u8(xr >> 8)]) + bf.s[3][u8(xr)] ^ bf.p[12]
107 xr ^= ((bf.s[0][u8(xl >> 24)] + bf.s[1][u8(xl >> 16)]) ^ bf.s[2][u8(xl >> 8)]) + bf.s[3][u8(xl)] ^ bf.p[13]
108 xl ^= ((bf.s[0][u8(xr >> 24)] + bf.s[1][u8(xr >> 16)]) ^ bf.s[2][u8(xr >> 8)]) + bf.s[3][u8(xr)] ^ bf.p[14]
109 xr ^= ((bf.s[0][u8(xl >> 24)] + bf.s[1][u8(xl >> 16)]) ^ bf.s[2][u8(xl >> 8)]) + bf.s[3][u8(xl)] ^ bf.p[15]
110 xl ^= ((bf.s[0][u8(xr >> 24)] + bf.s[1][u8(xr >> 16)]) ^ bf.s[2][u8(xr >> 8)]) + bf.s[3][u8(xr)] ^ bf.p[16]
111 xr ^= bf.p[17]
112 return xr, xl
113}
114
115// get_next_word returns the next big-endian u32 value from the byte
116// slice at the given position in a circular manner, updating the position.
117@[direct_array_access]
118fn get_next_word(b []u8, pos &int) u32 {
119 mut w := u32(0)
120 mut j := 0
121 unsafe {
122 j = *pos
123 }
124 for i := 0; i < 4; i++ {
125 w = w << 8 | u32(b[j])
126 j++
127 if j >= b.len {
128 j = 0
129 }
130 }
131 unsafe {
132 *pos = j
133 }
134 return w
135}
136