...

Source file src/github.com/ProtonMail/go-crypto/openpgp/key_generation.go

Documentation: github.com/ProtonMail/go-crypto/openpgp

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

View as plain text