1 // GoGOST -- Pure Go GOST cryptographic functions library
2 // Copyright (C) 2015-2023 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/>.
24 func WrapGost(ukm, kek, cek []byte) []byte {
25 c := NewCipher(kek, &SboxIdGost2814789CryptoProAParamSet)
26 mac, err := c.NewMAC(4, ukm)
30 _, err = mac.Write(cek)
34 cekMac := mac.Sum(nil)
35 cekEnc := make([]byte, 32)
36 c.NewECBEncrypter().CryptBlocks(cekEnc, cek)
37 return bytes.Join([][]byte{ukm, cekEnc, cekMac}, nil)
40 func UnwrapGost(kek, data []byte) []byte {
41 ukm, data := data[:8], data[8:]
42 cekEnc, cekMac := data[:KeySize], data[KeySize:]
43 c := NewCipher(kek, &SboxIdGost2814789CryptoProAParamSet)
44 cek := make([]byte, 32)
45 c.NewECBDecrypter().CryptBlocks(cek, cekEnc)
46 mac, err := c.NewMAC(4, ukm)
50 _, err = mac.Write(cek)
54 if subtle.ConstantTimeCompare(mac.Sum(nil), cekMac) != 1 {
60 func DiversifyCryptoPro(kek, ukm []byte) []byte {
62 for i := 0; i < 8; i++ {
64 for j := 0; j < 8; j++ {
65 k := binary.LittleEndian.Uint32(out[j*4 : j*4+4])
66 if (ukm[i]>>j)&1 > 0 {
73 binary.LittleEndian.PutUint32(iv[:4], uint32(s1%(1<<32)))
74 binary.LittleEndian.PutUint32(iv[4:], uint32(s2%(1<<32)))
75 c := NewCipher(out, &SboxIdGost2814789CryptoProAParamSet)
76 c.NewCFBEncrypter(iv).XORKeyStream(out, out)
81 func UnwrapCryptoPro(kek, data []byte) []byte {
82 return UnwrapGost(DiversifyCryptoPro(kek, data[:8]), data)