--- /dev/null
+// GoGOST -- Pure Go GOST cryptographic functions library
+// Copyright (C) 2015-2019 Sergey Matveev <stargrave@stargrave.org>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+// GOST 34.12-2015 64-bit (Магма (Magma)) block cipher.
+package gost341264
+
+import (
+ "cypherpunks.ru/gogost/gost28147"
+)
+
+const (
+ BlockSize = 8
+ KeySize = 32
+)
+
+type Cipher struct {
+ c *gost28147.Cipher
+ blk *[BlockSize]byte
+}
+
+func NewCipher(key [KeySize]byte) *Cipher {
+ keyCompatible := new([KeySize]byte)
+ for i := 0; i < KeySize/4; i++ {
+ keyCompatible[i*4+0] = key[i*4+3]
+ keyCompatible[i*4+1] = key[i*4+2]
+ keyCompatible[i*4+2] = key[i*4+1]
+ keyCompatible[i*4+3] = key[i*4+0]
+ }
+ return &Cipher{
+ c: gost28147.NewCipher(*keyCompatible, &gost28147.Gost28147_tc26_ParamZ),
+ blk: new([BlockSize]byte),
+ }
+}
+
+func (c *Cipher) BlockSize() int {
+ return BlockSize
+}
+
+func (c *Cipher) Encrypt(dst, src []byte) {
+ c.blk[0] = src[7]
+ c.blk[1] = src[6]
+ c.blk[2] = src[5]
+ c.blk[3] = src[4]
+ c.blk[4] = src[3]
+ c.blk[5] = src[2]
+ c.blk[6] = src[1]
+ c.blk[7] = src[0]
+ c.c.Encrypt(c.blk[:], c.blk[:])
+ dst[0] = c.blk[7]
+ dst[1] = c.blk[6]
+ dst[2] = c.blk[5]
+ dst[3] = c.blk[4]
+ dst[4] = c.blk[3]
+ dst[5] = c.blk[2]
+ dst[6] = c.blk[1]
+ dst[7] = c.blk[0]
+}
+
+func (c *Cipher) Decrypt(dst, src []byte) {
+ c.blk[0] = src[7]
+ c.blk[1] = src[6]
+ c.blk[2] = src[5]
+ c.blk[3] = src[4]
+ c.blk[4] = src[3]
+ c.blk[5] = src[2]
+ c.blk[6] = src[1]
+ c.blk[7] = src[0]
+ c.c.Decrypt(c.blk[:], c.blk[:])
+ dst[0] = c.blk[7]
+ dst[1] = c.blk[6]
+ dst[2] = c.blk[5]
+ dst[3] = c.blk[4]
+ dst[4] = c.blk[3]
+ dst[5] = c.blk[2]
+ dst[6] = c.blk[1]
+ dst[7] = c.blk[0]
+}
--- /dev/null
+// GoGOST -- Pure Go GOST cryptographic functions library
+// Copyright (C) 2015-2019 Sergey Matveev <stargrave@stargrave.org>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+package gost341264
+
+import (
+ "bytes"
+ "crypto/cipher"
+ "testing"
+)
+
+func TestCipherInterface(t *testing.T) {
+ var key [32]byte
+ var _ cipher.Block = NewCipher(key)
+}
+
+func TestVector(t *testing.T) {
+ key := [KeySize]byte{
+ 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88,
+ 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ }
+ pt := [BlockSize]byte{0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
+ ct := [BlockSize]byte{0x4e, 0xe9, 0x01, 0xe5, 0xc2, 0xd8, 0xca, 0x3d}
+ c := NewCipher(key)
+ dst := make([]byte, BlockSize)
+ c.Encrypt(dst, pt[:])
+ if bytes.Compare(dst, ct[:]) != 0 {
+ t.FailNow()
+ }
+ c.Decrypt(dst, dst)
+ if bytes.Compare(dst, pt[:]) != 0 {
+ t.FailNow()
+ }
+}