X-Git-Url: http://www.git.cypherpunks.ru/?a=blobdiff_plain;f=gost3410%2Fprivate.go;h=be10c1f394905cc4858c25fd2f08015e5e4de756;hb=b7f69d1826caacffd042ca8660aba41d0945de0f;hp=231f45e552934c7bcee1f44a31a929d2a72ca336;hpb=0da4d634ac5368d024489baf4bdd5d422b84dd84;p=gogost.git diff --git a/gost3410/private.go b/gost3410/private.go index 231f45e..be10c1f 100644 --- a/gost3410/private.go +++ b/gost3410/private.go @@ -1,5 +1,5 @@ // GoGOST -- Pure Go GOST cryptographic functions library -// Copyright (C) 2015-2019 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 @@ -24,16 +24,17 @@ 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) +// Unmarshal little-endian private key. "raw" must be c.PointSize() length. +func NewPrivateKeyLE(c *Curve, raw []byte) (*PrivateKey, error) { + pointSize := c.PointSize() + if len(raw) != pointSize { + return nil, fmt.Errorf("gogost/gost3410: len(key)=%d != %d", len(raw), 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,29 +42,58 @@ 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{c, k.Mod(k, c.Q)}, nil } -func GenPrivateKey(curve *Curve, mode Mode, rand io.Reader) (*PrivateKey, error) { - raw := make([]byte, int(mode)) +// Unmarshal big-endian private key. "raw" must be c.PointSize() length. +func NewPrivateKeyBE(c *Curve, raw []byte) (*PrivateKey, error) { + pointSize := c.PointSize() + if len(raw) != pointSize { + return nil, fmt.Errorf("gogost/gost3410: len(key)=%d != %d", len(raw), pointSize) + } + k := bytes2big(raw) + if k.Cmp(zero) == 0 { + return nil, errors.New("gogost/gost3410: zero private key") + } + return &PrivateKey{c, k.Mod(k, c.Q)}, nil +} + +// This is an alias for NewPrivateKeyLE(). +func NewPrivateKey(c *Curve, raw []byte) (*PrivateKey, error) { + return NewPrivateKeyLE(c, raw) +} + +func GenPrivateKey(c *Curve, rand io.Reader) (*PrivateKey, error) { + raw := make([]byte, c.PointSize()) if _, err := io.ReadFull(rand, raw); err != nil { - return nil, err + return nil, fmt.Errorf("gogost/gost3410.GenPrivateKey: %w", err) } - return NewPrivateKey(curve, mode, raw) + return NewPrivateKey(c, raw) } -func (prv *PrivateKey) Raw() []byte { - raw := pad(prv.Key.Bytes(), int(prv.Mode)) +// Marshal little-endian private key. raw will be prv.C.PointSize() length. +func (prv *PrivateKey) RawLE() (raw []byte) { + raw = pad(prv.Key.Bytes(), prv.C.PointSize()) reverse(raw) return raw } +// Marshal big-endian private key. raw will be prv.C.PointSize() length. +func (prv *PrivateKey) RawBE() (raw []byte) { + return pad(prv.Key.Bytes(), prv.C.PointSize()) +} + +// This is an alias for RawLE(). +func (prv *PrivateKey) Raw() []byte { + return prv.RawLE() +} + func (prv *PrivateKey) PublicKey() (*PublicKey, error) { x, y, err := prv.C.Exp(prv.Key, prv.C.X, prv.C.Y) if err != nil { - return nil, err + return nil, fmt.Errorf("gogost/gost3410.PrivateKey.PublicKey: %w", 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 +102,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 @@ -80,7 +110,7 @@ func (prv *PrivateKey) SignDigest(digest []byte, rand io.Reader) ([]byte, error) s := big.NewInt(0) Retry: if _, err = io.ReadFull(rand, kRaw); err != nil { - return nil, err + return nil, fmt.Errorf("gogost/gost3410.PrivateKey.SignDigest: %w", err) } k = bytes2big(kRaw) k.Mod(k, prv.C.Q) @@ -89,7 +119,7 @@ Retry: } r, _, err = prv.C.Exp(k, prv.C.X, prv.C.Y) if err != nil { - return nil, err + return nil, fmt.Errorf("gogost/gost3410.PrivateKey.SignDigest: %w", err) } r.Mod(r, prv.C.Q) if r.Cmp(zero) == 0 { @@ -102,13 +132,18 @@ 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 } -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) } @@ -119,3 +154,44 @@ func (prv *PrivateKey) Public() crypto.PublicKey { } return pub } + +type PrivateKeyReverseDigest struct { + Prv *PrivateKey +} + +func (prv *PrivateKeyReverseDigest) Public() crypto.PublicKey { + return prv.Prv.Public() +} + +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 { + Prv *PrivateKey +} + +func (prv *PrivateKeyReverseDigestAndSignature) Public() crypto.PublicKey { + return prv.Prv.Public() +} + +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 + } + reverse(sign) + return sign, err +}