diff --git a/README b/README.md similarity index 51% rename from README rename to README.md index 592eb55..ad5846e 100644 --- a/README +++ b/README.md @@ -1,6 +1,7 @@ -Pure Go GOST cryptographic functions library. +##Pure Go GOST cryptographic functions library. -GOST is GOvernment STandard of Russian Federation (and Soviet Union). +###Fork of original gogost project https://git.cypherpunks.ru/cgit.cgi/gogost.git +####GOST is GOvernment STandard of Russian Federation (and Soviet Union). * GOST 28147-89 (RFC 5830) block cipher with ECB, CNT (CTR), CFB, MAC CBC (RFC 4357) modes of operation @@ -18,28 +19,53 @@ GOST is GOvernment STandard of Russian Federation (and Soviet Union). * GOST R 34.12-2015 128-bit block cipher Кузнечик (Kuznechik) (RFC 7801) * GOST R 34.12-2015 64-bit block cipher Магма (Magma) * GOST R 34.13-2015 padding methods -* MGM AEAD mode for 64 and 128 bit ciphers +* MGM AEAD mode for 64 and 128 bit ciphers (Р 1323565.1.026–2019) * TLSTREE keyscheduling function * ESPTREE/IKETREE (IKE* is the same as ESP*) keyscheduling function * PRF_IPSEC_PRFPLUS_GOSTR3411_2012_{256,512} and generic prf+ functions (Р 50.1.111-2016 with IKEv2 RFC 7296) Probably you could be interested in -Go's support of GOST TLS 1.3 (http://gostls13.cypherpunks.ru/). +Go's support of GOST TLS 1.3 (http://www.gostls13.cypherpunks.ru/). -Known problems: +####Known problems: * intermediate calculation values are not zeroed * 34.10 is not time constant and slow +#####Example 34.10-2012-256 keypair generation, signing and verifying: + + import ( + "crypto/rand" + "io" + "github.com/ftomza/gogost/gost3410" + "github.com/ftomza/gogost/gost34112012256" + ) + func main() { + data := []byte("data to be signed") + hasher := gost34112012256.New() + _, err := hasher.Write(data) + dgst := hasher.Sum(nil) + curve := gost3410.CurveIdtc26gost34102012256paramSetB() + prvRaw := make([]byte, int(32)) + _, err = io.ReadFull(rand.Reader, prvRaw) + prv, err := gost3410.NewPrivateKey(curve, prvRaw) + pub, err := prv.PublicKey() + pubRaw := pub.Raw() + sign, err := prv.Sign(rand.Reader, dgst, nil) + pub, err = gost3410.NewPublicKey(curve, pubRaw) + isValid, err := pub.VerifyDigest(dgst, sign) + if !isValid { panic("signature is invalid") } + } + GoGOST is free software: see the file COPYING for copying conditions. -GoGOST'es home page is: http://gogost.cypherpunks.ru/ -You can read about GOST algorithms more: http://gost.cypherpunks.ru/ +GoGOST'es home page is: http://www.gogost.cypherpunks.ru/ +You can read about GOST algorithms more: http://www.gost.cypherpunks.ru/ Please send questions, bug reports and patches to https://lists.cypherpunks.ru/mailman/listinfo/gost mailing list. Announcements also go to this mailing list. Development Git source code repository currently is located here: -https://git.cypherpunks.ru/cgit.cgi/gogost.git/ +http://git.cypherpunks.ru/cgit.cgi/gogost.git/ diff --git a/clean.do b/clean.do index 615710c..8cd8ae5 100644 --- a/clean.do +++ b/clean.do @@ -1 +1 @@ -rm -f module-name streebog256 streebog512 +rm -f module-name streebog256 streebog512 VERSION diff --git a/default.do b/default.do index 85bd5f1..db7986d 100644 --- a/default.do +++ b/default.do @@ -1,3 +1,2 @@ redo-ifchange module-name -MOD=`cat module-name` -go build -o $3 -ldflags "-X ${MOD}.Version=`cat VERSION`" ${MOD}/cmd/$1 +go build -o $3 `cat module-name`/cmd/$1 diff --git a/download.texi b/download.texi index c05711c..d79e017 100644 --- a/download.texi +++ b/download.texi @@ -1,6 +1,31 @@ @multitable {XXXXX} {XXXX-XX-XX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @headitem Version @tab Date @tab Size @tab Tarball @tab SHA256 checksum @tab Streebog-256 checksum +@item 5.0.2 @tab 2020-09-05 @tab 62 KiB +@tab @url{gogost-5.0.2.tar.xz, link} @url{gogost-5.0.2.tar.xz.sig, sign} +@tab @code{2A62D4B8 B45CBD6D EFF8DD2A 973F16B3 463F8365 467408A0 2DD538F9 0EFD0B69} +@tab @code{0dd8ed5b0cfae0b8ad30658dab3e12188c005a590db0a698731fb85dcec679c4} + +@item 5.0.1 @tab 2020-09-05 @tab 62 KiB +@tab @url{gogost-5.0.1.tar.xz, link} @url{gogost-5.0.1.tar.xz.sig, sign} +@tab @code{4DAEA73C 44527737 054C659A 9B619A21 643EA3AA 66F6E092 4AC8777A 5D897C6A} +@tab @code{0bde87f569e0dbad29856610dcbd2ffbcaca4f4899046cb138d92b059856b4b2} + +@item @ref{Release 5.0.0, 5.0.0} @tab 2020-09-04 @tab 62 KiB +@tab @url{gogost-5.0.0.tar.xz, link} @url{gogost-5.0.0.tar.xz.sig, sign} +@tab @code{222CB86E 559E9CCF E80FFFB1 B3A7908B A978FE84 9E12B7F9 DA571512 6A24BCA7} +@tab @code{2a0fc616372fe905e8677e1e82d8bd82f852e6393c03cbfb34f69f855bcbfc85} + +@item 4.3.1 @tab 2020-09-01 @tab 63 KiB +@tab @url{gogost-4.3.1.tar.xz, link} @url{gogost-4.3.1.tar.xz.sig, sign} +@tab @code{FEB48FAA 49F43FB4 6FF4812C ECB9BD8B 077EA3A1 693088CA 1C2F29E8 F2AFE500} +@tab @code{785b17e7f84f3b472d5bdcb710e124908da656bdec2df7f6bcf0a1b4042403ce} + +@item @ref{Release 4.3.0, 4.3.0} @tab 2020-08-02 @tab 58 KiB +@tab @url{gogost-4.3.0.tar.xz, link} @url{gogost-4.3.0.tar.xz.sig, sign} +@tab @code{B5550996 57149869 46F01316 937CA4E2 C0786F90 F0281E59 FD3E4D0B 633785EC} +@tab @code{e5a187c1e9753b747918a13008f128efa0b9fbc8f2b26ef8af1315a53ac8b8ba} + @item @ref{Release 4.2.4, 4.2.4} @tab 2020-06-24 @tab 58 KiB @tab @url{gogost-4.2.4.tar.xz, link} @url{gogost-4.2.4.tar.xz.sig, sign} @tab @code{AB7716CB B1E67C5F 5F38B4F9 EEE2733E 931A0498 084AF7BC E816F961 16EB26AE} diff --git a/go.mod b/go.mod index 1b095df..fbddef6 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/ftomza/gogost go 1.12 -require golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 +require golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a diff --git a/gogost.go b/gogost.go index de5246b..90c3bb7 100644 --- a/gogost.go +++ b/gogost.go @@ -1,6 +1,4 @@ // Pure Go GOST cryptographic functions library. package gogost -var ( - Version string = "UNKNOWN" -) +const Version = "5.0.2" diff --git a/gost3410/2001_test.go b/gost3410/2001_test.go index e330d4e..c5d8271 100644 --- a/gost3410/2001_test.go +++ b/gost3410/2001_test.go @@ -59,7 +59,7 @@ func TestRFCVectors(t *testing.T) { } c := CurveIdGostR34102001TestParamSet() - prv, err := NewPrivateKey(c, Mode2001, priv) + prv, err := NewPrivateKey(c, priv) if err != nil { t.FailNow() } @@ -90,11 +90,7 @@ func TestRFCVectors(t *testing.T) { func TestRandom2001(t *testing.T) { c := CurveIdGostR34102001TestParamSet() f := func(data [31]byte, digest [32]byte) bool { - prv, err := NewPrivateKey( - c, - Mode2001, - append([]byte{0xde}, data[:]...), - ) + prv, err := NewPrivateKey(c, append([]byte{0xde}, data[:]...)) if err != nil { return false } @@ -103,7 +99,7 @@ func TestRandom2001(t *testing.T) { return false } pubRaw := pub.Raw() - pub, err = NewPublicKey(c, Mode2001, pubRaw) + pub, err = NewPublicKey(c, pubRaw) if err != nil { return false } @@ -124,7 +120,7 @@ func TestRandom2001(t *testing.T) { func BenchmarkSign2001(b *testing.B) { c := CurveIdGostR34102001TestParamSet() - prv, err := GenPrivateKey(c, Mode2001, rand.Reader) + prv, err := GenPrivateKey(c, rand.Reader) if err != nil { b.FailNow() } @@ -138,7 +134,7 @@ func BenchmarkSign2001(b *testing.B) { func BenchmarkVerify2001(b *testing.B) { c := CurveIdGostR34102001TestParamSet() - prv, err := GenPrivateKey(c, Mode2001, rand.Reader) + prv, err := GenPrivateKey(c, rand.Reader) if err != nil { b.FailNow() } @@ -160,9 +156,9 @@ func BenchmarkVerify2001(b *testing.B) { func TestPrvEqualsTo1(t *testing.T) { c := CurveIdGostR34102001TestParamSet() - prvRaw := make([]byte, int(Mode2001)) + prvRaw := make([]byte, 32) prvRaw[len(prvRaw)-1] = 1 - prv, err := NewPrivateKey(c, Mode2001, prvRaw) + prv, err := NewPrivateKey(c, prvRaw) if err != nil { t.FailNow() } diff --git a/gost3410/2012_test.go b/gost3410/2012_test.go index 422ed7c..fa868f2 100644 --- a/gost3410/2012_test.go +++ b/gost3410/2012_test.go @@ -57,7 +57,7 @@ func TestStdVector1(t *testing.T) { 0x92, 0x80, 0x14, 0xF6, 0xC5, 0xBF, 0x9C, 0x40, } reverse(prvRaw) - prv, err := NewPrivateKey(CurveIdGostR34102001TestParamSet(), Mode2001, prvRaw) + prv, err := NewPrivateKey(CurveIdGostR34102001TestParamSet(), prvRaw) if err != nil { t.FailNow() } @@ -126,6 +126,7 @@ func TestStdVector2(t *testing.T) { }), nil, nil, + nil, ) if err != nil { t.FailNow() @@ -181,7 +182,7 @@ func TestStdVector2(t *testing.T) { 0x2A, 0x98, 0x53, 0xBD, 0xE7, 0x3E, 0x5B, 0x4A, } reverse(prvRaw) - prv, err := NewPrivateKey(c, Mode2012, prvRaw) + prv, err := NewPrivateKey(c, prvRaw) if err != nil { t.FailNow() } @@ -322,11 +323,12 @@ func TestGCL3Vectors(t *testing.T) { bytes2big(y), nil, nil, + nil, ) if err != nil { t.FailNow() } - prv, err := NewPrivateKey(c, Mode2012, priv) + prv, err := NewPrivateKey(c, priv) if err != nil { t.FailNow() } @@ -357,11 +359,7 @@ func TestGCL3Vectors(t *testing.T) { func TestRandom2012(t *testing.T) { c := CurveIdtc26gost341012512paramSetA() f := func(prvRaw [64 - 1]byte, digest [64]byte) bool { - prv, err := NewPrivateKey( - c, - Mode2012, - append([]byte{0xde}, prvRaw[:]...), - ) + prv, err := NewPrivateKey(c, append([]byte{0xde}, prvRaw[:]...)) if err != nil { return false } @@ -370,7 +368,7 @@ func TestRandom2012(t *testing.T) { return false } pubRaw := pub.Raw() - pub, err = NewPublicKey(c, Mode2012, pubRaw) + pub, err = NewPublicKey(c, pubRaw) if err != nil { return false } @@ -580,7 +578,7 @@ func TestUVXYConversion(t *testing.T) { func BenchmarkSign2012(b *testing.B) { c := CurveIdtc26gost341012512paramSetA() - prv, err := GenPrivateKey(c, Mode2012, rand.Reader) + prv, err := GenPrivateKey(c, rand.Reader) if err != nil { b.FailNow() } @@ -594,7 +592,7 @@ func BenchmarkSign2012(b *testing.B) { func BenchmarkVerify2012(b *testing.B) { c := CurveIdtc26gost341012512paramSetA() - prv, err := GenPrivateKey(c, Mode2012, rand.Reader) + prv, err := GenPrivateKey(c, rand.Reader) if err != nil { b.FailNow() } diff --git a/gost3410/curve.go b/gost3410/curve.go index 696beab..e1214d7 100644 --- a/gost3410/curve.go +++ b/gost3410/curve.go @@ -25,6 +25,7 @@ var ( bigInt1 *big.Int = big.NewInt(1) bigInt2 *big.Int = big.NewInt(2) bigInt3 *big.Int = big.NewInt(3) + bigInt4 *big.Int = big.NewInt(4) ) type Curve struct { @@ -33,6 +34,8 @@ type Curve struct { P *big.Int // Characteristic of the underlying prime field Q *big.Int // Elliptic curve subgroup order + Co *big.Int // Cofactor + // Equation coefficients of the elliptic curve in canonical form A *big.Int B *big.Int @@ -55,7 +58,7 @@ type Curve struct { edT *big.Int } -func NewCurve(p, q, a, b, x, y, e, d *big.Int) (*Curve, error) { +func NewCurve(p, q, a, b, x, y, e, d, co *big.Int) (*Curve, error) { c := Curve{ Name: "unknown", P: p, @@ -85,9 +88,18 @@ func NewCurve(p, q, a, b, x, y, e, d *big.Int) (*Curve, error) { c.E = e c.D = d } + if co == nil { + c.Co = bigInt1 + } else { + c.Co = co + } return &c, nil } +func (c *Curve) PointSize() int { + return PointSize(c.P) +} + func (c *Curve) pos(v *big.Int) { if v.Cmp(zero) < 0 { v.Add(v, c.P) diff --git a/gost3410/params.go b/gost3410/params.go index 196ff2f..6e71114 100644 --- a/gost3410/params.go +++ b/gost3410/params.go @@ -15,12 +15,7 @@ package gost3410 -type Mode int - var ( - Mode2001 Mode = Mode(32) - Mode2012 Mode = Mode(64) - CurveGostR34102001ParamSetcc func() *Curve = func() *Curve { curve, err := NewCurve( bytes2big([]byte{ @@ -61,6 +56,7 @@ var ( }), nil, nil, + nil, ) if err != nil { panic(err) @@ -109,6 +105,7 @@ var ( }), nil, nil, + nil, ) if err != nil { panic(err) @@ -157,6 +154,7 @@ var ( }), nil, nil, + nil, ) if err != nil { panic(err) @@ -205,6 +203,7 @@ var ( }), nil, nil, + nil, ) if err != nil { panic(err) @@ -253,6 +252,7 @@ var ( }), nil, nil, + nil, ) if err != nil { panic(err) @@ -318,6 +318,7 @@ var ( 0x2B, 0x9D, 0xF6, 0x28, 0x97, 0x00, 0x9A, 0xF7, 0xE5, 0x22, 0xC3, 0x2D, 0x6D, 0xC7, 0xBF, 0xFB, }), + bigInt4, ) if err != nil { panic(err) @@ -408,6 +409,7 @@ var ( }), nil, nil, + nil, ) if err != nil { panic(err) @@ -480,6 +482,7 @@ var ( }), nil, nil, + nil, ) if err != nil { panic(err) @@ -561,6 +564,7 @@ var ( 0x91, 0xA0, 0xCF, 0xC2, 0xBC, 0x2A, 0x22, 0xB4, 0xCA, 0x30, 0x2D, 0xBB, 0x33, 0xEE, 0x75, 0x50, }), + bigInt4, ) if err != nil { panic(err) diff --git a/gost3410/private.go b/gost3410/private.go index 645881b..689a961 100644 --- a/gost3410/private.go +++ b/gost3410/private.go @@ -24,16 +24,16 @@ import ( ) type PrivateKey struct { - C *Curve - Mode Mode - Key *big.Int + C *Curve + Key *big.Int } -func NewPrivateKey(curve *Curve, mode Mode, raw []byte) (*PrivateKey, error) { - if len(raw) != int(mode) { - return nil, fmt.Errorf("gogost/gost3410: len(key) != %d", mode) +func NewPrivateKey(curve *Curve, raw []byte) (*PrivateKey, error) { + pointSize := curve.PointSize() + if len(raw) != pointSize { + return nil, fmt.Errorf("gogost/gost3410: len(key) != %d", pointSize) } - key := make([]byte, int(mode)) + key := make([]byte, pointSize) for i := 0; i < len(key); i++ { key[i] = raw[len(raw)-i-1] } @@ -41,19 +41,19 @@ func NewPrivateKey(curve *Curve, mode Mode, raw []byte) (*PrivateKey, error) { if k.Cmp(zero) == 0 { return nil, errors.New("gogost/gost3410: zero private key") } - return &PrivateKey{curve, mode, k}, nil + return &PrivateKey{curve, k}, nil } -func GenPrivateKey(curve *Curve, mode Mode, rand io.Reader) (*PrivateKey, error) { - raw := make([]byte, int(mode)) +func GenPrivateKey(curve *Curve, rand io.Reader) (*PrivateKey, error) { + raw := make([]byte, curve.PointSize()) if _, err := io.ReadFull(rand, raw); err != nil { return nil, err } - return NewPrivateKey(curve, mode, raw) + return NewPrivateKey(curve, raw) } func (prv *PrivateKey) Raw() []byte { - raw := pad(prv.Key.Bytes(), int(prv.Mode)) + raw := pad(prv.Key.Bytes(), prv.C.PointSize()) reverse(raw) return raw } @@ -63,7 +63,7 @@ func (prv *PrivateKey) PublicKey() (*PublicKey, error) { if err != nil { return nil, err } - return &PublicKey{prv.C, prv.Mode, x, y}, nil + return &PublicKey{prv.C, x, y}, nil } func (prv *PrivateKey) SignDigest(digest []byte, rand io.Reader) ([]byte, error) { @@ -72,7 +72,7 @@ func (prv *PrivateKey) SignDigest(digest []byte, rand io.Reader) ([]byte, error) if e.Cmp(zero) == 0 { e = big.NewInt(1) } - kRaw := make([]byte, int(prv.Mode)) + kRaw := make([]byte, prv.C.PointSize()) var err error var k *big.Int var r *big.Int @@ -102,9 +102,10 @@ Retry: if s.Cmp(zero) == 0 { goto Retry } + pointSize := prv.C.PointSize() return append( - pad(s.Bytes(), int(prv.Mode)), - pad(r.Bytes(), int(prv.Mode))..., + pad(s.Bytes(), pointSize), + pad(r.Bytes(), pointSize)..., ), nil } diff --git a/gost3410/private_test.go b/gost3410/private_test.go index f20d325..a9b051c 100644 --- a/gost3410/private_test.go +++ b/gost3410/private_test.go @@ -22,9 +22,9 @@ import ( ) func TestSignerInterface(t *testing.T) { - prvRaw := make([]byte, int(Mode2001)) + prvRaw := make([]byte, 32) rand.Read(prvRaw) - prv, err := NewPrivateKey(CurveIdGostR34102001TestParamSet(), Mode2001, prvRaw) + prv, err := NewPrivateKey(CurveIdGostR34102001TestParamSet(), prvRaw) if err != nil { t.FailNow() } diff --git a/gost3410/public.go b/gost3410/public.go index 675431c..e2e3814 100644 --- a/gost3410/public.go +++ b/gost3410/public.go @@ -21,14 +21,14 @@ import ( ) type PublicKey struct { - C *Curve - Mode Mode - X *big.Int - Y *big.Int + C *Curve + X *big.Int + Y *big.Int } -func NewPublicKey(curve *Curve, mode Mode, raw []byte) (*PublicKey, error) { - key := make([]byte, 2*int(mode)) +func NewPublicKey(curve *Curve, raw []byte) (*PublicKey, error) { + pointSize := curve.PointSize() + key := make([]byte, 2*pointSize) if len(raw) != len(key) { return nil, fmt.Errorf("gogost/gost3410: len(key) != %d", len(key)) } @@ -37,27 +37,28 @@ func NewPublicKey(curve *Curve, mode Mode, raw []byte) (*PublicKey, error) { } return &PublicKey{ curve, - mode, - bytes2big(key[int(mode) : 2*int(mode)]), - bytes2big(key[:int(mode)]), + bytes2big(key[pointSize : 2*pointSize]), + bytes2big(key[:pointSize]), }, nil } func (pub *PublicKey) Raw() []byte { + pointSize := pub.C.PointSize() raw := append( - pad(pub.Y.Bytes(), int(pub.Mode)), - pad(pub.X.Bytes(), int(pub.Mode))..., + pad(pub.Y.Bytes(), pointSize), + pad(pub.X.Bytes(), pointSize)..., ) reverse(raw) return raw } func (pub *PublicKey) VerifyDigest(digest, signature []byte) (bool, error) { - if len(signature) != 2*int(pub.Mode) { - return false, fmt.Errorf("gogost/gost3410: len(signature) != %d", 2*int(pub.Mode)) + pointSize := pub.C.PointSize() + if len(signature) != 2*pointSize { + return false, fmt.Errorf("gogost/gost3410: len(signature) != %d", 2*pointSize) } - s := bytes2big(signature[:pub.Mode]) - r := bytes2big(signature[pub.Mode:]) + s := bytes2big(signature[:pointSize]) + r := bytes2big(signature[pointSize:]) if r.Cmp(zero) <= 0 || r.Cmp(pub.C.Q) >= 0 || s.Cmp(zero) <= 0 || diff --git a/gost3410/utils.go b/gost3410/utils.go index 2f22d3b..b903915 100644 --- a/gost3410/utils.go +++ b/gost3410/utils.go @@ -32,3 +32,10 @@ func reverse(d []byte) { func pad(d []byte, size int) []byte { return append(make([]byte, size-len(d)), d...) } + +func PointSize(p *big.Int) int { + if p.BitLen() > 256 { + return 64 + } + return 32 +} diff --git a/gost3410/vko.go b/gost3410/vko.go index 1ac5ea3..fdf3a2f 100644 --- a/gost3410/vko.go +++ b/gost3410/vko.go @@ -24,12 +24,13 @@ func (prv *PrivateKey) KEK(pub *PublicKey, ukm *big.Int) ([]byte, error) { if err != nil { return nil, err } + ukm = ukm.Mul(ukm, prv.C.Co) if ukm.Cmp(bigInt1) != 0 { keyX, keyY, err = prv.C.Exp(ukm, keyX, keyY) if err != nil { return nil, err } } - pk := PublicKey{prv.C, prv.Mode, keyX, keyY} + pk := PublicKey{prv.C, keyX, keyY} return pk.Raw(), nil } diff --git a/gost3410/vko2001.go b/gost3410/vko2001.go index ad61842..13831ce 100644 --- a/gost3410/vko2001.go +++ b/gost3410/vko2001.go @@ -26,8 +26,8 @@ import ( // RFC 4357 VKO GOST R 34.10-2001 key agreement function. // UKM is user keying material, also called VKO-factor. func (prv *PrivateKey) KEK2001(pub *PublicKey, ukm *big.Int) ([]byte, error) { - if prv.Mode != Mode2001 { - return nil, errors.New("gogost/gost3410: KEK2001 can not be used in Mode2012") + if prv.C.PointSize() != 32 { + return nil, errors.New("gogost/gost3410: KEK2001 is only for 256-bit curves") } key, err := prv.KEK(pub, ukm) if err != nil { diff --git a/gost3410/vko2001_test.go b/gost3410/vko2001_test.go index 41fa4a4..3f80733 100644 --- a/gost3410/vko2001_test.go +++ b/gost3410/vko2001_test.go @@ -29,8 +29,8 @@ func TestVKO2001(t *testing.T) { prvRaw1, _ := hex.DecodeString("1df129e43dab345b68f6a852f4162dc69f36b2f84717d08755cc5c44150bf928") prvRaw2, _ := hex.DecodeString("5b9356c6474f913f1e83885ea0edd5df1a43fd9d799d219093241157ac9ed473") kek, _ := hex.DecodeString("ee4618a0dbb10cb31777b4b86a53d9e7ef6cb3e400101410f0c0f2af46c494a6") - prv1, _ := NewPrivateKey(c, Mode2001, prvRaw1) - prv2, _ := NewPrivateKey(c, Mode2001, prvRaw2) + prv1, _ := NewPrivateKey(c, prvRaw1) + prv2, _ := NewPrivateKey(c, prvRaw2) pub1, _ := prv1.PublicKey() pub2, _ := prv2.PublicKey() kek1, _ := prv1.KEK2001(pub2, ukm) @@ -46,11 +46,11 @@ func TestVKO2001(t *testing.T) { func TestRandomVKO2001(t *testing.T) { c := CurveIdGostR34102001TestParamSet() f := func(prvRaw1 [32]byte, prvRaw2 [32]byte, ukmRaw [8]byte) bool { - prv1, err := NewPrivateKey(c, Mode2001, prvRaw1[:]) + prv1, err := NewPrivateKey(c, prvRaw1[:]) if err != nil { return false } - prv2, err := NewPrivateKey(c, Mode2001, prvRaw2[:]) + prv2, err := NewPrivateKey(c, prvRaw2[:]) if err != nil { return false } diff --git a/gost3410/vko2012_test.go b/gost3410/vko2012_test.go index 3d23b95..33aabd9 100644 --- a/gost3410/vko2012_test.go +++ b/gost3410/vko2012_test.go @@ -30,11 +30,11 @@ func TestVKO2012256(t *testing.T) { pubRawA, _ := hex.DecodeString("aab0eda4abff21208d18799fb9a8556654ba783070eba10cb9abb253ec56dcf5d3ccba6192e464e6e5bcb6dea137792f2431f6c897eb1b3c0cc14327b1adc0a7914613a3074e363aedb204d38d3563971bd8758e878c9db11403721b48002d38461f92472d40ea92f9958c0ffa4c93756401b97f89fdbe0b5e46e4a4631cdb5a") prvRawB, _ := hex.DecodeString("48c859f7b6f11585887cc05ec6ef1390cfea739b1a18c0d4662293ef63b79e3b8014070b44918590b4b996acfea4edfbbbcccc8c06edd8bf5bda92a51392d0db") pubRawB, _ := hex.DecodeString("192fe183b9713a077253c72c8735de2ea42a3dbc66ea317838b65fa32523cd5efca974eda7c863f4954d1147f1f2b25c395fce1c129175e876d132e94ed5a65104883b414c9b592ec4dc84826f07d0b6d9006dda176ce48c391e3f97d102e03bb598bf132a228a45f7201aba08fc524a2d77e43a362ab022ad4028f75bde3b79") - pubA, _ := NewPublicKey(c, Mode2012, pubRawA) - pubB, _ := NewPublicKey(c, Mode2012, pubRawB) + pubA, _ := NewPublicKey(c, pubRawA) + pubB, _ := NewPublicKey(c, pubRawB) kek, _ := hex.DecodeString("c9a9a77320e2cc559ed72dce6f47e2192ccea95fa648670582c054c0ef36c221") - prvA, _ := NewPrivateKey(c, Mode2012, prvRawA) - prvB, _ := NewPrivateKey(c, Mode2012, prvRawB) + prvA, _ := NewPrivateKey(c, prvRawA) + prvB, _ := NewPrivateKey(c, prvRawB) kekA, _ := prvA.KEK2012256(pubB, ukm) kekB, _ := prvB.KEK2012256(pubA, ukm) if bytes.Compare(kekA, kekB) != 0 { @@ -48,11 +48,11 @@ func TestVKO2012256(t *testing.T) { func TestRandomVKO2012256(t *testing.T) { c := CurveIdtc26gost341012512paramSetA() f := func(prvRaw1 [64]byte, prvRaw2 [64]byte, ukmRaw [8]byte) bool { - prv1, err := NewPrivateKey(c, Mode2012, prvRaw1[:]) + prv1, err := NewPrivateKey(c, prvRaw1[:]) if err != nil { return false } - prv2, err := NewPrivateKey(c, Mode2012, prvRaw2[:]) + prv2, err := NewPrivateKey(c, prvRaw2[:]) if err != nil { return false } @@ -76,11 +76,11 @@ func TestVKO2012512(t *testing.T) { pubRawA, _ := hex.DecodeString("aab0eda4abff21208d18799fb9a8556654ba783070eba10cb9abb253ec56dcf5d3ccba6192e464e6e5bcb6dea137792f2431f6c897eb1b3c0cc14327b1adc0a7914613a3074e363aedb204d38d3563971bd8758e878c9db11403721b48002d38461f92472d40ea92f9958c0ffa4c93756401b97f89fdbe0b5e46e4a4631cdb5a") prvRawB, _ := hex.DecodeString("48c859f7b6f11585887cc05ec6ef1390cfea739b1a18c0d4662293ef63b79e3b8014070b44918590b4b996acfea4edfbbbcccc8c06edd8bf5bda92a51392d0db") pubRawB, _ := hex.DecodeString("192fe183b9713a077253c72c8735de2ea42a3dbc66ea317838b65fa32523cd5efca974eda7c863f4954d1147f1f2b25c395fce1c129175e876d132e94ed5a65104883b414c9b592ec4dc84826f07d0b6d9006dda176ce48c391e3f97d102e03bb598bf132a228a45f7201aba08fc524a2d77e43a362ab022ad4028f75bde3b79") - pubA, _ := NewPublicKey(c, Mode2012, pubRawA) - pubB, _ := NewPublicKey(c, Mode2012, pubRawB) + pubA, _ := NewPublicKey(c, pubRawA) + pubB, _ := NewPublicKey(c, pubRawB) kek, _ := hex.DecodeString("79f002a96940ce7bde3259a52e015297adaad84597a0d205b50e3e1719f97bfa7ee1d2661fa9979a5aa235b558a7e6d9f88f982dd63fc35a8ec0dd5e242d3bdf") - prvA, _ := NewPrivateKey(c, Mode2012, prvRawA) - prvB, _ := NewPrivateKey(c, Mode2012, prvRawB) + prvA, _ := NewPrivateKey(c, prvRawA) + prvB, _ := NewPrivateKey(c, prvRawB) kekA, _ := prvA.KEK2012512(pubB, ukm) kekB, _ := prvB.KEK2012512(pubA, ukm) if bytes.Compare(kekA, kekB) != 0 { @@ -94,11 +94,11 @@ func TestVKO2012512(t *testing.T) { func TestRandomVKO2012512(t *testing.T) { c := CurveIdtc26gost341012512paramSetA() f := func(prvRaw1 [64]byte, prvRaw2 [64]byte, ukmRaw [8]byte) bool { - prv1, err := NewPrivateKey(c, Mode2012, prvRaw1[:]) + prv1, err := NewPrivateKey(c, prvRaw1[:]) if err != nil { return false } - prv2, err := NewPrivateKey(c, Mode2012, prvRaw2[:]) + prv2, err := NewPrivateKey(c, prvRaw2[:]) if err != nil { return false } diff --git a/install.texi b/install.texi index 9ce6459..dcb8b25 100644 --- a/install.texi +++ b/install.texi @@ -1,31 +1,25 @@ @node Download @unnumbered Download -@set VERSION 4.2.4 - Preferable way is to download tarball with the signature from website and, for example, run tests with benchmarks: @example -$ [fetch|wget] http://gogost.cypherpunks.ru/gogost-@value{VERSION}.tar.xz -$ [fetch|wget] http://gogost.cypherpunks.ru/gogost-@value{VERSION}.tar.xz.sig +$ [fetch|wget] http://www.gogost.cypherpunks.ru/gogost-@value{VERSION}.tar.xz +$ [fetch|wget] http://www.gogost.cypherpunks.ru/gogost-@value{VERSION}.tar.xz.sig $ gpg --verify gogost-@value{VERSION}.tar.xz.sig gogost-@value{VERSION}.tar.xz $ xz --decompress --stdout gogost-@value{VERSION}.tar.xz | tar xf - $ cd gogost-@value{VERSION} -$ redo bench -$ redo all +$ redo bench all $ echo hello world | ./streebog256 f72018189a5cfb803dbe1f2149cf554c40093d8e7f81c21e08ac5bcd09d9934d @end example It uses @url{http://cr.yp.to/redo.html, redo} build system for that examples. You can use either dozen of various implementations, or at -least minimalistic POSIX shell @code{apenwarr/do}: - -@example -$ [fetch|wget] https://github.com/apenwarr/redo/raw/master/minimal/do -$ mv do redo ; chmod +x redo -@end example +least minimalistic POSIX shell @command{contrib/do} (just replace +@command{redo} with @command{contrib/do} in the example above) included +in tarball. @include download.texi @@ -44,7 +38,7 @@ import ( "encoding/hex" "fmt" - "go.cypherpunks.ru/gogost/v4/gost34112012256" + "go.cypherpunks.ru/gogost/v5/gost34112012256" ) func main() @{ @@ -94,7 +88,7 @@ GoGOST is also @command{go get}-able. For example to use $ go get go.cypherpunks.ru/gogost/cmd/streebog256 @end example -@code{go.cypherpunks.ru} uses @url{http://ca.cypherpunks.ru/, ca.cypherpunks.ru} +@code{go.cypherpunks.ru} uses @url{http://www.ca.cypherpunks.ru/, ca.cypherpunks.ru} certificate authority. If you have issues using either @code{sum.golang.org} or @code{proxy.golang.org}, then you can disable their usage with @env{GOPRIVATE=go.cypherpunks.ru/gogost} environment @@ -103,8 +97,8 @@ variable. Also you can use @code{replace} feature inside your @file{go.mod}, like: @example -require go.cypherpunks.ru/gogost/v4 v@value{VERSION} -replace go.cypherpunks.ru/gogost/v4 => /home/stargrave/gogost-@value{VERSION}/src/go.cypherpunks.ru/gogost/v4 +require go.cypherpunks.ru/gogost/v5 v@value{VERSION} +replace go.cypherpunks.ru/gogost/v5 => /home/stargrave/gogost-@value{VERSION}/src/go.cypherpunks.ru/gogost/v5 @end example You can obtain development source code with diff --git a/makedist.sh b/makedist.sh index 5ca9e86..b994ed0 100755 --- a/makedist.sh +++ b/makedist.sh @@ -5,11 +5,12 @@ tmp=$(mktemp -d) release=$1 [ -n "$release" ] -redo-ifchange module-name streebog256 -mod_name=`cat module-name` +redo-ifchange streebog256 git clone . $tmp/gogost-$release cd $tmp/gogost-$release git checkout v$release +redo module-name VERSION +mod_name=`cat module-name` crypto_mod_path=$(sed -n 's#^require \(golang.org/x/crypto\) \(.*\)$#\1@\2#p' go.mod) mkdir -p src/$mod_name @@ -26,9 +27,10 @@ mv \ prfplus \ cmd internal gogost.go go.mod go.sum src/$mod_name -rm module-name.do clean.do echo $mod_name > module-name find . -name "*.do" -exec perl -i -npe "s/^go/GOPATH=\`pwd\` go/" {} \; +mkdir contrib +cp ~/work/redo/minimal/do contrib/do mkdir -p src/golang.org/x/crypto ( cd $GOPATH/pkg/mod/$crypto_mod_path ; \ @@ -37,7 +39,7 @@ mkdir -p src/golang.org/x/crypto cat > download.texi < $texi < $texi < $texi < $texi < $texi <8 ------------------------ -GoGOST'es home page is: http://gogost.cypherpunks.ru/ +GoGOST'es home page is: http://www.gogost.cypherpunks.ru/ Source code and its signature for that version can be found here: - http://gogost.cypherpunks.ru/gogost-${release}.tar.xz ($size KiB) - http://gogost.cypherpunks.ru/gogost-${release}.tar.xz.sig + http://www.gogost.cypherpunks.ru/gogost-${release}.tar.xz ($size KiB) + http://www.gogost.cypherpunks.ru/gogost-${release}.tar.xz.sig Streebog-256 hash: $hashsb SHA256 hash: $hash @@ -141,12 +153,12 @@ GoGOST это свободное программное обеспечение ------------------------ >8 ------------------------ -Домашняя страница GoGOST: http://gogost.cypherpunks.ru/ +Домашняя страница GoGOST: http://www.gogost.cypherpunks.ru/ Исходный код и его подпись для этой версии могут быть найдены здесь: - http://gogost.cypherpunks.ru/gogost-${release}.tar.xz ($size KiB) - http://gogost.cypherpunks.ru/gogost-${release}.tar.xz.sig + http://www.gogost.cypherpunks.ru/gogost-${release}.tar.xz ($size KiB) + http://www.gogost.cypherpunks.ru/gogost-${release}.tar.xz.sig Streebog-256 хэш: $hashsb SHA256 хэш: $hash diff --git a/mgm/mul.go b/mgm/mul.go index ab1948b..a3168c7 100644 --- a/mgm/mul.go +++ b/mgm/mul.go @@ -19,7 +19,6 @@ func (mgm *MGM) mul(xBuf, yBuf []byte) []byte { mgm.x.SetBytes(xBuf) mgm.y.SetBytes(yBuf) mgm.z.SetInt64(0) - var i int for mgm.y.BitLen() != 0 { if mgm.y.Bit(0) == 1 { mgm.z.Xor(mgm.z, mgm.x) @@ -35,7 +34,7 @@ func (mgm *MGM) mul(xBuf, yBuf []byte) []byte { } zBytes := mgm.z.Bytes() rem := len(xBuf) - len(zBytes) - for i = 0; i < rem; i++ { + for i := 0; i < rem; i++ { mgm.mulBuf[i] = 0 } copy(mgm.mulBuf[rem:], zBytes) diff --git a/news.texi b/news.texi index 7d139e1..350ac07 100644 --- a/news.texi +++ b/news.texi @@ -3,6 +3,17 @@ @table @strong +@anchor{Release 5.0.0} +@item 5.0.0 + Backward incompatible remove of excess misleading @code{gost3410.Mode} + from all related functions. Point/key sizes are determined by + looking at curve's parameters size. + +@anchor{Release 4.3.0} +@item 4.3.0 + @strong{Fixed} nasty bug with Edwards curves using in 34.10-VKO + functions: curve's cofactor has not been used. + @anchor{Release 4.2.4} @item 4.2.4 @code{gost3410.PrivateKeyReverseDigest} reversed digests and diff --git a/www.do b/www.do index 51b16f0..174c933 100644 --- a/www.do +++ b/www.do @@ -1,11 +1,15 @@ -rm -f gogost.html/*.html +redo-ifchange *.texi VERSION +html=gogost.html +rm -f $html/*.html ${MAKEINFO:-makeinfo} --html \ + -D "VERSION `cat VERSION`" \ --set-customization-variable EXTRA_HEAD='' \ --set-customization-variable CSS_LINES="`cat style.css`" \ --set-customization-variable SHOW_TITLE=0 \ - --set-customization-variable USE_ACCESSKEY=0 \ --set-customization-variable DATE_IN_HEADER=1 \ --set-customization-variable TOP_NODE_UP_URL=index.html \ --set-customization-variable CLOSE_QUOTE_SYMBOL=\" \ --set-customization-variable OPEN_QUOTE_SYMBOL=\" \ - -o gogost.html www.texi + -o $html www.texi +find $html -type d -exec chmod 755 {} \; +find $html -type f -exec chmod 644 {} \; diff --git a/www.texi b/www.texi index 3338522..046d6dc 100644 --- a/www.texi +++ b/www.texi @@ -15,7 +15,7 @@ It is @url{https://www.gnu.org/philosophy/pragmatic.html, copylefted} @url{https://www.gnu.org/philosophy/free-sw.html, free software}: licenced under @url{https://www.gnu.org/licenses/gpl-3.0.html, GPLv3}. -You can read about GOST algorithms @url{http://gost.cypherpunks.ru/, more}. +You can read about GOST algorithms @url{http://www.gost.cypherpunks.ru/, more}. Currently supported algorithms are: @@ -57,7 +57,34 @@ Currently supported algorithms are: @end itemize Probably you could be interested in -@url{//gostls13.cypherpunks.ru/, Go's support of GOST TLS 1.3}. +@url{//www.gostls13.cypherpunks.ru/, Go's support of GOST TLS 1.3}. + +Example 34.10-2012-256 keypair generation, signing and verifying: + +@verbatim +import ( + "crypto/rand" + "io" + "go.cypherpunks.ru/gogost/v5/gost3410" + "go.cypherpunks.ru/gogost/v5/gost34112012256" +) +func main() { + data := []byte("data to be signed") + hasher := gost34112012256.New() + _, err := hasher.Write(data) + dgst := hasher.Sum(nil) + curve := gost3410.CurveIdtc26gost34102012256paramSetB() + prvRaw := make([]byte, 32) + _, err = io.ReadFull(rand.Reader, prvRaw) + prv, err := gost3410.NewPrivateKey(curve, prvRaw) + pub, err := prv.PublicKey() + pubRaw := pub.Raw() + sign, err := prv.Sign(rand.Reader, dgst, nil) + pub, err = gost3410.NewPublicKey(curve, pubRaw) + isValid, err := pub.VerifyDigest(dgst, sign) + if !isValid { panic("signature is invalid") } +} +@end verbatim Please send questions, bug reports and patches to @url{https://lists.cypherpunks.ru/mailman/listinfo/gost, gost}