main
Raw Download raw file
  1// Copyright 2011 The Go Authors. All rights reserved.
  2// Use of this source code is governed by a BSD-style
  3// license that can be found in the LICENSE file.
  4
  5package openpgp
  6
  7import (
  8	"crypto"
  9	"crypto/rand"
 10	"crypto/rsa"
 11	goerrors "errors"
 12	"io"
 13	"math/big"
 14	"time"
 15
 16	"github.com/ProtonMail/go-crypto/openpgp/ecdh"
 17	"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
 18	"github.com/ProtonMail/go-crypto/openpgp/ed25519"
 19	"github.com/ProtonMail/go-crypto/openpgp/ed448"
 20	"github.com/ProtonMail/go-crypto/openpgp/eddsa"
 21	"github.com/ProtonMail/go-crypto/openpgp/errors"
 22	"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
 23	"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
 24	"github.com/ProtonMail/go-crypto/openpgp/packet"
 25	"github.com/ProtonMail/go-crypto/openpgp/x25519"
 26	"github.com/ProtonMail/go-crypto/openpgp/x448"
 27)
 28
 29// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
 30// single identity composed of the given full name, comment and email, any of
 31// which may be empty but must not contain any of "()<>\x00".
 32// If config is nil, sensible defaults will be used.
 33func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
 34	creationTime := config.Now()
 35	keyLifetimeSecs := config.KeyLifetime()
 36
 37	// Generate a primary signing key
 38	primaryPrivRaw, err := newSigner(config)
 39	if err != nil {
 40		return nil, err
 41	}
 42	primary := packet.NewSignerPrivateKey(creationTime, primaryPrivRaw)
 43	if config.V6() {
 44		if err := primary.UpgradeToV6(); err != nil {
 45			return nil, err
 46		}
 47	}
 48
 49	e := &Entity{
 50		PrimaryKey: &primary.PublicKey,
 51		PrivateKey: primary,
 52		Identities: make(map[string]*Identity),
 53		Subkeys:    []Subkey{},
 54		Signatures: []*packet.Signature{},
 55	}
 56
 57	if config.V6() {
 58		// In v6 keys algorithm preferences should be stored in direct key signatures
 59		selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypeDirectSignature, config)
 60		err = writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config)
 61		if err != nil {
 62			return nil, err
 63		}
 64		err = selfSignature.SignDirectKeyBinding(&primary.PublicKey, primary, config)
 65		if err != nil {
 66			return nil, err
 67		}
 68		e.Signatures = append(e.Signatures, selfSignature)
 69		e.SelfSignature = selfSignature
 70	}
 71
 72	err = e.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
 73	if err != nil {
 74		return nil, err
 75	}
 76
 77	// NOTE: No key expiry here, but we will not return this subkey in EncryptionKey()
 78	// if the primary/master key has expired.
 79	err = e.addEncryptionSubkey(config, creationTime, 0)
 80	if err != nil {
 81		return nil, err
 82	}
 83
 84	return e, nil
 85}
 86
 87func (t *Entity) AddUserId(name, comment, email string, config *packet.Config) error {
 88	creationTime := config.Now()
 89	keyLifetimeSecs := config.KeyLifetime()
 90	return t.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
 91}
 92
 93func writeKeyProperties(selfSignature *packet.Signature, creationTime time.Time, keyLifetimeSecs uint32, config *packet.Config) error {
 94	advertiseAead := config.AEAD() != nil
 95
 96	selfSignature.CreationTime = creationTime
 97	selfSignature.KeyLifetimeSecs = &keyLifetimeSecs
 98	selfSignature.FlagsValid = true
 99	selfSignature.FlagSign = true
100	selfSignature.FlagCertify = true
101	selfSignature.SEIPDv1 = true // true by default, see 5.8 vs. 5.14
102	selfSignature.SEIPDv2 = advertiseAead
103
104	// Set the PreferredHash for the SelfSignature from the packet.Config.
105	// If it is not the must-implement algorithm from rfc4880bis, append that.
106	hash, ok := algorithm.HashToHashId(config.Hash())
107	if !ok {
108		return errors.UnsupportedError("unsupported preferred hash function")
109	}
110
111	selfSignature.PreferredHash = []uint8{hash}
112	if config.Hash() != crypto.SHA256 {
113		selfSignature.PreferredHash = append(selfSignature.PreferredHash, hashToHashId(crypto.SHA256))
114	}
115
116	// Likewise for DefaultCipher.
117	selfSignature.PreferredSymmetric = []uint8{uint8(config.Cipher())}
118	if config.Cipher() != packet.CipherAES128 {
119		selfSignature.PreferredSymmetric = append(selfSignature.PreferredSymmetric, uint8(packet.CipherAES128))
120	}
121
122	// We set CompressionNone as the preferred compression algorithm because
123	// of compression side channel attacks, then append the configured
124	// DefaultCompressionAlgo if any is set (to signal support for cases
125	// where the application knows that using compression is safe).
126	selfSignature.PreferredCompression = []uint8{uint8(packet.CompressionNone)}
127	if config.Compression() != packet.CompressionNone {
128		selfSignature.PreferredCompression = append(selfSignature.PreferredCompression, uint8(config.Compression()))
129	}
130
131	if advertiseAead {
132		// Get the preferred AEAD mode from the packet.Config.
133		// If it is not the must-implement algorithm from rfc9580, append that.
134		modes := []uint8{uint8(config.AEAD().Mode())}
135		if config.AEAD().Mode() != packet.AEADModeOCB {
136			modes = append(modes, uint8(packet.AEADModeOCB))
137		}
138
139		// For preferred (AES256, GCM), we'll generate (AES256, GCM), (AES256, OCB), (AES128, GCM), (AES128, OCB)
140		for _, cipher := range selfSignature.PreferredSymmetric {
141			for _, mode := range modes {
142				selfSignature.PreferredCipherSuites = append(selfSignature.PreferredCipherSuites, [2]uint8{cipher, mode})
143			}
144		}
145	}
146	return nil
147}
148
149func (t *Entity) addUserId(name, comment, email string, config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32, writeProperties bool) error {
150	uid := packet.NewUserId(name, comment, email)
151	if uid == nil {
152		return errors.InvalidArgumentError("user id field contained invalid characters")
153	}
154
155	if _, ok := t.Identities[uid.Id]; ok {
156		return errors.InvalidArgumentError("user id exist")
157	}
158
159	primary := t.PrivateKey
160	isPrimaryId := len(t.Identities) == 0
161	selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypePositiveCert, config)
162	if writeProperties {
163		err := writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config)
164		if err != nil {
165			return err
166		}
167	}
168	selfSignature.IsPrimaryId = &isPrimaryId
169
170	// User ID binding signature
171	err := selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config)
172	if err != nil {
173		return err
174	}
175	t.Identities[uid.Id] = &Identity{
176		Name:          uid.Id,
177		UserId:        uid,
178		SelfSignature: selfSignature,
179		Signatures:    []*packet.Signature{selfSignature},
180	}
181	return nil
182}
183
184// AddSigningSubkey adds a signing keypair as a subkey to the Entity.
185// If config is nil, sensible defaults will be used.
186func (e *Entity) AddSigningSubkey(config *packet.Config) error {
187	creationTime := config.Now()
188	keyLifetimeSecs := config.KeyLifetime()
189
190	subPrivRaw, err := newSigner(config)
191	if err != nil {
192		return err
193	}
194	sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw)
195	sub.IsSubkey = true
196	if config.V6() {
197		if err := sub.UpgradeToV6(); err != nil {
198			return err
199		}
200	}
201
202	subkey := Subkey{
203		PublicKey:  &sub.PublicKey,
204		PrivateKey: sub,
205	}
206	subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config)
207	subkey.Sig.CreationTime = creationTime
208	subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs
209	subkey.Sig.FlagsValid = true
210	subkey.Sig.FlagSign = true
211	subkey.Sig.EmbeddedSignature = createSignaturePacket(subkey.PublicKey, packet.SigTypePrimaryKeyBinding, config)
212	subkey.Sig.EmbeddedSignature.CreationTime = creationTime
213
214	err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, subkey.PrivateKey, config)
215	if err != nil {
216		return err
217	}
218
219	err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
220	if err != nil {
221		return err
222	}
223
224	e.Subkeys = append(e.Subkeys, subkey)
225	return nil
226}
227
228// AddEncryptionSubkey adds an encryption keypair as a subkey to the Entity.
229// If config is nil, sensible defaults will be used.
230func (e *Entity) AddEncryptionSubkey(config *packet.Config) error {
231	creationTime := config.Now()
232	keyLifetimeSecs := config.KeyLifetime()
233	return e.addEncryptionSubkey(config, creationTime, keyLifetimeSecs)
234}
235
236func (e *Entity) addEncryptionSubkey(config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32) error {
237	subPrivRaw, err := newDecrypter(config)
238	if err != nil {
239		return err
240	}
241	sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
242	sub.IsSubkey = true
243	if config.V6() {
244		if err := sub.UpgradeToV6(); err != nil {
245			return err
246		}
247	}
248
249	subkey := Subkey{
250		PublicKey:  &sub.PublicKey,
251		PrivateKey: sub,
252	}
253	subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config)
254	subkey.Sig.CreationTime = creationTime
255	subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs
256	subkey.Sig.FlagsValid = true
257	subkey.Sig.FlagEncryptStorage = true
258	subkey.Sig.FlagEncryptCommunications = true
259
260	err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
261	if err != nil {
262		return err
263	}
264
265	e.Subkeys = append(e.Subkeys, subkey)
266	return nil
267}
268
269// Generates a signing key
270func newSigner(config *packet.Config) (signer interface{}, err error) {
271	switch config.PublicKeyAlgorithm() {
272	case packet.PubKeyAlgoRSA:
273		bits := config.RSAModulusBits()
274		if bits < 1024 {
275			return nil, errors.InvalidArgumentError("bits must be >= 1024")
276		}
277		if config != nil && len(config.RSAPrimes) >= 2 {
278			primes := config.RSAPrimes[0:2]
279			config.RSAPrimes = config.RSAPrimes[2:]
280			return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
281		}
282		return rsa.GenerateKey(config.Random(), bits)
283	case packet.PubKeyAlgoEdDSA:
284		if config.V6() {
285			// Implementations MUST NOT accept or generate v6 key material
286			// using the deprecated OIDs.
287			return nil, errors.InvalidArgumentError("EdDSALegacy cannot be used for v6 keys")
288		}
289		curve := ecc.FindEdDSAByGenName(string(config.CurveName()))
290		if curve == nil {
291			return nil, errors.InvalidArgumentError("unsupported curve")
292		}
293
294		priv, err := eddsa.GenerateKey(config.Random(), curve)
295		if err != nil {
296			return nil, err
297		}
298		return priv, nil
299	case packet.PubKeyAlgoECDSA:
300		curve := ecc.FindECDSAByGenName(string(config.CurveName()))
301		if curve == nil {
302			return nil, errors.InvalidArgumentError("unsupported curve")
303		}
304
305		priv, err := ecdsa.GenerateKey(config.Random(), curve)
306		if err != nil {
307			return nil, err
308		}
309		return priv, nil
310	case packet.PubKeyAlgoEd25519:
311		priv, err := ed25519.GenerateKey(config.Random())
312		if err != nil {
313			return nil, err
314		}
315		return priv, nil
316	case packet.PubKeyAlgoEd448:
317		priv, err := ed448.GenerateKey(config.Random())
318		if err != nil {
319			return nil, err
320		}
321		return priv, nil
322	default:
323		return nil, errors.InvalidArgumentError("unsupported public key algorithm")
324	}
325}
326
327// Generates an encryption/decryption key
328func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
329	switch config.PublicKeyAlgorithm() {
330	case packet.PubKeyAlgoRSA:
331		bits := config.RSAModulusBits()
332		if bits < 1024 {
333			return nil, errors.InvalidArgumentError("bits must be >= 1024")
334		}
335		if config != nil && len(config.RSAPrimes) >= 2 {
336			primes := config.RSAPrimes[0:2]
337			config.RSAPrimes = config.RSAPrimes[2:]
338			return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
339		}
340		return rsa.GenerateKey(config.Random(), bits)
341	case packet.PubKeyAlgoEdDSA, packet.PubKeyAlgoECDSA:
342		fallthrough // When passing EdDSA or ECDSA, we generate an ECDH subkey
343	case packet.PubKeyAlgoECDH:
344		if config.V6() &&
345			(config.CurveName() == packet.Curve25519 ||
346				config.CurveName() == packet.Curve448) {
347			// Implementations MUST NOT accept or generate v6 key material
348			// using the deprecated OIDs.
349			return nil, errors.InvalidArgumentError("ECDH with Curve25519/448 legacy cannot be used for v6 keys")
350		}
351		var kdf = ecdh.KDF{
352			Hash:   algorithm.SHA512,
353			Cipher: algorithm.AES256,
354		}
355		curve := ecc.FindECDHByGenName(string(config.CurveName()))
356		if curve == nil {
357			return nil, errors.InvalidArgumentError("unsupported curve")
358		}
359		return ecdh.GenerateKey(config.Random(), curve, kdf)
360	case packet.PubKeyAlgoEd25519, packet.PubKeyAlgoX25519: // When passing Ed25519, we generate an x25519 subkey
361		return x25519.GenerateKey(config.Random())
362	case packet.PubKeyAlgoEd448, packet.PubKeyAlgoX448: // When passing Ed448, we generate an x448 subkey
363		return x448.GenerateKey(config.Random())
364	default:
365		return nil, errors.InvalidArgumentError("unsupported public key algorithm")
366	}
367}
368
369var bigOne = big.NewInt(1)
370
371// generateRSAKeyWithPrimes generates a multi-prime RSA keypair of the
372// given bit size, using the given random source and pre-populated primes.
373func generateRSAKeyWithPrimes(random io.Reader, nprimes int, bits int, prepopulatedPrimes []*big.Int) (*rsa.PrivateKey, error) {
374	priv := new(rsa.PrivateKey)
375	priv.E = 65537
376
377	if nprimes < 2 {
378		return nil, goerrors.New("generateRSAKeyWithPrimes: nprimes must be >= 2")
379	}
380
381	if bits < 1024 {
382		return nil, goerrors.New("generateRSAKeyWithPrimes: bits must be >= 1024")
383	}
384
385	primes := make([]*big.Int, nprimes)
386
387NextSetOfPrimes:
388	for {
389		todo := bits
390		// crypto/rand should set the top two bits in each prime.
391		// Thus each prime has the form
392		//   p_i = 2^bitlen(p_i) × 0.11... (in base 2).
393		// And the product is:
394		//   P = 2^todo × α
395		// where α is the product of nprimes numbers of the form 0.11...
396		//
397		// If α < 1/2 (which can happen for nprimes > 2), we need to
398		// shift todo to compensate for lost bits: the mean value of 0.11...
399		// is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2
400		// will give good results.
401		if nprimes >= 7 {
402			todo += (nprimes - 2) / 5
403		}
404		for i := 0; i < nprimes; i++ {
405			var err error
406			if len(prepopulatedPrimes) == 0 {
407				primes[i], err = rand.Prime(random, todo/(nprimes-i))
408				if err != nil {
409					return nil, err
410				}
411			} else {
412				primes[i] = prepopulatedPrimes[0]
413				prepopulatedPrimes = prepopulatedPrimes[1:]
414			}
415
416			todo -= primes[i].BitLen()
417		}
418
419		// Make sure that primes is pairwise unequal.
420		for i, prime := range primes {
421			for j := 0; j < i; j++ {
422				if prime.Cmp(primes[j]) == 0 {
423					continue NextSetOfPrimes
424				}
425			}
426		}
427
428		n := new(big.Int).Set(bigOne)
429		totient := new(big.Int).Set(bigOne)
430		pminus1 := new(big.Int)
431		for _, prime := range primes {
432			n.Mul(n, prime)
433			pminus1.Sub(prime, bigOne)
434			totient.Mul(totient, pminus1)
435		}
436		if n.BitLen() != bits {
437			// This should never happen for nprimes == 2 because
438			// crypto/rand should set the top two bits in each prime.
439			// For nprimes > 2 we hope it does not happen often.
440			continue NextSetOfPrimes
441		}
442
443		priv.D = new(big.Int)
444		e := big.NewInt(int64(priv.E))
445		ok := priv.D.ModInverse(e, totient)
446
447		if ok != nil {
448			priv.Primes = primes
449			priv.N = n
450			break
451		}
452	}
453
454	priv.Precompute()
455	return priv, nil
456}