1 // GoGOST -- Pure Go GOST cryptographic functions library
2 // Copyright (C) 2015-2016 Sergey Matveev <stargrave@stargrave.org>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 "cypherpunks.ru/gogost/gost28147"
25 "cypherpunks.ru/gogost/gost341194"
28 type PrivateKey struct {
34 func NewPrivateKey(curve *Curve, ds DigestSize, raw []byte) (*PrivateKey, error) {
35 key := make([]byte, len(raw))
40 return nil, errors.New("zero private key")
42 return &PrivateKey{curve, int(ds), k}, nil
45 func GenPrivateKey(curve *Curve, ds DigestSize, rand io.Reader) (*PrivateKey, error) {
46 raw := make([]byte, int(ds))
47 if _, err := io.ReadFull(rand, raw); err != nil {
50 return NewPrivateKey(curve, ds, raw)
53 func (pk *PrivateKey) Raw() []byte {
54 raw := pad(pk.key.Bytes(), pk.ds)
59 func (pk *PrivateKey) PublicKey() (*PublicKey, error) {
60 x, y, err := pk.c.Exp(pk.key, pk.c.Bx, pk.c.By)
64 return &PublicKey{pk.c, pk.ds, x, y}, nil
67 func (pk *PrivateKey) SignDigest(digest []byte, rand io.Reader) ([]byte, error) {
68 if len(digest) != pk.ds {
69 return nil, errors.New("Invalid input digest length")
71 e := bytes2big(digest)
76 kRaw := make([]byte, pk.ds)
83 if _, err = io.ReadFull(rand, kRaw); err != nil {
91 r, _, err = pk.c.Exp(k, pk.c.Bx, pk.c.By)
103 if s.Cmp(zero) == 0 {
106 return append(pad(s.Bytes(), pk.ds), pad(r.Bytes(), pk.ds)...), nil
109 // Make Diffie-Hellman computation. Key Encryption Key calculation.
110 // UKM is user keying material, also called VKO-factor, 8-bytes long.
111 // It is based on RFC 4357 VKO GOST 34.10-2001 with little-endian hash
113 func (pk *PrivateKey) KEK(pub *PublicKey, ukm []byte) ([]byte, error) {
115 return nil, errors.New("UKM must be 8 bytes long")
117 keyX, keyY, err := pk.c.Exp(pk.key, pub.x, pub.y)
121 t := make([]byte, DigestSize2001)
122 copy(t[int(DigestSize2001)-len(ukm):], ukm)
123 keyX, keyY, err = pk.c.Exp(bytes2big(t), keyX, keyY)
127 h := gost341194.New(&gost28147.GostR3411_94_CryptoProParamSet)
128 copy(t, pad(keyX.Bytes(), int(DigestSize2001)))
131 copy(t, pad(keyY.Bytes(), int(DigestSize2001)))