From 9009082ff15ac83ea5923042c22891b6b525bc72 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Thu, 21 Jan 2021 21:50:00 +0300 Subject: [PATCH] Calculations cache for 34.12-2015-128 --- gogost.go | 2 +- gost3412128/cipher.go | 169 ++++++++++++++++++++++++------------- gost3412128/cipher_test.go | 33 +++++--- news.texi | 4 + 4 files changed, 132 insertions(+), 76 deletions(-) diff --git a/gogost.go b/gogost.go index ed45ddf..d373248 100644 --- a/gogost.go +++ b/gogost.go @@ -1,4 +1,4 @@ // Pure Go GOST cryptographic functions library. package gogost -const Version = "5.2.0" +const Version = "5.3.0" diff --git a/gost3412128/cipher.go b/gost3412128/cipher.go index fd48d8b..cbc2b3e 100644 --- a/gost3412128/cipher.go +++ b/gost3412128/cipher.go @@ -51,8 +51,9 @@ var ( 190, 229, 108, 82, 89, 166, 116, 210, 230, 244, 180, 192, 209, 102, 175, 194, 57, 75, 99, 182, } - piInv [256]byte - cBlk [32]*[BlockSize]byte + piInv [256]byte + cBlk [32][]byte + gfCache [256][256]byte ) func gf(a, b byte) (c byte) { @@ -70,61 +71,108 @@ func gf(a, b byte) (c byte) { return } -func l(blk *[BlockSize]byte, rounds int) { - var t byte - var i int - for ; rounds > 0; rounds-- { - t = blk[15] - for i = 14; i >= 0; i-- { - blk[i+1] = blk[i] - t ^= gf(blk[i], lc[i]) - } +func l(blk []byte) { + for n := 0; n < BlockSize; n++ { + t := blk[15] + t ^= gfCache[blk[0]][lc[0]] + t ^= gfCache[blk[1]][lc[1]] + t ^= gfCache[blk[2]][lc[2]] + t ^= gfCache[blk[3]][lc[3]] + t ^= gfCache[blk[4]][lc[4]] + t ^= gfCache[blk[5]][lc[5]] + t ^= gfCache[blk[6]][lc[6]] + t ^= gfCache[blk[7]][lc[7]] + t ^= gfCache[blk[8]][lc[8]] + t ^= gfCache[blk[9]][lc[9]] + t ^= gfCache[blk[10]][lc[10]] + t ^= gfCache[blk[11]][lc[11]] + t ^= gfCache[blk[12]][lc[12]] + t ^= gfCache[blk[13]][lc[13]] + t ^= gfCache[blk[14]][lc[14]] + copy(blk[1:], blk) blk[0] = t } } -func lInv(blk *[BlockSize]byte) { - var t byte - var i int +func lInv(blk []byte) { for n := 0; n < BlockSize; n++ { - t = blk[0] - for i = 0; i < 15; i++ { - blk[i] = blk[i+1] - t ^= gf(blk[i], lc[i]) - } + t := blk[0] + copy(blk, blk[1:]) + t ^= gfCache[blk[0]][lc[0]] + t ^= gfCache[blk[1]][lc[1]] + t ^= gfCache[blk[2]][lc[2]] + t ^= gfCache[blk[3]][lc[3]] + t ^= gfCache[blk[4]][lc[4]] + t ^= gfCache[blk[5]][lc[5]] + t ^= gfCache[blk[6]][lc[6]] + t ^= gfCache[blk[7]][lc[7]] + t ^= gfCache[blk[8]][lc[8]] + t ^= gfCache[blk[9]][lc[9]] + t ^= gfCache[blk[10]][lc[10]] + t ^= gfCache[blk[11]][lc[11]] + t ^= gfCache[blk[12]][lc[12]] + t ^= gfCache[blk[13]][lc[13]] + t ^= gfCache[blk[14]][lc[14]] blk[15] = t } } func init() { - piInvP := new([256]byte) + for a := 0; a < 256; a++ { + for b := 0; b < 256; b++ { + gfCache[a][b] = gf(byte(a), byte(b)) + } + } for i := 0; i < 256; i++ { - piInvP[int(pi[i])] = byte(i) + piInv[int(pi[i])] = byte(i) } - piInv = *piInvP - CP := new([32]*[BlockSize]byte) for i := 0; i < 32; i++ { - CP[i] = new([BlockSize]byte) - CP[i][15] = byte(i) + 1 - l(CP[i], 16) + cBlk[i] = make([]byte, BlockSize) + cBlk[i][15] = byte(i) + 1 + l(cBlk[i]) } - cBlk = *CP } -func s(blk *[BlockSize]byte) { - for i := 0; i < BlockSize; i++ { - blk[i] = pi[int(blk[i])] - } +func s(blk []byte) { + blk[0] = pi[int(blk[0])] + blk[1] = pi[int(blk[1])] + blk[2] = pi[int(blk[2])] + blk[3] = pi[int(blk[3])] + blk[4] = pi[int(blk[4])] + blk[5] = pi[int(blk[5])] + blk[6] = pi[int(blk[6])] + blk[7] = pi[int(blk[7])] + blk[8] = pi[int(blk[8])] + blk[9] = pi[int(blk[9])] + blk[10] = pi[int(blk[10])] + blk[11] = pi[int(blk[11])] + blk[12] = pi[int(blk[12])] + blk[13] = pi[int(blk[13])] + blk[14] = pi[int(blk[14])] + blk[15] = pi[int(blk[15])] } -func xor(dst, src1, src2 *[BlockSize]byte) { - for i := 0; i < BlockSize; i++ { - dst[i] = src1[i] ^ src2[i] - } +func xor(dst, src1, src2 []byte) { + dst[0] = src1[0] ^ src2[0] + dst[1] = src1[1] ^ src2[1] + dst[2] = src1[2] ^ src2[2] + dst[3] = src1[3] ^ src2[3] + dst[4] = src1[4] ^ src2[4] + dst[5] = src1[5] ^ src2[5] + dst[6] = src1[6] ^ src2[6] + dst[7] = src1[7] ^ src2[7] + dst[8] = src1[8] ^ src2[8] + dst[9] = src1[9] ^ src2[9] + dst[10] = src1[10] ^ src2[10] + dst[11] = src1[11] ^ src2[11] + dst[12] = src1[12] ^ src2[12] + dst[13] = src1[13] ^ src2[13] + dst[14] = src1[14] ^ src2[14] + dst[15] = src1[15] ^ src2[15] } type Cipher struct { - ks [10]*[BlockSize]byte + ks [10][]byte } func (c *Cipher) BlockSize() int { @@ -135,48 +183,47 @@ func NewCipher(key []byte) *Cipher { if len(key) != KeySize { panic("invalid key size") } - ks := new([10]*[BlockSize]byte) - kr0 := new([BlockSize]byte) - kr1 := new([BlockSize]byte) - krt := new([BlockSize]byte) - copy(kr0[:], key[:BlockSize]) - copy(kr1[:], key[BlockSize:]) - ks[0] = new([BlockSize]byte) - ks[1] = new([BlockSize]byte) - copy(ks[0][:], kr0[:]) - copy(ks[1][:], kr1[:]) + var ks [10][]byte + for i := 0; i < len(ks); i++ { + ks[i] = make([]byte, BlockSize) + } + kr0 := make([]byte, BlockSize) + kr1 := make([]byte, BlockSize) + krt := make([]byte, BlockSize) + copy(kr0, key[:BlockSize]) + copy(kr1, key[BlockSize:]) + copy(ks[0], kr0) + copy(ks[1], kr1) for i := 0; i < 4; i++ { for j := 0; j < 8; j++ { xor(krt, kr0, cBlk[8*i+j]) s(krt) - l(krt, 16) + l(krt) xor(krt, krt, kr1) - copy(kr1[:], kr0[:]) - copy(kr0[:], krt[:]) + copy(kr1, kr0) + copy(kr0, krt) } - ks[2+2*i] = new([BlockSize]byte) - copy(ks[2+2*i][:], kr0[:]) - ks[2+2*i+1] = new([BlockSize]byte) - copy(ks[2+2*i+1][:], kr1[:]) + copy(ks[2+2*i], kr0) + copy(ks[2+2*i+1], kr1) } - return &Cipher{*ks} + return &Cipher{ks} } func (c *Cipher) Encrypt(dst, src []byte) { - blk := new([BlockSize]byte) - copy(blk[:], src) + blk := make([]byte, BlockSize) + copy(blk, src) for i := 0; i < 9; i++ { xor(blk, blk, c.ks[i]) s(blk) - l(blk, 16) + l(blk) } xor(blk, blk, c.ks[9]) - copy(dst[:BlockSize], blk[:]) + copy(dst[:BlockSize], blk) } func (c *Cipher) Decrypt(dst, src []byte) { - blk := new([BlockSize]byte) - copy(blk[:], src) + blk := make([]byte, BlockSize) + copy(blk, src) var n int for i := 9; i > 0; i-- { xor(blk, blk, c.ks[i]) @@ -186,5 +233,5 @@ func (c *Cipher) Decrypt(dst, src []byte) { } } xor(blk, blk, c.ks[0]) - copy(dst[:BlockSize], blk[:]) + copy(dst[:BlockSize], blk) } diff --git a/gost3412128/cipher_test.go b/gost3412128/cipher_test.go index f574245..f25b6d3 100644 --- a/gost3412128/cipher_test.go +++ b/gost3412128/cipher_test.go @@ -86,28 +86,28 @@ func TestS(t *testing.T) { 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, } - s(&blk) + s(blk[:]) if bytes.Compare(blk[:], []byte{ 0xb6, 0x6c, 0xd8, 0x88, 0x7d, 0x38, 0xe8, 0xd7, 0x77, 0x65, 0xae, 0xea, 0x0c, 0x9a, 0x7e, 0xfc, }) != 0 { t.FailNow() } - s(&blk) + s(blk[:]) if bytes.Compare(blk[:], []byte{ 0x55, 0x9d, 0x8d, 0xd7, 0xbd, 0x06, 0xcb, 0xfe, 0x7e, 0x7b, 0x26, 0x25, 0x23, 0x28, 0x0d, 0x39, }) != 0 { t.FailNow() } - s(&blk) + s(blk[:]) if bytes.Compare(blk[:], []byte{ 0x0c, 0x33, 0x22, 0xfe, 0xd5, 0x31, 0xe4, 0x63, 0x0d, 0x80, 0xef, 0x5c, 0x5a, 0x81, 0xc5, 0x0b, }) != 0 { t.FailNow() } - s(&blk) + s(blk[:]) if bytes.Compare(blk[:], []byte{ 0x23, 0xae, 0x65, 0x63, 0x3f, 0x84, 0x2d, 0x29, 0xc5, 0xdf, 0x52, 0x9c, 0x13, 0xf5, 0xac, 0xda, @@ -116,8 +116,13 @@ func TestS(t *testing.T) { } } -func R(blk *[BlockSize]byte) { - l(blk, 1) +func R(blk []byte) { + t := blk[15] + for i := 0; i < 15; i++ { + t ^= gfCache[blk[i]][lc[i]] + } + copy(blk[1:], blk) + blk[0] = t } func TestR(t *testing.T) { @@ -125,28 +130,28 @@ func TestR(t *testing.T) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, } - R(&blk) + R(blk[:]) if bytes.Compare(blk[:], []byte{ 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, }) != 0 { t.FailNow() } - R(&blk) + R(blk[:]) if bytes.Compare(blk[:], []byte{ 0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }) != 0 { t.FailNow() } - R(&blk) + R(blk[:]) if bytes.Compare(blk[:], []byte{ 0x64, 0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }) != 0 { t.FailNow() } - R(&blk) + R(blk[:]) if bytes.Compare(blk[:], []byte{ 0x0d, 0x64, 0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -160,28 +165,28 @@ func TestL(t *testing.T) { 0x64, 0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, } - l(&blk, 16) + l(blk[:]) if bytes.Compare(blk[:], []byte{ 0xd4, 0x56, 0x58, 0x4d, 0xd0, 0xe3, 0xe8, 0x4c, 0xc3, 0x16, 0x6e, 0x4b, 0x7f, 0xa2, 0x89, 0x0d, }) != 0 { t.FailNow() } - l(&blk, 16) + l(blk[:]) if bytes.Compare(blk[:], []byte{ 0x79, 0xd2, 0x62, 0x21, 0xb8, 0x7b, 0x58, 0x4c, 0xd4, 0x2f, 0xbc, 0x4f, 0xfe, 0xa5, 0xde, 0x9a, }) != 0 { t.FailNow() } - l(&blk, 16) + l(blk[:]) if bytes.Compare(blk[:], []byte{ 0x0e, 0x93, 0x69, 0x1a, 0x0c, 0xfc, 0x60, 0x40, 0x8b, 0x7b, 0x68, 0xf6, 0x6b, 0x51, 0x3c, 0x13, }) != 0 { t.FailNow() } - l(&blk, 16) + l(blk[:]) if bytes.Compare(blk[:], []byte{ 0xe6, 0xa8, 0x09, 0x4f, 0xee, 0x0a, 0xa2, 0x04, 0xfd, 0x97, 0xbc, 0xb0, 0xb4, 0x4b, 0x85, 0x80, diff --git a/news.texi b/news.texi index 50b3e3a..bcfd5fe 100644 --- a/news.texi +++ b/news.texi @@ -3,6 +3,10 @@ @table @strong +@anchor{Release 5.3.0} +@item 5.3.0 + ~16x speedup of Streebog, ~15x speedup of Kuznechik. + @anchor{Release 5.2.0} @item 5.2.0 MGM does not panic when short (tagless) message is verified. -- 2.44.0