File: config.go

package info (click to toggle)
golang-github-protonmail-go-crypto 1.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,932 kB
  • sloc: makefile: 10
file content (434 lines) | stat: -rw-r--r-- 14,470 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package packet

import (
	"crypto"
	"crypto/rand"
	"io"
	"math/big"
	"time"

	"github.com/ProtonMail/go-crypto/openpgp/s2k"
)

var (
	defaultRejectPublicKeyAlgorithms = map[PublicKeyAlgorithm]bool{
		PubKeyAlgoElGamal: true,
		PubKeyAlgoDSA:     true,
	}
	defaultRejectHashAlgorithms = map[crypto.Hash]bool{
		crypto.MD5:       true,
		crypto.RIPEMD160: true,
	}
	defaultRejectMessageHashAlgorithms = map[crypto.Hash]bool{
		crypto.SHA1:      true,
		crypto.MD5:       true,
		crypto.RIPEMD160: true,
	}
	defaultRejectCurves = map[Curve]bool{
		CurveSecP256k1: true,
	}
)

// A global feature flag to indicate v5 support.
// Can be set via a build tag, e.g.: `go build -tags v5 ./...`
// If the build tag is missing config_v5.go will set it to true.
//
// Disables parsing of v5 keys and v5 signatures.
// These are non-standard entities, which in the crypto-refresh have been superseded
// by v6 keys, v6 signatures and SEIPDv2 encrypted data, respectively.
var V5Disabled = false

// Config collects a number of parameters along with sensible defaults.
// A nil *Config is valid and results in all default values.
type Config struct {
	// Rand provides the source of entropy.
	// If nil, the crypto/rand Reader is used.
	Rand io.Reader
	// DefaultHash is the default hash function to be used.
	// If zero, SHA-256 is used.
	DefaultHash crypto.Hash
	// DefaultCipher is the cipher to be used.
	// If zero, AES-128 is used.
	DefaultCipher CipherFunction
	// Time returns the current time as the number of seconds since the
	// epoch. If Time is nil, time.Now is used.
	Time func() time.Time
	// DefaultCompressionAlgo is the compression algorithm to be
	// applied to the plaintext before encryption. If zero, no
	// compression is done.
	DefaultCompressionAlgo CompressionAlgo
	// CompressionConfig configures the compression settings.
	CompressionConfig *CompressionConfig
	// S2K (String to Key) config, used for key derivation in the context of secret key encryption
	// and password-encrypted data.
	// If nil, the default configuration is used
	S2KConfig *s2k.Config
	// Iteration count for Iterated S2K (String to Key).
	// Only used if sk2.Mode is nil.
	// This value is duplicated here from s2k.Config for backwards compatibility.
	// It determines the strength of the passphrase stretching when
	// the said passphrase is hashed to produce a key. S2KCount
	// should be between 65536 and 65011712, inclusive. If Config
	// is nil or S2KCount is 0, the value 16777216 used. Not all
	// values in the above range can be represented. S2KCount will
	// be rounded up to the next representable value if it cannot
	// be encoded exactly. When set, it is strongly encrouraged to
	// use a value that is at least 65536. See RFC 4880 Section
	// 3.7.1.3.
	//
	// Deprecated: SK2Count should be configured in S2KConfig instead.
	S2KCount int
	// RSABits is the number of bits in new RSA keys made with NewEntity.
	// If zero, then 2048 bit keys are created.
	RSABits int
	// The public key algorithm to use - will always create a signing primary
	// key and encryption subkey.
	Algorithm PublicKeyAlgorithm
	// Some known primes that are optionally prepopulated by the caller
	RSAPrimes []*big.Int
	// Curve configures the desired packet.Curve if the Algorithm is PubKeyAlgoECDSA,
	// PubKeyAlgoEdDSA, or PubKeyAlgoECDH. If empty Curve25519 is used.
	Curve Curve
	// AEADConfig configures the use of the new AEAD Encrypted Data Packet,
	// defined in the draft of the next version of the OpenPGP specification.
	// If a non-nil AEADConfig is passed, usage of this packet is enabled. By
	// default, it is disabled. See the documentation of AEADConfig for more
	// configuration options related to AEAD.
	// **Note: using this option may break compatibility with other OpenPGP
	// implementations, as well as future versions of this library.**
	AEADConfig *AEADConfig
	// V6Keys configures version 6 key generation. If false, this package still
	// supports version 6 keys, but produces version 4 keys.
	V6Keys bool
	// Minimum RSA key size allowed for key generation and message signing, verification and encryption.
	MinRSABits uint16
	// Reject insecure algorithms, only works with v2 api
	RejectPublicKeyAlgorithms   map[PublicKeyAlgorithm]bool
	RejectHashAlgorithms        map[crypto.Hash]bool
	RejectMessageHashAlgorithms map[crypto.Hash]bool
	RejectCurves                map[Curve]bool
	// "The validity period of the key.  This is the number of seconds after
	// the key creation time that the key expires.  If this is not present
	// or has a value of zero, the key never expires.  This is found only on
	// a self-signature.""
	// https://tools.ietf.org/html/rfc4880#section-5.2.3.6
	KeyLifetimeSecs uint32
	// "The validity period of the signature.  This is the number of seconds
	// after the signature creation time that the signature expires.  If
	// this is not present or has a value of zero, it never expires."
	// https://tools.ietf.org/html/rfc4880#section-5.2.3.10
	SigLifetimeSecs uint32
	// SigningKeyId is used to specify the signing key to use (by Key ID).
	// By default, the signing key is selected automatically, preferring
	// signing subkeys if available.
	SigningKeyId uint64
	// SigningIdentity is used to specify a user ID (packet Signer's User ID, type 28)
	// when producing a generic certification signature onto an existing user ID.
	// The identity must be present in the signer Entity.
	SigningIdentity string
	// InsecureAllowUnauthenticatedMessages controls, whether it is tolerated to read
	// encrypted messages without Modification Detection Code (MDC).
	// MDC is mandated by the IETF OpenPGP Crypto Refresh draft and has long been implemented
	// in most OpenPGP implementations. Messages without MDC are considered unnecessarily
	// insecure and should be prevented whenever possible.
	// In case one needs to deal with messages from very old OpenPGP implementations, there
	// might be no other way than to tolerate the missing MDC. Setting this flag, allows this
	// mode of operation. It should be considered a measure of last resort.
	InsecureAllowUnauthenticatedMessages bool
	// InsecureAllowDecryptionWithSigningKeys allows decryption with keys marked as signing keys in the v2 API.
	// This setting is potentially insecure, but it is needed as some libraries
	// ignored key flags when selecting a key for encryption.
	// Not relevant for the v1 API, as all keys were allowed in decryption.
	InsecureAllowDecryptionWithSigningKeys bool
	// KnownNotations is a map of Notation Data names to bools, which controls
	// the notation names that are allowed to be present in critical Notation Data
	// signature subpackets.
	KnownNotations map[string]bool
	// SignatureNotations is a list of Notations to be added to any signatures.
	SignatureNotations []*Notation
	// CheckIntendedRecipients controls, whether the OpenPGP Intended Recipient Fingerprint feature
	// should be enabled for encryption and decryption.
	// (See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr).
	// When the flag is set, encryption produces Intended Recipient Fingerprint signature sub-packets and decryption
	// checks whether the key it was encrypted to is one of the included fingerprints in the signature.
	// If the flag is disabled, no Intended Recipient Fingerprint sub-packets are created or checked.
	// The default behavior, when the config or flag is nil, is to enable the feature.
	CheckIntendedRecipients *bool
	// CacheSessionKey controls if decryption should return the session key used for decryption.
	// If the flag is set, the session key is cached in the message details struct.
	CacheSessionKey bool
	// CheckPacketSequence is a flag that controls if the pgp message reader should strictly check
	// that the packet sequence conforms with the grammar mandated by rfc4880.
	// The default behavior, when the config or flag is nil, is to check the packet sequence.
	CheckPacketSequence *bool
	// NonDeterministicSignaturesViaNotation is a flag to enable randomization of signatures.
	// If true, a salt notation is used to randomize signatures generated by v4 and v5 keys
	// (v6 signatures are always non-deterministic, by design).
	// This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
	// during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of
	// weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
	// The default behavior, when the config or flag is nil, is to enable the feature.
	NonDeterministicSignaturesViaNotation *bool

	// InsecureAllowAllKeyFlagsWhenMissing determines how a key without valid key flags is handled.
	// When set to true, a key without flags is treated as if all flags are enabled.
	// This behavior is consistent with GPG.
	InsecureAllowAllKeyFlagsWhenMissing bool

	// MaxDecompressedMessageSize specifies the maximum number of bytes that can be
	// read from a compressed packet. This serves as an upper limit to prevent
	// excessively large decompressed messages.
	MaxDecompressedMessageSize *int64
}

func (c *Config) Random() io.Reader {
	if c == nil || c.Rand == nil {
		return rand.Reader
	}
	return c.Rand
}

func (c *Config) Hash() crypto.Hash {
	if c == nil || uint(c.DefaultHash) == 0 {
		return crypto.SHA256
	}
	return c.DefaultHash
}

func (c *Config) Cipher() CipherFunction {
	if c == nil || uint8(c.DefaultCipher) == 0 {
		return CipherAES128
	}
	return c.DefaultCipher
}

func (c *Config) Now() time.Time {
	if c == nil || c.Time == nil {
		return time.Now().Truncate(time.Second)
	}
	return c.Time().Truncate(time.Second)
}

// KeyLifetime returns the validity period of the key.
func (c *Config) KeyLifetime() uint32 {
	if c == nil {
		return 0
	}
	return c.KeyLifetimeSecs
}

// SigLifetime returns the validity period of the signature.
func (c *Config) SigLifetime() uint32 {
	if c == nil {
		return 0
	}
	return c.SigLifetimeSecs
}

func (c *Config) Compression() CompressionAlgo {
	if c == nil {
		return CompressionNone
	}
	return c.DefaultCompressionAlgo
}

func (c *Config) RSAModulusBits() int {
	if c == nil || c.RSABits == 0 {
		return 2048
	}
	return c.RSABits
}

func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm {
	if c == nil || c.Algorithm == 0 {
		return PubKeyAlgoRSA
	}
	return c.Algorithm
}

func (c *Config) CurveName() Curve {
	if c == nil || c.Curve == "" {
		return Curve25519
	}
	return c.Curve
}

// Deprecated: The hash iterations should now be queried via the S2K() method.
func (c *Config) PasswordHashIterations() int {
	if c == nil || c.S2KCount == 0 {
		return 0
	}
	return c.S2KCount
}

func (c *Config) S2K() *s2k.Config {
	if c == nil {
		return nil
	}
	// for backwards compatibility
	if c.S2KCount > 0 && c.S2KConfig == nil {
		return &s2k.Config{
			S2KCount: c.S2KCount,
		}
	}
	return c.S2KConfig
}

func (c *Config) AEAD() *AEADConfig {
	if c == nil {
		return nil
	}
	return c.AEADConfig
}

func (c *Config) SigningKey() uint64 {
	if c == nil {
		return 0
	}
	return c.SigningKeyId
}

func (c *Config) SigningUserId() string {
	if c == nil {
		return ""
	}
	return c.SigningIdentity
}

func (c *Config) AllowUnauthenticatedMessages() bool {
	if c == nil {
		return false
	}
	return c.InsecureAllowUnauthenticatedMessages
}

func (c *Config) AllowDecryptionWithSigningKeys() bool {
	if c == nil {
		return false
	}
	return c.InsecureAllowDecryptionWithSigningKeys
}

func (c *Config) KnownNotation(notationName string) bool {
	if c == nil {
		return false
	}
	return c.KnownNotations[notationName]
}

func (c *Config) Notations() []*Notation {
	if c == nil {
		return nil
	}
	return c.SignatureNotations
}

func (c *Config) V6() bool {
	if c == nil {
		return false
	}
	return c.V6Keys
}

func (c *Config) IntendedRecipients() bool {
	if c == nil || c.CheckIntendedRecipients == nil {
		return true
	}
	return *c.CheckIntendedRecipients
}

func (c *Config) RetrieveSessionKey() bool {
	if c == nil {
		return false
	}
	return c.CacheSessionKey
}

func (c *Config) MinimumRSABits() uint16 {
	if c == nil || c.MinRSABits == 0 {
		return 2047
	}
	return c.MinRSABits
}

func (c *Config) RejectPublicKeyAlgorithm(alg PublicKeyAlgorithm) bool {
	var rejectedAlgorithms map[PublicKeyAlgorithm]bool
	if c == nil || c.RejectPublicKeyAlgorithms == nil {
		// Default
		rejectedAlgorithms = defaultRejectPublicKeyAlgorithms
	} else {
		rejectedAlgorithms = c.RejectPublicKeyAlgorithms
	}
	return rejectedAlgorithms[alg]
}

func (c *Config) RejectHashAlgorithm(hash crypto.Hash) bool {
	var rejectedAlgorithms map[crypto.Hash]bool
	if c == nil || c.RejectHashAlgorithms == nil {
		// Default
		rejectedAlgorithms = defaultRejectHashAlgorithms
	} else {
		rejectedAlgorithms = c.RejectHashAlgorithms
	}
	return rejectedAlgorithms[hash]
}

func (c *Config) RejectMessageHashAlgorithm(hash crypto.Hash) bool {
	var rejectedAlgorithms map[crypto.Hash]bool
	if c == nil || c.RejectMessageHashAlgorithms == nil {
		// Default
		rejectedAlgorithms = defaultRejectMessageHashAlgorithms
	} else {
		rejectedAlgorithms = c.RejectMessageHashAlgorithms
	}
	return rejectedAlgorithms[hash]
}

func (c *Config) RejectCurve(curve Curve) bool {
	var rejectedCurve map[Curve]bool
	if c == nil || c.RejectCurves == nil {
		// Default
		rejectedCurve = defaultRejectCurves
	} else {
		rejectedCurve = c.RejectCurves
	}
	return rejectedCurve[curve]
}

func (c *Config) StrictPacketSequence() bool {
	if c == nil || c.CheckPacketSequence == nil {
		return true
	}
	return *c.CheckPacketSequence
}

func (c *Config) RandomizeSignaturesViaNotation() bool {
	if c == nil || c.NonDeterministicSignaturesViaNotation == nil {
		return true
	}
	return *c.NonDeterministicSignaturesViaNotation
}

func (c *Config) AllowAllKeyFlagsWhenMissing() bool {
	if c == nil {
		return false
	}
	return c.InsecureAllowAllKeyFlagsWhenMissing
}

func (c *Config) DecompressedMessageSizeLimit() *int64 {
	if c == nil {
		return nil
	}
	return c.MaxDecompressedMessageSize
}

// BoolPointer is a helper function to set a boolean pointer in the Config.
// e.g., config.CheckPacketSequence = BoolPointer(true)
func BoolPointer(value bool) *bool {
	return &value
}