X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=gost3410%2Fpublic.go;h=a1bf539c2ae52abf5a64de05cf27eb0e7bfa6b79;hb=b7f69d1826caacffd042ca8660aba41d0945de0f;hp=79f00f441261a14bfcda14cc417531e4e86c0daa;hpb=6d9056bfe4a2d69469a1e70f3bf08f89b377b06e;p=gogost.git diff --git a/gost3410/public.go b/gost3410/public.go index 79f00f4..a1bf539 100644 --- a/gost3410/public.go +++ b/gost3410/public.go @@ -1,5 +1,5 @@ // GoGOST -- Pure Go GOST cryptographic functions library -// Copyright (C) 2015-2021 Sergey Matveev +// Copyright (C) 2015-2023 Sergey Matveev // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -16,18 +16,19 @@ package gost3410 import ( + "crypto" "fmt" "math/big" ) type PublicKey struct { - C *Curve - X *big.Int - Y *big.Int + C *Curve + X, Y *big.Int } -func NewPublicKey(curve *Curve, raw []byte) (*PublicKey, error) { - pointSize := curve.PointSize() +// Unmarshal LE(X)||LE(Y) public key. "raw" must be 2*c.PointSize() length. +func NewPublicKeyLE(c *Curve, raw []byte) (*PublicKey, error) { + pointSize := c.PointSize() key := make([]byte, 2*pointSize) if len(raw) != len(key) { return nil, fmt.Errorf("gogost/gost3410: len(key) != %d", len(key)) @@ -36,13 +37,32 @@ func NewPublicKey(curve *Curve, raw []byte) (*PublicKey, error) { key[i] = raw[len(raw)-i-1] } return &PublicKey{ - curve, + c, bytes2big(key[pointSize : 2*pointSize]), bytes2big(key[:pointSize]), }, nil } -func (pub *PublicKey) Raw() []byte { +// Unmarshal BE(X)||BE(Y) public key. "raw" must be 2*c.PointSize() length. +func NewPublicKeyBE(c *Curve, raw []byte) (*PublicKey, error) { + pointSize := c.PointSize() + if len(raw) != 2*pointSize { + return nil, fmt.Errorf("gogost/gost3410: len(key) != %d", 2*pointSize) + } + return &PublicKey{ + c, + bytes2big(raw[:pointSize]), + bytes2big(raw[pointSize:]), + }, nil +} + +// This is an alias for NewPublicKeyLE(). +func NewPublicKey(c *Curve, raw []byte) (*PublicKey, error) { + return NewPublicKeyLE(c, raw) +} + +// Marshal LE(X)||LE(Y) public key. raw will be 2*pub.C.PointSize() length. +func (pub *PublicKey) RawLE() []byte { pointSize := pub.C.PointSize() raw := append( pad(pub.Y.Bytes(), pointSize), @@ -52,10 +72,24 @@ func (pub *PublicKey) Raw() []byte { return raw } +// Marshal BE(X)||BE(Y) public key. raw will be 2*pub.C.PointSize() length. +func (pub *PublicKey) RawBE() []byte { + pointSize := pub.C.PointSize() + return append( + pad(pub.X.Bytes(), pointSize), + pad(pub.Y.Bytes(), pointSize)..., + ) +} + +// This is an alias for RawLE(). +func (pub *PublicKey) Raw() []byte { + return pub.RawLE() +} + func (pub *PublicKey) VerifyDigest(digest, signature []byte) (bool, error) { pointSize := pub.C.PointSize() if len(signature) != 2*pointSize { - return false, fmt.Errorf("gogost/gost3410: len(signature) != %d", 2*pointSize) + return false, fmt.Errorf("gogost/gost3410: len(signature)=%d != %d", len(signature), 2*pointSize) } s := bytes2big(signature[:pointSize]) r := bytes2big(signature[pointSize:]) @@ -107,3 +141,51 @@ func (pub *PublicKey) VerifyDigest(digest, signature []byte) (bool, error) { lm.Mod(lm, pub.C.Q) return lm.Cmp(r) == 0, nil } + +func (our *PublicKey) Equal(theirKey crypto.PublicKey) bool { + their, ok := theirKey.(*PublicKey) + if !ok { + return false + } + 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) +}