1 // GoGOST -- Pure Go GOST cryptographic functions library
2 // Copyright (C) 2015-2022 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
305 // Create new hash object with specified size digest size.
306 func New(size int) *Hash {
307 if size != 32 && size != 64 {
308 panic("size must be either 32 or 64")
312 hsh: make([]byte, BlockSize),
313 chk: make([]byte, BlockSize),
314 tmp: make([]byte, BlockSize),
315 psBuf: make([]byte, BlockSize),
316 eMsgBuf: make([]byte, BlockSize),
317 eKBuf: make([]byte, BlockSize),
318 eXorBuf: make([]byte, BlockSize),
319 gBuf: make([]byte, BlockSize),
320 addBuf: make([]byte, BlockSize),
326 func (h *Hash) Reset() {
329 for i := 0; i < BlockSize; i++ {
339 func (h *Hash) BlockSize() int {
343 func (h *Hash) Size() int {
347 func (h *Hash) Write(data []byte) (int, error) {
348 h.buf = append(h.buf, data...)
349 for len(h.buf) >= BlockSize {
350 copy(h.tmp, h.buf[:BlockSize])
351 copy(h.hsh, h.g(h.n, h.hsh, h.tmp))
352 copy(h.chk, h.add512bit(h.chk, h.tmp))
354 h.buf = h.buf[BlockSize:]
356 return len(data), nil
359 func (h *Hash) Sum(in []byte) []byte {
360 buf := make([]byte, BlockSize)
361 hsh := make([]byte, BlockSize)
365 copy(hsh, h.g(h.n, h.hsh, buf))
366 binary.LittleEndian.PutUint64(h.tmp, h.n+uint64(len(h.buf))*8)
367 copy(hsh, h.g(0, hsh, h.tmp))
368 copy(hsh, h.g(0, hsh, h.add512bit(h.chk, buf)))
370 return append(in, hsh[BlockSize/2:]...)
372 return append(in, hsh...)
375 func (h *Hash) add512bit(chk, data []byte) []byte {
377 for i := 0; i < BlockSize; i++ {
378 ss = uint16(chk[i]) + uint16(data[i]) + (ss >> 8)
379 h.addBuf[i] = byte(0xFF & ss)
384 func (h *Hash) g(n uint64, hsh, data []byte) []byte {
387 out[0] ^= byte((n >> 0) & 0xFF)
388 out[1] ^= byte((n >> 8) & 0xFF)
389 out[2] ^= byte((n >> 16) & 0xFF)
390 out[3] ^= byte((n >> 24) & 0xFF)
391 out[4] ^= byte((n >> 32) & 0xFF)
392 out[5] ^= byte((n >> 40) & 0xFF)
393 out[6] ^= byte((n >> 48) & 0xFF)
394 out[7] ^= byte((n >> 56) & 0xFF)
395 return blockXor(out, blockXor(out, h.e(l(out, h.ps(out)), data), hsh), data)
398 func (h *Hash) e(k, msg []byte) []byte {
399 for i := 0; i < 12; i++ {
400 msg = l(h.eMsgBuf, h.ps(blockXor(h.eXorBuf, k, msg)))
401 k = l(h.eKBuf, h.ps(blockXor(h.eXorBuf, k, c[i][:])))
403 return blockXor(h.eXorBuf, k, msg)
406 func blockXor(dst, x, y []byte) []byte {
407 for i := 0; i < BlockSize; i++ {
413 func (h *Hash) ps(data []byte) []byte {
414 for i := 0; i < BlockSize; i++ {
415 h.psBuf[tau[i]] = pi[int(data[i])]
420 func l(out, data []byte) []byte {
421 for i := 0; i < 8; i++ {
423 res64 ^= cache[0][data[8*i+0]]
424 res64 ^= cache[1][data[8*i+1]]
425 res64 ^= cache[2][data[8*i+2]]
426 res64 ^= cache[3][data[8*i+3]]
427 res64 ^= cache[4][data[8*i+4]]
428 res64 ^= cache[5][data[8*i+5]]
429 res64 ^= cache[6][data[8*i+6]]
430 res64 ^= cache[7][data[8*i+7]]
431 binary.LittleEndian.PutUint64(out[i*8:i*8+8], res64)
436 func (h *Hash) MarshalBinary() (data []byte, err error) {
437 data = make([]byte, len(MarshaledName)+1+8+2*BlockSize+len(h.buf))
438 copy(data, []byte(MarshaledName))
439 idx := len(MarshaledName)
440 data[idx] = byte(h.size)
442 binary.BigEndian.PutUint64(data[idx:idx+8], h.n)
444 copy(data[idx:], h.hsh)
446 copy(data[idx:], h.chk)
448 copy(data[idx:], h.buf)
452 func (h *Hash) UnmarshalBinary(data []byte) error {
453 expectedLen := len(MarshaledName) + 1 + 8 + 2*BlockSize
454 if len(data) < expectedLen {
455 return fmt.Errorf("gogost/internal/gost34112012: len(data) != %d", expectedLen)
457 if !bytes.HasPrefix(data, []byte(MarshaledName)) {
458 return errors.New("gogost/internal/gost34112012: no hash name prefix")
460 idx := len(MarshaledName)
461 h.size = int(data[idx])
463 h.n = binary.BigEndian.Uint64(data[idx : idx+8])
465 copy(h.hsh, data[idx:])
467 copy(h.chk, data[idx:])