X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=gost3410%2Fpublic.go;h=a5a4b7059b60d98a68f60ed435f8212bf2443b5c;hb=HEAD;hp=08e1414000bf6e3d42710b5485e002d74b6e46c7;hpb=c07494bbd559b9d00f391e28cfd070e18afe9900;p=gogost.git diff --git a/gost3410/public.go b/gost3410/public.go index 08e1414..a8669cf 100644 --- a/gost3410/public.go +++ b/gost3410/public.go @@ -1,5 +1,5 @@ // GoGOST -- Pure Go GOST cryptographic functions library -// Copyright (C) 2015-2019 Sergey Matveev +// Copyright (C) 2015-2024 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,49 +16,87 @@ package gost3410 import ( - "errors" + "crypto" + "fmt" "math/big" ) type PublicKey struct { C *Curve - Mode Mode - X *big.Int - Y *big.Int + X, Y *big.Int } -func NewPublicKey(curve *Curve, mode Mode, raw []byte) (*PublicKey, error) { - key := make([]byte, 2*int(mode)) +// 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, errors.New("Invalid public key length") + return nil, fmt.Errorf("gogost/gost3410: len(key) != %d", len(key)) } for i := 0; i < len(key); i++ { key[i] = raw[len(raw)-i-1] } return &PublicKey{ - curve, - mode, - bytes2big(key[int(mode) : 2*int(mode)]), - bytes2big(key[:int(mode)]), + 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(), int(pub.Mode)), - pad(pub.X.Bytes(), int(pub.Mode))..., + pad(pub.Y.Bytes(), pointSize), + pad(pub.X.Bytes(), pointSize)..., ) reverse(raw) 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) { - if len(signature) != 2*int(pub.Mode) { - return false, errors.New("Invalid signature length") + pointSize := pub.C.PointSize() + if len(signature) != 2*pointSize { + return false, fmt.Errorf("gogost/gost3410: len(signature)=%d != %d", len(signature), 2*pointSize) } - s := bytes2big(signature[:pub.Mode]) - r := bytes2big(signature[pub.Mode:]) - if r.Cmp(zero) <= 0 || r.Cmp(pub.C.Q) >= 0 || s.Cmp(zero) <= 0 || s.Cmp(pub.C.Q) >= 0 { + s := bytes2big(signature[:pointSize]) + r := bytes2big(signature[pointSize:]) + if r.Cmp(zero) <= 0 || + r.Cmp(pub.C.Q) >= 0 || + s.Cmp(zero) <= 0 || + s.Cmp(pub.C.Q) >= 0 { return false, nil } e := bytes2big(digest) @@ -103,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) +}