]> Cypherpunks.ru repositories - gogost.git/commitdiff
PublicKeyReverseDigest, PublicKeyReverseDigestAndSignature v5.13.0
authorSergey Matveev <stargrave@stargrave.org>
Mon, 7 Aug 2023 13:04:43 +0000 (16:04 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Mon, 7 Aug 2023 13:19:50 +0000 (16:19 +0300)
gost3410/private.go
gost3410/private_test.go
gost3410/public.go
news.texi

index 18549a29cf1f0f8718af45fef3059ba0183c7977..be10c1f394905cc4858c25fd2f08015e5e4de756 100644 (file)
@@ -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
        }
index 924cad8442183e7378685e14b4da8c87bfb1eae1..6045c1e683c4c7f408ad1b7f78de49117ac1d745 100644 (file)
@@ -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()
+       }
 }
index ef5926bc336a03705ef44eaceb00f4656cc574bb..a1bf539c2ae52abf5a64de05cf27eb0e7bfa6b79 100644 (file)
@@ -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)
+}
index 022b9a60c95fe610aca49f75d931d86b359fab14..a514e528f9faa324b82207ba456e3c0468629635 100644 (file)
--- 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}