From: Sergey Matveev Date: Mon, 7 Aug 2023 13:04:43 +0000 (+0300) Subject: PublicKeyReverseDigest, PublicKeyReverseDigestAndSignature X-Git-Tag: v5.13.0^0 X-Git-Url: http://www.git.cypherpunks.ru/?p=gogost.git;a=commitdiff_plain;h=b7f69d1826caacffd042ca8660aba41d0945de0f PublicKeyReverseDigest, PublicKeyReverseDigestAndSignature --- diff --git a/gost3410/private.go b/gost3410/private.go index 18549a2..be10c1f 100644 --- a/gost3410/private.go +++ b/gost3410/private.go @@ -139,8 +139,11 @@ Retry: ), nil } -// Sign the digest. opts argument is unused. -func (prv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { +// Sign the digest. opts argument is unused. That is identical to SignDigest, +// but kept to be friendly to crypto.Signer. +func (prv *PrivateKey) Sign( + rand io.Reader, digest []byte, opts crypto.SignerOpts, +) ([]byte, error) { return prv.SignDigest(digest, rand) } @@ -160,11 +163,14 @@ func (prv *PrivateKeyReverseDigest) Public() crypto.PublicKey { return prv.Prv.Public() } -func (prv *PrivateKeyReverseDigest) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { - d := make([]byte, len(digest)) - copy(d, digest) - reverse(d) - return prv.Prv.Sign(rand, d, opts) +func (prv *PrivateKeyReverseDigest) Sign( + rand io.Reader, digest []byte, opts crypto.SignerOpts, +) ([]byte, error) { + dgst := make([]byte, len(digest)) + for i := 0; i < len(digest); i++ { + dgst[i] = digest[len(digest)-i-1] + } + return prv.Prv.Sign(rand, dgst, opts) } type PrivateKeyReverseDigestAndSignature struct { @@ -175,11 +181,14 @@ func (prv *PrivateKeyReverseDigestAndSignature) Public() crypto.PublicKey { return prv.Prv.Public() } -func (prv *PrivateKeyReverseDigestAndSignature) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { - d := make([]byte, len(digest)) - copy(d, digest) - reverse(d) - sign, err := prv.Prv.Sign(rand, d, opts) +func (prv *PrivateKeyReverseDigestAndSignature) Sign( + rand io.Reader, digest []byte, opts crypto.SignerOpts, +) ([]byte, error) { + dgst := make([]byte, len(digest)) + for i := 0; i < len(digest); i++ { + dgst[i] = digest[len(digest)-i-1] + } + sign, err := prv.Prv.Sign(rand, dgst, opts) if err != nil { return sign, err } diff --git a/gost3410/private_test.go b/gost3410/private_test.go index 924cad8..6045c1e 100644 --- a/gost3410/private_test.go +++ b/gost3410/private_test.go @@ -18,15 +18,75 @@ package gost3410 import ( "crypto" "crypto/rand" + "io" "testing" ) func TestSignerInterface(t *testing.T) { - prvRaw := make([]byte, 32) - rand.Read(prvRaw) - prv, err := NewPrivateKey(CurveIdGostR34102001TestParamSet(), prvRaw) + c := CurveIdGostR34102001TestParamSet() + prvRaw := make([]byte, c.PointSize()) + _, err := io.ReadFull(rand.Reader, prvRaw) + if err != nil { + t.Fatal(err) + } + prv, err := NewPrivateKey(c, prvRaw) if err != nil { t.Fatal(err) } var _ crypto.Signer = prv + var _ crypto.Signer = &PrivateKeyReverseDigest{prv} + var _ crypto.Signer = &PrivateKeyReverseDigestAndSignature{prv} +} + +func TestSignerReverseDigest(t *testing.T) { + dgst := make([]byte, 32) + _, err := io.ReadFull(rand.Reader, dgst) + if err != nil { + t.Fatal(err) + } + prv0, err := GenPrivateKey(CurveIdGostR34102001TestParamSet(), rand.Reader) + if err != nil { + t.Fatal(err) + } + pub0 := prv0.Public().(*PublicKey) + sign, err := prv0.Sign(rand.Reader, dgst, nil) + if err != nil { + t.Fatal(err) + } + valid, err := pub0.VerifyDigest(dgst, sign) + if err != nil { + t.Fatal(err) + } + if !valid { + t.FailNow() + } + var _ crypto.PublicKey = pub0 + + prv1 := PrivateKeyReverseDigest{prv0} + pub1 := PublicKeyReverseDigest{prv1.Public().(*PublicKey)} + sign, err = prv1.Sign(rand.Reader, dgst, nil) + if err != nil { + t.Fatal(err) + } + valid, err = pub1.VerifyDigest(dgst, sign) + if err != nil { + t.Fatal(err) + } + if !valid { + t.FailNow() + } + + prv2 := PrivateKeyReverseDigestAndSignature{prv0} + pub2 := PublicKeyReverseDigestAndSignature{prv2.Public().(*PublicKey)} + sign, err = prv2.Sign(rand.Reader, dgst, nil) + if err != nil { + t.Fatal(err) + } + valid, err = pub2.VerifyDigest(dgst, sign) + if err != nil { + t.Fatal(err) + } + if !valid { + t.FailNow() + } } diff --git a/gost3410/public.go b/gost3410/public.go index ef5926b..a1bf539 100644 --- a/gost3410/public.go +++ b/gost3410/public.go @@ -22,7 +22,7 @@ import ( ) type PublicKey struct { - C *Curve + C *Curve X, Y *big.Int } @@ -149,3 +149,43 @@ func (our *PublicKey) Equal(theirKey crypto.PublicKey) bool { } return our.X.Cmp(their.X) == 0 && our.Y.Cmp(their.Y) == 0 && our.C.Equal(their.C) } + +type PublicKeyReverseDigest struct { + Pub *PublicKey +} + +func (pub PublicKeyReverseDigest) VerifyDigest( + digest, signature []byte, +) (bool, error) { + dgst := make([]byte, len(digest)) + for i := 0; i < len(digest); i++ { + dgst[i] = digest[len(digest)-i-1] + } + return pub.Pub.VerifyDigest(dgst, signature) +} + +func (pub PublicKeyReverseDigest) Equal(theirKey crypto.PublicKey) bool { + return pub.Pub.Equal(theirKey) +} + +type PublicKeyReverseDigestAndSignature struct { + Pub *PublicKey +} + +func (pub PublicKeyReverseDigestAndSignature) VerifyDigest( + digest, signature []byte, +) (bool, error) { + dgst := make([]byte, len(digest)) + for i := 0; i < len(digest); i++ { + dgst[i] = digest[len(digest)-i-1] + } + sign := make([]byte, len(signature)) + for i := 0; i < len(signature); i++ { + sign[i] = signature[len(signature)-i-1] + } + return pub.Pub.VerifyDigest(dgst, sign) +} + +func (pub PublicKeyReverseDigestAndSignature) Equal(theirKey crypto.PublicKey) bool { + return pub.Pub.Equal(theirKey) +} diff --git a/news.texi b/news.texi index 022b9a6..a514e52 100644 --- a/news.texi +++ b/news.texi @@ -13,6 +13,9 @@ @code{gost3410.NewPrivateKeyBE}, @code{gost3410.PrivateKey.RawBE}, functions appeared, to simplify dealing with different endianness keys serialisation + @item + @code{gost3410.PublicKeyReverseDigest} and + @code{gost3410.PublicKeyReverseDigestAndSignature} wrappers appeared @end itemize @anchor{Release 5.12.0}