]> Cypherpunks.ru repositories - gogost.git/commitdiff
Separate GF^64 and GF^128 multiplier implementations
authorSergey Matveev <stargrave@stargrave.org>
Fri, 8 Oct 2021 09:38:10 +0000 (12:38 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Fri, 8 Oct 2021 11:07:57 +0000 (14:07 +0300)
mgm/mode.go
mgm/mode_test.go
mgm/mul128.go [new file with mode: 0644]
mgm/mul128_test.go [moved from mgm/mul_test.go with 62% similarity]
mgm/mul64.go [new file with mode: 0644]
mgm/mul64_test.go [moved from mgm/mul.go with 58% similarity]

index c281567fbaf9ceb8dc33777314e2122788064a7b..38b9ab349cc6bc290e8a8b3367a8890ca00fba17 100644 (file)
@@ -21,22 +21,10 @@ import (
        "crypto/hmac"
        "encoding/binary"
        "errors"
        "crypto/hmac"
        "encoding/binary"
        "errors"
-       "math/big"
 )
 
 )
 
-var (
-       R64  *big.Int = big.NewInt(0)
-       R128 *big.Int = big.NewInt(0)
-)
-
-func init() {
-       R64.SetBytes([]byte{
-               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
-       })
-       R128.SetBytes([]byte{
-               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87,
-       })
+type Mul interface {
+       Mul(x, y []byte) []byte
 }
 
 type MGM struct {
 }
 
 type MGM struct {
@@ -49,13 +37,7 @@ type MGM struct {
        bufC      []byte
        padded    []byte
        sum       []byte
        bufC      []byte
        padded    []byte
        sum       []byte
-
-       x      *big.Int
-       y      *big.Int
-       z      *big.Int
-       maxBit int
-       r      *big.Int
-       mulBuf []byte
+       mul       Mul
 }
 
 func NewMGM(cipher cipher.Block, tagSize int) (cipher.AEAD, error) {
 }
 
 func NewMGM(cipher cipher.Block, tagSize int) (cipher.AEAD, error) {
@@ -76,17 +58,11 @@ func NewMGM(cipher cipher.Block, tagSize int) (cipher.AEAD, error) {
                bufC:      make([]byte, blockSize),
                padded:    make([]byte, blockSize),
                sum:       make([]byte, blockSize),
                bufC:      make([]byte, blockSize),
                padded:    make([]byte, blockSize),
                sum:       make([]byte, blockSize),
-               x:         big.NewInt(0),
-               y:         big.NewInt(0),
-               z:         big.NewInt(0),
-               mulBuf:    make([]byte, blockSize),
        }
        if blockSize == 8 {
        }
        if blockSize == 8 {
-               mgm.maxBit = 64 - 1
-               mgm.r = R64
+               mgm.mul = newMul64()
        } else {
        } else {
-               mgm.maxBit = 128 - 1
-               mgm.r = R128
+               mgm.mul = newMul128()
        }
        return &mgm, nil
 }
        }
        return &mgm, nil
 }
@@ -148,7 +124,7 @@ func (mgm *MGM) auth(out, text, ad []byte) {
                xor(                                   // sum (xor)= H_i (x) A_i
                        mgm.sum,
                        mgm.sum,
                xor(                                   // sum (xor)= H_i (x) A_i
                        mgm.sum,
                        mgm.sum,
-                       mgm.mul(mgm.bufC, ad[:mgm.BlockSize]),
+                       mgm.mul.Mul(mgm.bufC, ad[:mgm.BlockSize]),
                )
                incr(mgm.bufP[:mgm.BlockSize/2]) // Z_{i+1} = incr_l(Z_i)
                ad = ad[mgm.BlockSize:]
                )
                incr(mgm.bufP[:mgm.BlockSize/2]) // Z_{i+1} = incr_l(Z_i)
                ad = ad[mgm.BlockSize:]
@@ -159,7 +135,7 @@ func (mgm *MGM) auth(out, text, ad []byte) {
                        mgm.padded[i] = 0
                }
                mgm.cipher.Encrypt(mgm.bufC, mgm.bufP)
                        mgm.padded[i] = 0
                }
                mgm.cipher.Encrypt(mgm.bufC, mgm.bufP)
-               xor(mgm.sum, mgm.sum, mgm.mul(mgm.bufC, mgm.padded))
+               xor(mgm.sum, mgm.sum, mgm.mul.Mul(mgm.bufC, mgm.padded))
                incr(mgm.bufP[:mgm.BlockSize/2])
        }
 
                incr(mgm.bufP[:mgm.BlockSize/2])
        }
 
@@ -168,7 +144,7 @@ func (mgm *MGM) auth(out, text, ad []byte) {
                xor(                                   // sum (xor)= H_{h+j} (x) C_j
                        mgm.sum,
                        mgm.sum,
                xor(                                   // sum (xor)= H_{h+j} (x) C_j
                        mgm.sum,
                        mgm.sum,
-                       mgm.mul(mgm.bufC, text[:mgm.BlockSize]),
+                       mgm.mul.Mul(mgm.bufC, text[:mgm.BlockSize]),
                )
                incr(mgm.bufP[:mgm.BlockSize/2]) // Z_{h+j+1} = incr_l(Z_{h+j})
                text = text[mgm.BlockSize:]
                )
                incr(mgm.bufP[:mgm.BlockSize/2]) // Z_{h+j+1} = incr_l(Z_{h+j})
                text = text[mgm.BlockSize:]
@@ -179,7 +155,7 @@ func (mgm *MGM) auth(out, text, ad []byte) {
                        mgm.padded[i] = 0
                }
                mgm.cipher.Encrypt(mgm.bufC, mgm.bufP)
                        mgm.padded[i] = 0
                }
                mgm.cipher.Encrypt(mgm.bufC, mgm.bufP)
-               xor(mgm.sum, mgm.sum, mgm.mul(mgm.bufC, mgm.padded))
+               xor(mgm.sum, mgm.sum, mgm.mul.Mul(mgm.bufC, mgm.padded))
                incr(mgm.bufP[:mgm.BlockSize/2])
        }
 
                incr(mgm.bufP[:mgm.BlockSize/2])
        }
 
@@ -193,7 +169,7 @@ func (mgm *MGM) auth(out, text, ad []byte) {
                binary.BigEndian.PutUint64(mgm.bufC[mgm.BlockSize/2:], uint64(textLen))
        }
        // sum (xor)= H_{h+q+1} (x) (len(A) || len(C))
                binary.BigEndian.PutUint64(mgm.bufC[mgm.BlockSize/2:], uint64(textLen))
        }
        // sum (xor)= H_{h+q+1} (x) (len(A) || len(C))
-       xor(mgm.sum, mgm.sum, mgm.mul(mgm.bufP, mgm.bufC))
+       xor(mgm.sum, mgm.sum, mgm.mul.Mul(mgm.bufC, mgm.bufP))
        mgm.cipher.Encrypt(mgm.bufP, mgm.sum) // E_K(sum)
        copy(out, mgm.bufP[:mgm.TagSize])     // MSB_S(E_K(sum))
 }
        mgm.cipher.Encrypt(mgm.bufP, mgm.sum) // E_K(sum)
        copy(out, mgm.bufP[:mgm.TagSize])     // MSB_S(E_K(sum))
 }
index 7d1d984316915227bdc46fe957a570175572fbea..984ea483f9b27b8b90e01507c3bbbd289467cadc 100644 (file)
@@ -19,6 +19,7 @@ import (
        "bytes"
        "crypto/cipher"
        "crypto/rand"
        "bytes"
        "crypto/cipher"
        "crypto/rand"
+       "io"
        "testing"
        "testing/quick"
 
        "testing"
        "testing/quick"
 
@@ -145,3 +146,55 @@ func TestSymmetric(t *testing.T) {
                nonce[:gost341264.BlockSize],
        )
 }
                nonce[:gost341264.BlockSize],
        )
 }
+
+func BenchmarkMGM64(b *testing.B) {
+       key := make([]byte, gost341264.KeySize)
+       if _, err := io.ReadFull(rand.Reader, key); err != nil {
+               panic(err)
+       }
+       nonce := make([]byte, gost341264.BlockSize)
+       if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+               panic(err)
+       }
+       nonce[0] &= 0x7F
+       pt := make([]byte, 1280+3)
+       if _, err := io.ReadFull(rand.Reader, pt); err != nil {
+               panic(err)
+       }
+       c := gost341264.NewCipher(key)
+       aead, err := NewMGM(c, gost341264.BlockSize)
+       if err != nil {
+               panic(err)
+       }
+       ct := make([]byte, len(pt)+aead.Overhead())
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               aead.Seal(ct[:0], nonce, pt, nil)
+       }
+}
+
+func BenchmarkMGM128(b *testing.B) {
+       key := make([]byte, gost3412128.KeySize)
+       if _, err := io.ReadFull(rand.Reader, key); err != nil {
+               panic(err)
+       }
+       nonce := make([]byte, gost3412128.BlockSize)
+       if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
+               panic(err)
+       }
+       nonce[0] &= 0x7F
+       pt := make([]byte, 1280+3)
+       if _, err := io.ReadFull(rand.Reader, pt); err != nil {
+               panic(err)
+       }
+       c := gost3412128.NewCipher(key)
+       aead, err := NewMGM(c, gost3412128.BlockSize)
+       if err != nil {
+               panic(err)
+       }
+       ct := make([]byte, len(pt)+aead.Overhead())
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               aead.Seal(ct[:0], nonce, pt, nil)
+       }
+}
diff --git a/mgm/mul128.go b/mgm/mul128.go
new file mode 100644 (file)
index 0000000..07f105b
--- /dev/null
@@ -0,0 +1,68 @@
+// GoGOST -- Pure Go GOST cryptographic functions library
+// Copyright (C) 2015-2021 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, version 3 of the License.
+//
+// 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 mgm
+
+import (
+       "math/big"
+)
+
+const Mul128MaxBit = 128 - 1
+
+var R128 = big.NewInt(0).SetBytes([]byte{
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87,
+})
+
+type mul128 struct {
+       x   *big.Int
+       y   *big.Int
+       z   *big.Int
+       buf [16]byte
+}
+
+func newMul128() *mul128 {
+       return &mul128{
+               x: big.NewInt(0),
+               y: big.NewInt(0),
+               z: big.NewInt(0),
+       }
+}
+
+func (mul *mul128) Mul(x, y []byte) []byte {
+       mul.x.SetBytes(x)
+       mul.y.SetBytes(y)
+       mul.z.SetInt64(0)
+       for mul.y.BitLen() != 0 {
+               if mul.y.Bit(0) == 1 {
+                       mul.z.Xor(mul.z, mul.x)
+               }
+               if mul.x.Bit(Mul128MaxBit) == 1 {
+                       mul.x.SetBit(mul.x, Mul128MaxBit, 0)
+                       mul.x.Lsh(mul.x, 1)
+                       mul.x.Xor(mul.x, R128)
+               } else {
+                       mul.x.Lsh(mul.x, 1)
+               }
+               mul.y.Rsh(mul.y, 1)
+       }
+       zBytes := mul.z.Bytes()
+       rem := len(x) - len(zBytes)
+       for i := 0; i < rem; i++ {
+               mul.buf[i] = 0
+       }
+       copy(mul.buf[rem:], zBytes)
+       return mul.buf[:]
+}
similarity index 62%
rename from mgm/mul_test.go
rename to mgm/mul128_test.go
index b585799e604c2ab8aef1b2b0fae03b93b874edab..06548801fa677fad29f626d4653a446e55215a0a 100644 (file)
@@ -17,47 +17,19 @@ package mgm
 
 import (
        "crypto/rand"
 
 import (
        "crypto/rand"
-       "math/big"
        "testing"
 
        "go.cypherpunks.ru/gogost/v5/gost3412128"
        "testing"
 
        "go.cypherpunks.ru/gogost/v5/gost3412128"
-       "go.cypherpunks.ru/gogost/v5/gost341264"
 )
 
 )
 
-func BenchmarkMul64(b *testing.B) {
-       x := make([]byte, gost341264.BlockSize)
-       y := make([]byte, gost341264.BlockSize)
-       rand.Read(x)
-       rand.Read(y)
-       mgm := MGM{
-               x:      big.NewInt(0),
-               y:      big.NewInt(0),
-               z:      big.NewInt(0),
-               maxBit: 64 - 1,
-               r:      R64,
-               mulBuf: make([]byte, gost341264.BlockSize),
-       }
-       b.ResetTimer()
-       for i := 0; i < b.N; i++ {
-               mgm.mul(x, y)
-       }
-}
-
 func BenchmarkMul128(b *testing.B) {
        x := make([]byte, gost3412128.BlockSize)
        y := make([]byte, gost3412128.BlockSize)
        rand.Read(x)
        rand.Read(y)
 func BenchmarkMul128(b *testing.B) {
        x := make([]byte, gost3412128.BlockSize)
        y := make([]byte, gost3412128.BlockSize)
        rand.Read(x)
        rand.Read(y)
-       mgm := MGM{
-               x:      big.NewInt(0),
-               y:      big.NewInt(0),
-               z:      big.NewInt(0),
-               maxBit: 128 - 1,
-               r:      R128,
-               mulBuf: make([]byte, gost3412128.BlockSize),
-       }
+       mul := newMul128()
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
-               mgm.mul(x, y)
+               mul.Mul(x, y)
        }
 }
        }
 }
diff --git a/mgm/mul64.go b/mgm/mul64.go
new file mode 100644 (file)
index 0000000..4d3ccd0
--- /dev/null
@@ -0,0 +1,65 @@
+// GoGOST -- Pure Go GOST cryptographic functions library
+// Copyright (C) 2015-2021 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, version 3 of the License.
+//
+// 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 mgm
+
+import "math/big"
+
+const Mul64MaxBit = 64 - 1
+
+var R64 = big.NewInt(0).SetBytes([]byte{
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b,
+})
+
+type mul64 struct {
+       x   *big.Int
+       y   *big.Int
+       z   *big.Int
+       buf [8]byte
+}
+
+func newMul64() *mul64 {
+       return &mul64{
+               x: big.NewInt(0),
+               y: big.NewInt(0),
+               z: big.NewInt(0),
+       }
+}
+
+func (mul *mul64) Mul(x, y []byte) []byte {
+       mul.x.SetBytes(x)
+       mul.y.SetBytes(y)
+       mul.z.SetInt64(0)
+       for mul.y.BitLen() != 0 {
+               if mul.y.Bit(0) == 1 {
+                       mul.z.Xor(mul.z, mul.x)
+               }
+               if mul.x.Bit(Mul64MaxBit) == 1 {
+                       mul.x.SetBit(mul.x, Mul64MaxBit, 0)
+                       mul.x.Lsh(mul.x, 1)
+                       mul.x.Xor(mul.x, R64)
+               } else {
+                       mul.x.Lsh(mul.x, 1)
+               }
+               mul.y.Rsh(mul.y, 1)
+       }
+       zBytes := mul.z.Bytes()
+       rem := len(x) - len(zBytes)
+       for i := 0; i < rem; i++ {
+               mul.buf[i] = 0
+       }
+       copy(mul.buf[rem:], zBytes)
+       return mul.buf[:]
+}
similarity index 58%
rename from mgm/mul.go
rename to mgm/mul64_test.go
index 8fec46619ded35d6e7fb430492254366a22c2060..43411cd948dd18c3ae6ad4f5a4fc344da555a2b5 100644 (file)
 
 package mgm
 
 
 package mgm
 
-func (mgm *MGM) mul(xBuf, yBuf []byte) []byte {
-       mgm.x.SetBytes(xBuf)
-       mgm.y.SetBytes(yBuf)
-       mgm.z.SetInt64(0)
-       for mgm.y.BitLen() != 0 {
-               if mgm.y.Bit(0) == 1 {
-                       mgm.z.Xor(mgm.z, mgm.x)
-               }
-               if mgm.x.Bit(mgm.maxBit) == 1 {
-                       mgm.x.SetBit(mgm.x, mgm.maxBit, 0)
-                       mgm.x.Lsh(mgm.x, 1)
-                       mgm.x.Xor(mgm.x, mgm.r)
-               } else {
-                       mgm.x.Lsh(mgm.x, 1)
-               }
-               mgm.y.Rsh(mgm.y, 1)
-       }
-       zBytes := mgm.z.Bytes()
-       rem := len(xBuf) - len(zBytes)
-       for i := 0; i < rem; i++ {
-               mgm.mulBuf[i] = 0
+import (
+       "crypto/rand"
+       "testing"
+
+       "go.cypherpunks.ru/gogost/v5/gost341264"
+)
+
+func BenchmarkMul64(b *testing.B) {
+       x := make([]byte, gost341264.BlockSize)
+       y := make([]byte, gost341264.BlockSize)
+       rand.Read(x)
+       rand.Read(y)
+       mul := newMul64()
+       b.ResetTimer()
+       for i := 0; i < b.N; i++ {
+               mul.Mul(x, y)
        }
        }
-       copy(mgm.mulBuf[rem:], zBytes)
-       return mgm.mulBuf
 }
 }