1
2
3
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
26
27
28
29 func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
30 creationTime := config.Now()
31 keyLifetimeSecs := config.KeyLifetime()
32
33
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
56
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
93 selfSignature.SEIPDv2 = config.AEAD() != nil
94
95
96
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
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
114
115
116
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
123 modes := []uint8{uint8(config.AEAD().Mode())}
124 if config.AEAD().Mode() != packet.AEADModeOCB {
125 modes = append(modes, uint8(packet.AEADModeOCB))
126 }
127
128
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
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
150
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
192
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
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
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
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
305
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
324
325
326
327
328
329
330
331
332
333
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
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
371
372
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