1 // GoGOST -- Pure Go GOST cryptographic functions library
2 // Copyright (C) 2015-2021 Sergey Matveev <stargrave@stargrave.org>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // GOST R 34.11-2012 hash function.
30 MarshaledName = "STREEBOG"
34 pi [256]byte = [256]byte{
35 0xfc, 0xee, 0xdd, 0x11, 0xcf, 0x6e, 0x31, 0x16,
36 0xfb, 0xc4, 0xfa, 0xda, 0x23, 0xc5, 0x04, 0x4d,
37 0xe9, 0x77, 0xf0, 0xdb, 0x93, 0x2e, 0x99, 0xba,
38 0x17, 0x36, 0xf1, 0xbb, 0x14, 0xcd, 0x5f, 0xc1,
39 0xf9, 0x18, 0x65, 0x5a, 0xe2, 0x5c, 0xef, 0x21,
40 0x81, 0x1c, 0x3c, 0x42, 0x8b, 0x01, 0x8e, 0x4f,
41 0x05, 0x84, 0x02, 0xae, 0xe3, 0x6a, 0x8f, 0xa0,
42 0x06, 0x0b, 0xed, 0x98, 0x7f, 0xd4, 0xd3, 0x1f,
43 0xeb, 0x34, 0x2c, 0x51, 0xea, 0xc8, 0x48, 0xab,
44 0xf2, 0x2a, 0x68, 0xa2, 0xfd, 0x3a, 0xce, 0xcc,
45 0xb5, 0x70, 0x0e, 0x56, 0x08, 0x0c, 0x76, 0x12,
46 0xbf, 0x72, 0x13, 0x47, 0x9c, 0xb7, 0x5d, 0x87,
47 0x15, 0xa1, 0x96, 0x29, 0x10, 0x7b, 0x9a, 0xc7,
48 0xf3, 0x91, 0x78, 0x6f, 0x9d, 0x9e, 0xb2, 0xb1,
49 0x32, 0x75, 0x19, 0x3d, 0xff, 0x35, 0x8a, 0x7e,
50 0x6d, 0x54, 0xc6, 0x80, 0xc3, 0xbd, 0x0d, 0x57,
51 0xdf, 0xf5, 0x24, 0xa9, 0x3e, 0xa8, 0x43, 0xc9,
52 0xd7, 0x79, 0xd6, 0xf6, 0x7c, 0x22, 0xb9, 0x03,
53 0xe0, 0x0f, 0xec, 0xde, 0x7a, 0x94, 0xb0, 0xbc,
54 0xdc, 0xe8, 0x28, 0x50, 0x4e, 0x33, 0x0a, 0x4a,
55 0xa7, 0x97, 0x60, 0x73, 0x1e, 0x00, 0x62, 0x44,
56 0x1a, 0xb8, 0x38, 0x82, 0x64, 0x9f, 0x26, 0x41,
57 0xad, 0x45, 0x46, 0x92, 0x27, 0x5e, 0x55, 0x2f,
58 0x8c, 0xa3, 0xa5, 0x7d, 0x69, 0xd5, 0x95, 0x3b,
59 0x07, 0x58, 0xb3, 0x40, 0x86, 0xac, 0x1d, 0xf7,
60 0x30, 0x37, 0x6b, 0xe4, 0x88, 0xd9, 0xe7, 0x89,
61 0xe1, 0x1b, 0x83, 0x49, 0x4c, 0x3f, 0xf8, 0xfe,
62 0x8d, 0x53, 0xaa, 0x90, 0xca, 0xd8, 0x85, 0x61,
63 0x20, 0x71, 0x67, 0xa4, 0x2d, 0x2b, 0x09, 0x5b,
64 0xcb, 0x9b, 0x25, 0xd0, 0xbe, 0xe5, 0x6c, 0x52,
65 0x59, 0xa6, 0x74, 0xd2, 0xe6, 0xf4, 0xb4, 0xc0,
66 0xd1, 0x66, 0xaf, 0xc2, 0x39, 0x4b, 0x63, 0xb6,
68 tau [64]int = [64]int{
69 0x00, 0x08, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38,
70 0x01, 0x09, 0x11, 0x19, 0x21, 0x29, 0x31, 0x39,
71 0x02, 0x0a, 0x12, 0x1a, 0x22, 0x2a, 0x32, 0x3a,
72 0x03, 0x0b, 0x13, 0x1b, 0x23, 0x2b, 0x33, 0x3b,
73 0x04, 0x0c, 0x14, 0x1c, 0x24, 0x2c, 0x34, 0x3c,
74 0x05, 0x0d, 0x15, 0x1d, 0x25, 0x2d, 0x35, 0x3d,
75 0x06, 0x0e, 0x16, 0x1e, 0x26, 0x2e, 0x36, 0x3e,
76 0x07, 0x0f, 0x17, 0x1f, 0x27, 0x2f, 0x37, 0x3f,
78 c [12][BlockSize]byte = [12][BlockSize]byte{
80 0x07, 0x45, 0xa6, 0xf2, 0x59, 0x65, 0x80, 0xdd,
81 0x23, 0x4d, 0x74, 0xcc, 0x36, 0x74, 0x76, 0x05,
82 0x15, 0xd3, 0x60, 0xa4, 0x08, 0x2a, 0x42, 0xa2,
83 0x01, 0x69, 0x67, 0x92, 0x91, 0xe0, 0x7c, 0x4b,
84 0xfc, 0xc4, 0x85, 0x75, 0x8d, 0xb8, 0x4e, 0x71,
85 0x16, 0xd0, 0x45, 0x2e, 0x43, 0x76, 0x6a, 0x2f,
86 0x1f, 0x7c, 0x65, 0xc0, 0x81, 0x2f, 0xcb, 0xeb,
87 0xe9, 0xda, 0xca, 0x1e, 0xda, 0x5b, 0x08, 0xb1,
90 0xb7, 0x9b, 0xb1, 0x21, 0x70, 0x04, 0x79, 0xe6,
91 0x56, 0xcd, 0xcb, 0xd7, 0x1b, 0xa2, 0xdd, 0x55,
92 0xca, 0xa7, 0x0a, 0xdb, 0xc2, 0x61, 0xb5, 0x5c,
93 0x58, 0x99, 0xd6, 0x12, 0x6b, 0x17, 0xb5, 0x9a,
94 0x31, 0x01, 0xb5, 0x16, 0x0f, 0x5e, 0xd5, 0x61,
95 0x98, 0x2b, 0x23, 0x0a, 0x72, 0xea, 0xfe, 0xf3,
96 0xd7, 0xb5, 0x70, 0x0f, 0x46, 0x9d, 0xe3, 0x4f,
97 0x1a, 0x2f, 0x9d, 0xa9, 0x8a, 0xb5, 0xa3, 0x6f,
100 0xb2, 0x0a, 0xba, 0x0a, 0xf5, 0x96, 0x1e, 0x99,
101 0x31, 0xdb, 0x7a, 0x86, 0x43, 0xf4, 0xb6, 0xc2,
102 0x09, 0xdb, 0x62, 0x60, 0x37, 0x3a, 0xc9, 0xc1,
103 0xb1, 0x9e, 0x35, 0x90, 0xe4, 0x0f, 0xe2, 0xd3,
104 0x7b, 0x7b, 0x29, 0xb1, 0x14, 0x75, 0xea, 0xf2,
105 0x8b, 0x1f, 0x9c, 0x52, 0x5f, 0x5e, 0xf1, 0x06,
106 0x35, 0x84, 0x3d, 0x6a, 0x28, 0xfc, 0x39, 0x0a,
107 0xc7, 0x2f, 0xce, 0x2b, 0xac, 0xdc, 0x74, 0xf5,
110 0x2e, 0xd1, 0xe3, 0x84, 0xbc, 0xbe, 0x0c, 0x22,
111 0xf1, 0x37, 0xe8, 0x93, 0xa1, 0xea, 0x53, 0x34,
112 0xbe, 0x03, 0x52, 0x93, 0x33, 0x13, 0xb7, 0xd8,
113 0x75, 0xd6, 0x03, 0xed, 0x82, 0x2c, 0xd7, 0xa9,
114 0x3f, 0x35, 0x5e, 0x68, 0xad, 0x1c, 0x72, 0x9d,
115 0x7d, 0x3c, 0x5c, 0x33, 0x7e, 0x85, 0x8e, 0x48,
116 0xdd, 0xe4, 0x71, 0x5d, 0xa0, 0xe1, 0x48, 0xf9,
117 0xd2, 0x66, 0x15, 0xe8, 0xb3, 0xdf, 0x1f, 0xef,
120 0x57, 0xfe, 0x6c, 0x7c, 0xfd, 0x58, 0x17, 0x60,
121 0xf5, 0x63, 0xea, 0xa9, 0x7e, 0xa2, 0x56, 0x7a,
122 0x16, 0x1a, 0x27, 0x23, 0xb7, 0x00, 0xff, 0xdf,
123 0xa3, 0xf5, 0x3a, 0x25, 0x47, 0x17, 0xcd, 0xbf,
124 0xbd, 0xff, 0x0f, 0x80, 0xd7, 0x35, 0x9e, 0x35,
125 0x4a, 0x10, 0x86, 0x16, 0x1f, 0x1c, 0x15, 0x7f,
126 0x63, 0x23, 0xa9, 0x6c, 0x0c, 0x41, 0x3f, 0x9a,
127 0x99, 0x47, 0x47, 0xad, 0xac, 0x6b, 0xea, 0x4b,
130 0x6e, 0x7d, 0x64, 0x46, 0x7a, 0x40, 0x68, 0xfa,
131 0x35, 0x4f, 0x90, 0x36, 0x72, 0xc5, 0x71, 0xbf,
132 0xb6, 0xc6, 0xbe, 0xc2, 0x66, 0x1f, 0xf2, 0x0a,
133 0xb4, 0xb7, 0x9a, 0x1c, 0xb7, 0xa6, 0xfa, 0xcf,
134 0xc6, 0x8e, 0xf0, 0x9a, 0xb4, 0x9a, 0x7f, 0x18,
135 0x6c, 0xa4, 0x42, 0x51, 0xf9, 0xc4, 0x66, 0x2d,
136 0xc0, 0x39, 0x30, 0x7a, 0x3b, 0xc3, 0xa4, 0x6f,
137 0xd9, 0xd3, 0x3a, 0x1d, 0xae, 0xae, 0x4f, 0xae,
140 0x93, 0xd4, 0x14, 0x3a, 0x4d, 0x56, 0x86, 0x88,
141 0xf3, 0x4a, 0x3c, 0xa2, 0x4c, 0x45, 0x17, 0x35,
142 0x04, 0x05, 0x4a, 0x28, 0x83, 0x69, 0x47, 0x06,
143 0x37, 0x2c, 0x82, 0x2d, 0xc5, 0xab, 0x92, 0x09,
144 0xc9, 0x93, 0x7a, 0x19, 0x33, 0x3e, 0x47, 0xd3,
145 0xc9, 0x87, 0xbf, 0xe6, 0xc7, 0xc6, 0x9e, 0x39,
146 0x54, 0x09, 0x24, 0xbf, 0xfe, 0x86, 0xac, 0x51,
147 0xec, 0xc5, 0xaa, 0xee, 0x16, 0x0e, 0xc7, 0xf4,
150 0x1e, 0xe7, 0x02, 0xbf, 0xd4, 0x0d, 0x7f, 0xa4,
151 0xd9, 0xa8, 0x51, 0x59, 0x35, 0xc2, 0xac, 0x36,
152 0x2f, 0xc4, 0xa5, 0xd1, 0x2b, 0x8d, 0xd1, 0x69,
153 0x90, 0x06, 0x9b, 0x92, 0xcb, 0x2b, 0x89, 0xf4,
154 0x9a, 0xc4, 0xdb, 0x4d, 0x3b, 0x44, 0xb4, 0x89,
155 0x1e, 0xde, 0x36, 0x9c, 0x71, 0xf8, 0xb7, 0x4e,
156 0x41, 0x41, 0x6e, 0x0c, 0x02, 0xaa, 0xe7, 0x03,
157 0xa7, 0xc9, 0x93, 0x4d, 0x42, 0x5b, 0x1f, 0x9b,
160 0xdb, 0x5a, 0x23, 0x83, 0x51, 0x44, 0x61, 0x72,
161 0x60, 0x2a, 0x1f, 0xcb, 0x92, 0xdc, 0x38, 0x0e,
162 0x54, 0x9c, 0x07, 0xa6, 0x9a, 0x8a, 0x2b, 0x7b,
163 0xb1, 0xce, 0xb2, 0xdb, 0x0b, 0x44, 0x0a, 0x80,
164 0x84, 0x09, 0x0d, 0xe0, 0xb7, 0x55, 0xd9, 0x3c,
165 0x24, 0x42, 0x89, 0x25, 0x1b, 0x3a, 0x7d, 0x3a,
166 0xde, 0x5f, 0x16, 0xec, 0xd8, 0x9a, 0x4c, 0x94,
167 0x9b, 0x22, 0x31, 0x16, 0x54, 0x5a, 0x8f, 0x37,
170 0xed, 0x9c, 0x45, 0x98, 0xfb, 0xc7, 0xb4, 0x74,
171 0xc3, 0xb6, 0x3b, 0x15, 0xd1, 0xfa, 0x98, 0x36,
172 0xf4, 0x52, 0x76, 0x3b, 0x30, 0x6c, 0x1e, 0x7a,
173 0x4b, 0x33, 0x69, 0xaf, 0x02, 0x67, 0xe7, 0x9f,
174 0x03, 0x61, 0x33, 0x1b, 0x8a, 0xe1, 0xff, 0x1f,
175 0xdb, 0x78, 0x8a, 0xff, 0x1c, 0xe7, 0x41, 0x89,
176 0xf3, 0xf3, 0xe4, 0xb2, 0x48, 0xe5, 0x2a, 0x38,
177 0x52, 0x6f, 0x05, 0x80, 0xa6, 0xde, 0xbe, 0xab,
180 0x1b, 0x2d, 0xf3, 0x81, 0xcd, 0xa4, 0xca, 0x6b,
181 0x5d, 0xd8, 0x6f, 0xc0, 0x4a, 0x59, 0xa2, 0xde,
182 0x98, 0x6e, 0x47, 0x7d, 0x1d, 0xcd, 0xba, 0xef,
183 0xca, 0xb9, 0x48, 0xea, 0xef, 0x71, 0x1d, 0x8a,
184 0x79, 0x66, 0x84, 0x14, 0x21, 0x80, 0x01, 0x20,
185 0x61, 0x07, 0xab, 0xeb, 0xbb, 0x6b, 0xfa, 0xd8,
186 0x94, 0xfe, 0x5a, 0x63, 0xcd, 0xc6, 0x02, 0x30,
187 0xfb, 0x89, 0xc8, 0xef, 0xd0, 0x9e, 0xcd, 0x7b,
190 0x20, 0xd7, 0x1b, 0xf1, 0x4a, 0x92, 0xbc, 0x48,
191 0x99, 0x1b, 0xb2, 0xd9, 0xd5, 0x17, 0xf4, 0xfa,
192 0x52, 0x28, 0xe1, 0x88, 0xaa, 0xa4, 0x1d, 0xe7,
193 0x86, 0xcc, 0x91, 0x18, 0x9d, 0xef, 0x80, 0x5d,
194 0x9b, 0x9f, 0x21, 0x30, 0xd4, 0x12, 0x20, 0xf8,
195 0x77, 0x1d, 0xdf, 0xbc, 0x32, 0x3c, 0xa4, 0xcd,
196 0x7a, 0xb1, 0x49, 0x04, 0xb0, 0x80, 0x13, 0xd2,
197 0xba, 0x31, 0x16, 0xf1, 0x67, 0xe7, 0x8e, 0x37,
200 a [64]uint64 // It is filled in init()
207 {0x8e, 0x20, 0xfa, 0xa7, 0x2b, 0xa0, 0xb4, 0x70},
208 {0x47, 0x10, 0x7d, 0xdd, 0x9b, 0x50, 0x5a, 0x38},
209 {0xad, 0x08, 0xb0, 0xe0, 0xc3, 0x28, 0x2d, 0x1c},
210 {0xd8, 0x04, 0x58, 0x70, 0xef, 0x14, 0x98, 0x0e},
211 {0x6c, 0x02, 0x2c, 0x38, 0xf9, 0x0a, 0x4c, 0x07},
212 {0x36, 0x01, 0x16, 0x1c, 0xf2, 0x05, 0x26, 0x8d},
213 {0x1b, 0x8e, 0x0b, 0x0e, 0x79, 0x8c, 0x13, 0xc8},
214 {0x83, 0x47, 0x8b, 0x07, 0xb2, 0x46, 0x87, 0x64},
215 {0xa0, 0x11, 0xd3, 0x80, 0x81, 0x8e, 0x8f, 0x40},
216 {0x50, 0x86, 0xe7, 0x40, 0xce, 0x47, 0xc9, 0x20},
217 {0x28, 0x43, 0xfd, 0x20, 0x67, 0xad, 0xea, 0x10},
218 {0x14, 0xaf, 0xf0, 0x10, 0xbd, 0xd8, 0x75, 0x08},
219 {0x0a, 0xd9, 0x78, 0x08, 0xd0, 0x6c, 0xb4, 0x04},
220 {0x05, 0xe2, 0x3c, 0x04, 0x68, 0x36, 0x5a, 0x02},
221 {0x8c, 0x71, 0x1e, 0x02, 0x34, 0x1b, 0x2d, 0x01},
222 {0x46, 0xb6, 0x0f, 0x01, 0x1a, 0x83, 0x98, 0x8e},
223 {0x90, 0xda, 0xb5, 0x2a, 0x38, 0x7a, 0xe7, 0x6f},
224 {0x48, 0x6d, 0xd4, 0x15, 0x1c, 0x3d, 0xfd, 0xb9},
225 {0x24, 0xb8, 0x6a, 0x84, 0x0e, 0x90, 0xf0, 0xd2},
226 {0x12, 0x5c, 0x35, 0x42, 0x07, 0x48, 0x78, 0x69},
227 {0x09, 0x2e, 0x94, 0x21, 0x8d, 0x24, 0x3c, 0xba},
228 {0x8a, 0x17, 0x4a, 0x9e, 0xc8, 0x12, 0x1e, 0x5d},
229 {0x45, 0x85, 0x25, 0x4f, 0x64, 0x09, 0x0f, 0xa0},
230 {0xac, 0xcc, 0x9c, 0xa9, 0x32, 0x8a, 0x89, 0x50},
231 {0x9d, 0x4d, 0xf0, 0x5d, 0x5f, 0x66, 0x14, 0x51},
232 {0xc0, 0xa8, 0x78, 0xa0, 0xa1, 0x33, 0x0a, 0xa6},
233 {0x60, 0x54, 0x3c, 0x50, 0xde, 0x97, 0x05, 0x53},
234 {0x30, 0x2a, 0x1e, 0x28, 0x6f, 0xc5, 0x8c, 0xa7},
235 {0x18, 0x15, 0x0f, 0x14, 0xb9, 0xec, 0x46, 0xdd},
236 {0x0c, 0x84, 0x89, 0x0a, 0xd2, 0x76, 0x23, 0xe0},
237 {0x06, 0x42, 0xca, 0x05, 0x69, 0x3b, 0x9f, 0x70},
238 {0x03, 0x21, 0x65, 0x8c, 0xba, 0x93, 0xc1, 0x38},
239 {0x86, 0x27, 0x5d, 0xf0, 0x9c, 0xe8, 0xaa, 0xa8},
240 {0x43, 0x9d, 0xa0, 0x78, 0x4e, 0x74, 0x55, 0x54},
241 {0xaf, 0xc0, 0x50, 0x3c, 0x27, 0x3a, 0xa4, 0x2a},
242 {0xd9, 0x60, 0x28, 0x1e, 0x9d, 0x1d, 0x52, 0x15},
243 {0xe2, 0x30, 0x14, 0x0f, 0xc0, 0x80, 0x29, 0x84},
244 {0x71, 0x18, 0x0a, 0x89, 0x60, 0x40, 0x9a, 0x42},
245 {0xb6, 0x0c, 0x05, 0xca, 0x30, 0x20, 0x4d, 0x21},
246 {0x5b, 0x06, 0x8c, 0x65, 0x18, 0x10, 0xa8, 0x9e},
247 {0x45, 0x6c, 0x34, 0x88, 0x7a, 0x38, 0x05, 0xb9},
248 {0xac, 0x36, 0x1a, 0x44, 0x3d, 0x1c, 0x8c, 0xd2},
249 {0x56, 0x1b, 0x0d, 0x22, 0x90, 0x0e, 0x46, 0x69},
250 {0x2b, 0x83, 0x88, 0x11, 0x48, 0x07, 0x23, 0xba},
251 {0x9b, 0xcf, 0x44, 0x86, 0x24, 0x8d, 0x9f, 0x5d},
252 {0xc3, 0xe9, 0x22, 0x43, 0x12, 0xc8, 0xc1, 0xa0},
253 {0xef, 0xfa, 0x11, 0xaf, 0x09, 0x64, 0xee, 0x50},
254 {0xf9, 0x7d, 0x86, 0xd9, 0x8a, 0x32, 0x77, 0x28},
255 {0xe4, 0xfa, 0x20, 0x54, 0xa8, 0x0b, 0x32, 0x9c},
256 {0x72, 0x7d, 0x10, 0x2a, 0x54, 0x8b, 0x19, 0x4e},
257 {0x39, 0xb0, 0x08, 0x15, 0x2a, 0xcb, 0x82, 0x27},
258 {0x92, 0x58, 0x04, 0x84, 0x15, 0xeb, 0x41, 0x9d},
259 {0x49, 0x2c, 0x02, 0x42, 0x84, 0xfb, 0xae, 0xc0},
260 {0xaa, 0x16, 0x01, 0x21, 0x42, 0xf3, 0x57, 0x60},
261 {0x55, 0x0b, 0x8e, 0x9e, 0x21, 0xf7, 0xa5, 0x30},
262 {0xa4, 0x8b, 0x47, 0x4f, 0x9e, 0xf5, 0xdc, 0x18},
263 {0x70, 0xa6, 0xa5, 0x6e, 0x24, 0x40, 0x59, 0x8e},
264 {0x38, 0x53, 0xdc, 0x37, 0x12, 0x20, 0xa2, 0x47},
265 {0x1c, 0xa7, 0x6e, 0x95, 0x09, 0x10, 0x51, 0xad},
266 {0x0e, 0xdd, 0x37, 0xc4, 0x8a, 0x08, 0xa6, 0xd8},
267 {0x07, 0xe0, 0x95, 0x62, 0x45, 0x04, 0x53, 0x6c},
268 {0x8d, 0x70, 0xc4, 0x31, 0xac, 0x02, 0xa7, 0x36},
269 {0xc8, 0x38, 0x62, 0x96, 0x56, 0x01, 0xdd, 0x1b},
270 {0x64, 0x1c, 0x31, 0x4b, 0x2b, 0x8e, 0xe0, 0x83},
272 for i := 0; i < 64; i++ {
273 a[i] = binary.BigEndian.Uint64(as[i])
275 for byteN := 0; byteN < 8; byteN++ {
276 for byteValN := 0; byteValN < 256; byteValN++ {
277 val := byte(byteValN)
279 for bitN := 0; bitN < 8; bitN++ {
281 res64 ^= a[(7-byteN)*8+bitN]
285 cache[byteN][byteValN] = res64
303 // Create new hash object with specified size digest size.
304 func New(size int) *Hash {
305 if size != 32 && size != 64 {
306 panic("size must be either 32 or 64")
310 hsh: make([]byte, BlockSize),
311 chk: make([]byte, BlockSize),
312 tmp: make([]byte, BlockSize),
313 psBuf: make([]byte, BlockSize),
314 eBuf: make([]byte, BlockSize),
315 gBuf: make([]byte, BlockSize),
316 addBuf: make([]byte, BlockSize),
322 func (h *Hash) Reset() {
325 for i := 0; i < BlockSize; i++ {
335 func (h *Hash) BlockSize() int {
339 func (h *Hash) Size() int {
343 func (h *Hash) Write(data []byte) (int, error) {
344 h.buf = append(h.buf, data...)
345 for len(h.buf) >= BlockSize {
346 copy(h.tmp, h.buf[:BlockSize])
347 h.hsh = h.g(h.n, h.hsh, h.tmp)
348 h.chk = h.add512bit(h.chk, h.tmp)
350 h.buf = h.buf[BlockSize:]
352 return len(data), nil
355 func (h *Hash) Sum(in []byte) []byte {
356 buf := make([]byte, BlockSize)
360 hsh := h.g(h.n, h.hsh, buf)
361 binary.LittleEndian.PutUint64(h.tmp, h.n+uint64(len(h.buf))*8)
362 hsh = h.g(0, hsh, h.tmp)
363 hsh = h.g(0, hsh, h.add512bit(h.chk, buf))
365 return append(in, hsh[BlockSize/2:]...)
367 return append(in, hsh...)
370 func (h *Hash) add512bit(chk, data []byte) []byte {
372 for i := 0; i < BlockSize; i++ {
373 ss = uint16(chk[i]) + uint16(data[i]) + (ss >> 8)
374 h.addBuf[i] = byte(0xFF & ss)
379 func (h *Hash) g(n uint64, hsh, data []byte) []byte {
380 r := make([]byte, BlockSize)
382 r[0] ^= byte((n >> 0) & 0xFF)
383 r[1] ^= byte((n >> 8) & 0xFF)
384 r[2] ^= byte((n >> 16) & 0xFF)
385 r[3] ^= byte((n >> 24) & 0xFF)
386 r[4] ^= byte((n >> 32) & 0xFF)
387 r[5] ^= byte((n >> 40) & 0xFF)
388 r[6] ^= byte((n >> 48) & 0xFF)
389 r[7] ^= byte((n >> 56) & 0xFF)
390 return blockXor(h.gBuf, blockXor(h.gBuf, h.e(l(r, h.ps(r)), data), hsh), data)
393 func (h *Hash) e(k, msg []byte) []byte {
394 msgBuf := make([]byte, BlockSize)
395 kBuf := make([]byte, BlockSize)
396 for i := 0; i < 12; i++ {
397 msg = l(msgBuf, h.ps(blockXor(h.eBuf, k, msg)))
398 k = l(kBuf, h.ps(blockXor(h.eBuf, k, c[i][:])))
400 return blockXor(h.eBuf, k, msg)
403 func blockXor(dst, x, y []byte) []byte {
404 for i := 0; i < BlockSize; i++ {
410 func (h *Hash) ps(data []byte) []byte {
411 for i := 0; i < BlockSize; i++ {
412 h.psBuf[tau[i]] = pi[int(data[i])]
417 func l(out, data []byte) []byte {
418 for i := 0; i < 8; i++ {
420 res64 ^= cache[0][data[8*i+0]]
421 res64 ^= cache[1][data[8*i+1]]
422 res64 ^= cache[2][data[8*i+2]]
423 res64 ^= cache[3][data[8*i+3]]
424 res64 ^= cache[4][data[8*i+4]]
425 res64 ^= cache[5][data[8*i+5]]
426 res64 ^= cache[6][data[8*i+6]]
427 res64 ^= cache[7][data[8*i+7]]
428 binary.LittleEndian.PutUint64(out[i*8:i*8+8], res64)
433 func (h *Hash) MarshalBinary() (data []byte, err error) {
434 data = make([]byte, len(MarshaledName)+1+8+2*BlockSize+len(h.buf))
435 copy(data, []byte(MarshaledName))
436 idx := len(MarshaledName)
437 data[idx] = byte(h.size)
439 binary.BigEndian.PutUint64(data[idx:idx+8], h.n)
441 copy(data[idx:], h.hsh)
443 copy(data[idx:], h.chk)
445 copy(data[idx:], h.buf)
449 func (h *Hash) UnmarshalBinary(data []byte) error {
450 expectedLen := len(MarshaledName) + 1 + 8 + 2*BlockSize
451 if len(data) < expectedLen {
452 return fmt.Errorf("gogost/internal/gost34112012: len(data) != %d", expectedLen)
454 if !bytes.HasPrefix(data, []byte(MarshaledName)) {
455 return errors.New("gogost/internal/gost34112012: no hash name prefix")
457 idx := len(MarshaledName)
458 h.size = int(data[idx])
460 h.n = binary.BigEndian.Uint64(data[idx : idx+8])
462 copy(h.hsh, data[idx:])
464 copy(h.chk, data[idx:])