1 // GoGOST -- Pure Go GOST cryptographic functions library
2 // Copyright (C) 2015-2019 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()
205 []byte{0x8e, 0x20, 0xfa, 0xa7, 0x2b, 0xa0, 0xb4, 0x70},
206 []byte{0x47, 0x10, 0x7d, 0xdd, 0x9b, 0x50, 0x5a, 0x38},
207 []byte{0xad, 0x08, 0xb0, 0xe0, 0xc3, 0x28, 0x2d, 0x1c},
208 []byte{0xd8, 0x04, 0x58, 0x70, 0xef, 0x14, 0x98, 0x0e},
209 []byte{0x6c, 0x02, 0x2c, 0x38, 0xf9, 0x0a, 0x4c, 0x07},
210 []byte{0x36, 0x01, 0x16, 0x1c, 0xf2, 0x05, 0x26, 0x8d},
211 []byte{0x1b, 0x8e, 0x0b, 0x0e, 0x79, 0x8c, 0x13, 0xc8},
212 []byte{0x83, 0x47, 0x8b, 0x07, 0xb2, 0x46, 0x87, 0x64},
213 []byte{0xa0, 0x11, 0xd3, 0x80, 0x81, 0x8e, 0x8f, 0x40},
214 []byte{0x50, 0x86, 0xe7, 0x40, 0xce, 0x47, 0xc9, 0x20},
215 []byte{0x28, 0x43, 0xfd, 0x20, 0x67, 0xad, 0xea, 0x10},
216 []byte{0x14, 0xaf, 0xf0, 0x10, 0xbd, 0xd8, 0x75, 0x08},
217 []byte{0x0a, 0xd9, 0x78, 0x08, 0xd0, 0x6c, 0xb4, 0x04},
218 []byte{0x05, 0xe2, 0x3c, 0x04, 0x68, 0x36, 0x5a, 0x02},
219 []byte{0x8c, 0x71, 0x1e, 0x02, 0x34, 0x1b, 0x2d, 0x01},
220 []byte{0x46, 0xb6, 0x0f, 0x01, 0x1a, 0x83, 0x98, 0x8e},
221 []byte{0x90, 0xda, 0xb5, 0x2a, 0x38, 0x7a, 0xe7, 0x6f},
222 []byte{0x48, 0x6d, 0xd4, 0x15, 0x1c, 0x3d, 0xfd, 0xb9},
223 []byte{0x24, 0xb8, 0x6a, 0x84, 0x0e, 0x90, 0xf0, 0xd2},
224 []byte{0x12, 0x5c, 0x35, 0x42, 0x07, 0x48, 0x78, 0x69},
225 []byte{0x09, 0x2e, 0x94, 0x21, 0x8d, 0x24, 0x3c, 0xba},
226 []byte{0x8a, 0x17, 0x4a, 0x9e, 0xc8, 0x12, 0x1e, 0x5d},
227 []byte{0x45, 0x85, 0x25, 0x4f, 0x64, 0x09, 0x0f, 0xa0},
228 []byte{0xac, 0xcc, 0x9c, 0xa9, 0x32, 0x8a, 0x89, 0x50},
229 []byte{0x9d, 0x4d, 0xf0, 0x5d, 0x5f, 0x66, 0x14, 0x51},
230 []byte{0xc0, 0xa8, 0x78, 0xa0, 0xa1, 0x33, 0x0a, 0xa6},
231 []byte{0x60, 0x54, 0x3c, 0x50, 0xde, 0x97, 0x05, 0x53},
232 []byte{0x30, 0x2a, 0x1e, 0x28, 0x6f, 0xc5, 0x8c, 0xa7},
233 []byte{0x18, 0x15, 0x0f, 0x14, 0xb9, 0xec, 0x46, 0xdd},
234 []byte{0x0c, 0x84, 0x89, 0x0a, 0xd2, 0x76, 0x23, 0xe0},
235 []byte{0x06, 0x42, 0xca, 0x05, 0x69, 0x3b, 0x9f, 0x70},
236 []byte{0x03, 0x21, 0x65, 0x8c, 0xba, 0x93, 0xc1, 0x38},
237 []byte{0x86, 0x27, 0x5d, 0xf0, 0x9c, 0xe8, 0xaa, 0xa8},
238 []byte{0x43, 0x9d, 0xa0, 0x78, 0x4e, 0x74, 0x55, 0x54},
239 []byte{0xaf, 0xc0, 0x50, 0x3c, 0x27, 0x3a, 0xa4, 0x2a},
240 []byte{0xd9, 0x60, 0x28, 0x1e, 0x9d, 0x1d, 0x52, 0x15},
241 []byte{0xe2, 0x30, 0x14, 0x0f, 0xc0, 0x80, 0x29, 0x84},
242 []byte{0x71, 0x18, 0x0a, 0x89, 0x60, 0x40, 0x9a, 0x42},
243 []byte{0xb6, 0x0c, 0x05, 0xca, 0x30, 0x20, 0x4d, 0x21},
244 []byte{0x5b, 0x06, 0x8c, 0x65, 0x18, 0x10, 0xa8, 0x9e},
245 []byte{0x45, 0x6c, 0x34, 0x88, 0x7a, 0x38, 0x05, 0xb9},
246 []byte{0xac, 0x36, 0x1a, 0x44, 0x3d, 0x1c, 0x8c, 0xd2},
247 []byte{0x56, 0x1b, 0x0d, 0x22, 0x90, 0x0e, 0x46, 0x69},
248 []byte{0x2b, 0x83, 0x88, 0x11, 0x48, 0x07, 0x23, 0xba},
249 []byte{0x9b, 0xcf, 0x44, 0x86, 0x24, 0x8d, 0x9f, 0x5d},
250 []byte{0xc3, 0xe9, 0x22, 0x43, 0x12, 0xc8, 0xc1, 0xa0},
251 []byte{0xef, 0xfa, 0x11, 0xaf, 0x09, 0x64, 0xee, 0x50},
252 []byte{0xf9, 0x7d, 0x86, 0xd9, 0x8a, 0x32, 0x77, 0x28},
253 []byte{0xe4, 0xfa, 0x20, 0x54, 0xa8, 0x0b, 0x32, 0x9c},
254 []byte{0x72, 0x7d, 0x10, 0x2a, 0x54, 0x8b, 0x19, 0x4e},
255 []byte{0x39, 0xb0, 0x08, 0x15, 0x2a, 0xcb, 0x82, 0x27},
256 []byte{0x92, 0x58, 0x04, 0x84, 0x15, 0xeb, 0x41, 0x9d},
257 []byte{0x49, 0x2c, 0x02, 0x42, 0x84, 0xfb, 0xae, 0xc0},
258 []byte{0xaa, 0x16, 0x01, 0x21, 0x42, 0xf3, 0x57, 0x60},
259 []byte{0x55, 0x0b, 0x8e, 0x9e, 0x21, 0xf7, 0xa5, 0x30},
260 []byte{0xa4, 0x8b, 0x47, 0x4f, 0x9e, 0xf5, 0xdc, 0x18},
261 []byte{0x70, 0xa6, 0xa5, 0x6e, 0x24, 0x40, 0x59, 0x8e},
262 []byte{0x38, 0x53, 0xdc, 0x37, 0x12, 0x20, 0xa2, 0x47},
263 []byte{0x1c, 0xa7, 0x6e, 0x95, 0x09, 0x10, 0x51, 0xad},
264 []byte{0x0e, 0xdd, 0x37, 0xc4, 0x8a, 0x08, 0xa6, 0xd8},
265 []byte{0x07, 0xe0, 0x95, 0x62, 0x45, 0x04, 0x53, 0x6c},
266 []byte{0x8d, 0x70, 0xc4, 0x31, 0xac, 0x02, 0xa7, 0x36},
267 []byte{0xc8, 0x38, 0x62, 0x96, 0x56, 0x01, 0xdd, 0x1b},
268 []byte{0x64, 0x1c, 0x31, 0x4b, 0x2b, 0x8e, 0xe0, 0x83},
270 for i := 0; i < 64; i++ {
271 a[i] = binary.BigEndian.Uint64(as[i])
284 // Create new hash object with specified size digest size.
285 func New(size int) *Hash {
286 if size != 32 && size != 64 {
287 panic("size must be either 32 or 64")
291 hsh: new([BlockSize]byte),
292 chk: new([BlockSize]byte),
293 tmp: new([BlockSize]byte),
299 func (h *Hash) Reset() {
302 for i := 0; i < BlockSize; i++ {
312 func (h *Hash) BlockSize() int {
316 func (h *Hash) Size() int {
320 func (h *Hash) Write(data []byte) (int, error) {
321 h.buf = append(h.buf, data...)
322 for len(h.buf) >= BlockSize {
323 copy(h.tmp[:], h.buf[:BlockSize])
324 h.hsh = g(h.n, h.hsh, h.tmp)
325 h.chk = add512bit(h.chk, h.tmp)
327 h.buf = h.buf[BlockSize:]
329 return len(data), nil
332 func (h *Hash) Sum(in []byte) []byte {
333 buf := new([BlockSize]byte)
334 copy(h.tmp[:], buf[:])
335 copy(buf[:], h.buf[:])
337 hsh := g(h.n, h.hsh, buf)
338 binary.LittleEndian.PutUint64(h.tmp[:], h.n+uint64(len(h.buf))*8)
339 hsh = g(0, hsh, h.tmp)
340 hsh = g(0, hsh, add512bit(h.chk, buf))
342 return append(in, hsh[BlockSize/2:]...)
344 return append(in, hsh[:]...)
347 func add512bit(chk, data *[BlockSize]byte) *[BlockSize]byte {
349 r := new([BlockSize]byte)
350 for i := 0; i < BlockSize; i++ {
351 ss = uint16(chk[i]) + uint16(data[i]) + (ss >> 8)
352 r[i] = byte(0xFF & ss)
357 func g(n uint64, hsh, data *[BlockSize]byte) *[BlockSize]byte {
358 ns := make([]byte, 8)
359 binary.LittleEndian.PutUint64(ns, n)
360 r := new([BlockSize]byte)
361 for i := 0; i < 8; i++ {
362 r[i] = hsh[i] ^ ns[i]
365 return blockXor(blockXor(e(l(ps(r)), data), hsh), data)
368 func e(k, msg *[BlockSize]byte) *[BlockSize]byte {
369 for i := 0; i < 12; i++ {
370 msg = l(ps(blockXor(k, msg)))
371 k = l(ps(blockXor(k, &c[i])))
373 return blockXor(k, msg)
376 func blockXor(x, y *[BlockSize]byte) *[BlockSize]byte {
377 r := new([BlockSize]byte)
378 for i := 0; i < BlockSize; i++ {
384 func ps(data *[BlockSize]byte) *[BlockSize]byte {
385 r := new([BlockSize]byte)
386 for i := 0; i < BlockSize; i++ {
387 r[tau[i]] = pi[int(data[i])]
392 func l(data *[BlockSize]byte) *[BlockSize]byte {
396 r := new([BlockSize]byte)
397 for i := 0; i < 8; i++ {
398 val = binary.LittleEndian.Uint64(data[i*8 : i*8+8])
400 for j = 0; j < BlockSize; j++ {
401 if val&0x8000000000000000 > 0 {
406 binary.LittleEndian.PutUint64(r[i*8:i*8+8], res64)
411 func (h *Hash) MarshalBinary() (data []byte, err error) {
412 data = make([]byte, len(MarshaledName)+1+8+3*BlockSize+len(h.buf))
413 copy(data, []byte(MarshaledName))
414 idx := len(MarshaledName)
415 data[idx] = byte(h.size)
417 binary.BigEndian.PutUint64(data[idx:idx+8], h.n)
419 copy(data[idx:], h.hsh[:])
421 copy(data[idx:], h.chk[:])
423 copy(data[idx:], h.tmp[:])
425 copy(data[idx:], h.buf)
429 func (h *Hash) UnmarshalBinary(data []byte) error {
430 expectedLen := len(MarshaledName) + 1 + 8 + 3*BlockSize
431 if len(data) < expectedLen {
432 return fmt.Errorf("gogost/internal/gost34112012: len(data) != %d", expectedLen)
434 if !bytes.HasPrefix(data, []byte(MarshaledName)) {
435 return errors.New("gogost/internal/gost34112012: no hash name prefix")
437 idx := len(MarshaledName)
438 h.size = int(data[idx])
440 h.n = binary.BigEndian.Uint64(data[idx : idx+8])
442 copy(h.hsh[:], data[idx:])
444 copy(h.chk[:], data[idx:])
446 copy(h.tmp[:], data[idx:])