]> Cypherpunks.ru repositories - gogost.git/commitdiff
VKO 34.10-2001 implementation 1.2
authorSergey Matveev <stargrave@stargrave.org>
Sun, 13 Nov 2016 12:59:04 +0000 (15:59 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 13 Nov 2016 12:59:04 +0000 (15:59 +0300)
README
TODO
src/cypherpunks.ru/gogost/gost3410/2001_test.go
src/cypherpunks.ru/gogost/gost3410/private.go
www.texi

diff --git a/README b/README
index 3cceb56e27648710372523666aa65bdd9e9efeea..d0c17d31af21649d7e2d982ffc07d0ea3b20ab43 100644 (file)
--- a/README
+++ b/README
@@ -10,6 +10,7 @@ GOST is GOvernment STandard of Russian Federation (and Soviet Union).
 * GOST R 34.10-2001 (RFC 5832) public key signature function
 * GOST R 34.10-2012 (RFC 7091) public key signature function
 * various 34.10 curve parameters included
+* VKO 34.10-2001 Diffie-Hellman function (RFC 4357)
 * GOST R 34.12-2015 128-bit block cipher Кузнечик (Kuznechik) (RFC 7801)
 * GOST R 34.13-2015 padding methods
 
diff --git a/TODO b/TODO
index 0e2d7f7fda57eb0d4823a6eb806b43bed790254a..7938d48057713162d45815d1a3546699a1237e36 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,2 @@
-* VKO 34.10-2001 Diffie-Hellman function (RFC 4357)
 * 28147-89 and CryptoPro key wrapping (RFC 4357)
 * 28147-89 CryptoPro key meshing for CFB mode (RFC 4357)
index 0bc14291ce39be4fed1cb8dda18cc5974afd5851..21553b4eca70dff952a065a5e00d042b26f27088 100644 (file)
@@ -19,6 +19,7 @@ package gost3410
 import (
        "bytes"
        "crypto/rand"
+       "encoding/hex"
        "testing"
        "testing/quick"
 )
@@ -161,3 +162,45 @@ func BenchmarkVerify2001(b *testing.B) {
                pub.VerifyDigest(digest, sign)
        }
 }
+
+func TestVKO(t *testing.T) {
+       c, _ := NewCurveFromParams(CurveParamsGostR34102001Test)
+       ukm, _ := hex.DecodeString("33a252f825be7251")
+       prvRaw1, _ := hex.DecodeString("1df129e43dab345b68f6a852f4162dc69f36b2f84717d08755cc5c44150bf928")
+       prvRaw2, _ := hex.DecodeString("5b9356c6474f913f1e83885ea0edd5df1a43fd9d799d219093241157ac9ed473")
+       kek, _ := hex.DecodeString("ee4618a0dbb10cb31777b4b86a53d9e7ef6cb3e400101410f0c0f2af46c494a6")
+       prv1, _ := NewPrivateKey(c, DigestSize2001, prvRaw1)
+       prv2, _ := NewPrivateKey(c, DigestSize2001, prvRaw2)
+       pub1, _ := prv1.PublicKey()
+       pub2, _ := prv2.PublicKey()
+       kek1, _ := prv1.KEK(pub2, ukm)
+       kek2, _ := prv2.KEK(pub1, ukm)
+       if bytes.Compare(kek1, kek2) != 0 {
+               t.FailNow()
+       }
+       if bytes.Compare(kek1, kek) != 0 {
+               t.FailNow()
+       }
+}
+
+func TestRandomVKO(t *testing.T) {
+       c, _ := NewCurveFromParams(CurveParamsGostR34102001Test)
+       f := func(prvRaw1 [32]byte, prvRaw2 [32]byte, ukm [8]byte) bool {
+               prv1, err := NewPrivateKey(c, DigestSize2001, prvRaw1[:])
+               if err != nil {
+                       return false
+               }
+               prv2, err := NewPrivateKey(c, DigestSize2001, prvRaw2[:])
+               if err != nil {
+                       return false
+               }
+               pub1, _ := prv1.PublicKey()
+               pub2, _ := prv2.PublicKey()
+               kek1, _ := prv1.KEK(pub2, ukm[:])
+               kek2, _ := prv2.KEK(pub1, ukm[:])
+               return bytes.Compare(kek1, kek2) == 0
+       }
+       if err := quick.Check(f, nil); err != nil {
+               t.Error(err)
+       }
+}
index 0eec619e05b239c0e5437b493e3d2894144852f8..c145eb9dcd85990076c66a25cf1221b61f9c97d6 100644 (file)
@@ -20,6 +20,9 @@ import (
        "errors"
        "io"
        "math/big"
+
+       "cypherpunks.ru/gogost/gost28147"
+       "cypherpunks.ru/gogost/gost341194"
 )
 
 type PrivateKey struct {
@@ -102,3 +105,33 @@ Retry:
        }
        return append(pad(s.Bytes(), pk.ds), pad(r.Bytes(), pk.ds)...), nil
 }
+
+// Make Diffie-Hellman computation. Key Encryption Key calculation.
+// UKM is user keying material, also called VKO-factor, 8-bytes long.
+// It is based on RFC 4357 VKO GOST 34.10-2001 with little-endian hash
+// output.
+func (pk *PrivateKey) KEK(pub *PublicKey, ukm []byte) ([]byte, error) {
+       if len(ukm) != 8 {
+               return nil, errors.New("UKM must be 8 bytes long")
+       }
+       keyX, keyY, err := pk.c.Exp(pk.key, pub.x, pub.y)
+       if err != nil {
+               return nil, err
+       }
+       t := make([]byte, DigestSize2001)
+       copy(t[int(DigestSize2001)-len(ukm):], ukm)
+       keyX, keyY, err = pk.c.Exp(bytes2big(t), keyX, keyY)
+       if err != nil {
+               return nil, err
+       }
+       h := gost341194.New(&gost28147.GostR3411_94_CryptoProParamSet)
+       copy(t, pad(keyX.Bytes(), int(DigestSize2001)))
+       reverse(t)
+       h.Write(t)
+       copy(t, pad(keyY.Bytes(), int(DigestSize2001)))
+       reverse(t)
+       h.Write(t)
+       t = h.Sum(t[:0])
+       reverse(t)
+       return t, nil
+}
index b15c0112f380d5261ab6aa5d4782427c701823a6..03f0703e8432d804d8361ef6abd94d822b844c47 100644 (file)
--- a/www.texi
+++ b/www.texi
@@ -25,6 +25,8 @@ Currently supported algorithms are:
     CBC (@url{https://tools.ietf.org/html/rfc4357.html, RFC 4357})
     modes of operation
 @item various 28147-89-related S-boxes included
+@item VKO 34.10-2001 Diffie-Hellman function
+    (@url{https://tools.ietf.org/html/rfc4357.html, RFC 4357})
 @item GOST R 34.11-94 hash function
     (@url{https://tools.ietf.org/html/rfc5831.html, RFC 5831})
 @item GOST R 34.11-2012 Стрибог (Streebog) hash function