xref: /aosp_15_r20/external/tink/go/signature/ed25519_signer_key_manager.go (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1// Copyright 2018 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15////////////////////////////////////////////////////////////////////////////////
16
17package signature
18
19import (
20	"crypto/ed25519"
21	"crypto/rand"
22	"errors"
23	"fmt"
24	"io"
25
26	"google.golang.org/protobuf/proto"
27	"github.com/google/tink/go/keyset"
28	"github.com/google/tink/go/signature/subtle"
29	ed25519pb "github.com/google/tink/go/proto/ed25519_go_proto"
30	tinkpb "github.com/google/tink/go/proto/tink_go_proto"
31)
32
33const (
34	ed25519SignerKeyVersion = 0
35	ed25519SignerTypeURL    = "type.googleapis.com/google.crypto.tink.Ed25519PrivateKey"
36)
37
38// common errors
39var errInvalidED25519SignKey = errors.New("ed25519_signer_key_manager: invalid key")
40var errInvalidED25519SignKeyFormat = errors.New("ed25519_signer_key_manager: invalid key format")
41
42// ed25519SignerKeyManager is an implementation of KeyManager interface.
43// It generates new ED25519PrivateKeys and produces new instances of ED25519Sign subtle.
44type ed25519SignerKeyManager struct{}
45
46// Primitive creates an ED25519Sign subtle for the given serialized ED25519PrivateKey proto.
47func (km *ed25519SignerKeyManager) Primitive(serializedKey []byte) (interface{}, error) {
48	if len(serializedKey) == 0 {
49		return nil, errInvalidED25519SignKey
50	}
51	key := new(ed25519pb.Ed25519PrivateKey)
52
53	if err := proto.Unmarshal(serializedKey, key); err != nil {
54		return nil, errInvalidED25519SignKey
55	}
56	if err := km.validateKey(key); err != nil {
57		return nil, err
58	}
59
60	ret, err := subtle.NewED25519Signer(key.KeyValue)
61	if err != nil {
62		return nil, fmt.Errorf("ed25519_signer_key_manager: %s", err)
63	}
64	return ret, nil
65}
66
67// NewKey creates a new ED25519PrivateKey according to specification the given serialized ED25519KeyFormat.
68func (km *ed25519SignerKeyManager) NewKey(serializedKeyFormat []byte) (proto.Message, error) {
69	pub, priv, err := ed25519.GenerateKey(rand.Reader)
70	if err != nil {
71		return nil, fmt.Errorf("ed25519_signer_key_manager: cannot generate ED25519 key: %s", err)
72	}
73	return &ed25519pb.Ed25519PrivateKey{
74		Version:  ed25519SignerKeyVersion,
75		KeyValue: priv.Seed(),
76		PublicKey: &ed25519pb.Ed25519PublicKey{
77			Version:  ed25519SignerKeyVersion,
78			KeyValue: pub,
79		},
80	}, nil
81}
82
83// NewKeyData creates a new KeyData according to specification in  the given
84// serialized ED25519KeyFormat. It should be used solely by the key management API.
85func (km *ed25519SignerKeyManager) NewKeyData(serializedKeyFormat []byte) (*tinkpb.KeyData, error) {
86	key, err := km.NewKey(serializedKeyFormat)
87	if err != nil {
88		return nil, err
89	}
90	serializedKey, err := proto.Marshal(key)
91	if err != nil {
92		return nil, errInvalidED25519SignKeyFormat
93	}
94	return &tinkpb.KeyData{
95		TypeUrl:         ed25519SignerTypeURL,
96		Value:           serializedKey,
97		KeyMaterialType: km.KeyMaterialType(),
98	}, nil
99}
100
101// PublicKeyData extracts the public key data from the private key.
102func (km *ed25519SignerKeyManager) PublicKeyData(serializedPrivKey []byte) (*tinkpb.KeyData, error) {
103	privKey := new(ed25519pb.Ed25519PrivateKey)
104	if err := proto.Unmarshal(serializedPrivKey, privKey); err != nil {
105		return nil, errInvalidED25519SignKey
106	}
107	serializedPubKey, err := proto.Marshal(privKey.PublicKey)
108	if err != nil {
109		return nil, errInvalidED25519SignKey
110	}
111	return &tinkpb.KeyData{
112		TypeUrl:         ed25519VerifierTypeURL,
113		Value:           serializedPubKey,
114		KeyMaterialType: tinkpb.KeyData_ASYMMETRIC_PUBLIC,
115	}, nil
116}
117
118// DoesSupport indicates if this key manager supports the given key type.
119func (km *ed25519SignerKeyManager) DoesSupport(typeURL string) bool {
120	return typeURL == ed25519SignerTypeURL
121}
122
123// TypeURL returns the key type of keys managed by this key manager.
124func (km *ed25519SignerKeyManager) TypeURL() string {
125	return ed25519SignerTypeURL
126}
127
128// KeyMaterialType returns the key material type of this key manager.
129func (km *ed25519SignerKeyManager) KeyMaterialType() tinkpb.KeyData_KeyMaterialType {
130	return tinkpb.KeyData_ASYMMETRIC_PRIVATE
131}
132
133// DeriveKey derives a new key from serializedKeyFormat and pseudorandomness.
134// Unlike NewKey, DeriveKey validates serializedKeyFormat's version.
135func (km *ed25519SignerKeyManager) DeriveKey(serializedKeyFormat []byte, pseudorandomness io.Reader) (proto.Message, error) {
136	keyFormat := new(ed25519pb.Ed25519KeyFormat)
137	if err := proto.Unmarshal(serializedKeyFormat, keyFormat); err != nil {
138		return nil, fmt.Errorf("ed25519_signer_key_manager: %v", err)
139	}
140	err := keyset.ValidateKeyVersion(keyFormat.Version, ed25519SignerKeyVersion)
141	if err != nil {
142		return nil, fmt.Errorf("ed25519_signer_key_manager: %v", err)
143	}
144
145	pub, priv, err := ed25519.GenerateKey(pseudorandomness)
146	if err != nil {
147		return nil, fmt.Errorf("ed25519_signer_key_manager: cannot generate ED25519 key: %s", err)
148	}
149	return &ed25519pb.Ed25519PrivateKey{
150		Version:  ed25519SignerKeyVersion,
151		KeyValue: priv.Seed(),
152		PublicKey: &ed25519pb.Ed25519PublicKey{
153			Version:  ed25519SignerKeyVersion,
154			KeyValue: pub,
155		},
156	}, nil
157}
158
159// validateKey validates the given ED25519PrivateKey.
160func (km *ed25519SignerKeyManager) validateKey(key *ed25519pb.Ed25519PrivateKey) error {
161	if err := keyset.ValidateKeyVersion(key.Version, ed25519SignerKeyVersion); err != nil {
162		return fmt.Errorf("ed25519_signer_key_manager: invalid key: %s", err)
163	}
164	if len(key.KeyValue) != ed25519.SeedSize {
165		return fmt.Errorf("ed2219_signer_key_manager: invalid key length, got %d", len(key.KeyValue))
166	}
167	return nil
168}
169