main
1package s2k
2
3import "crypto"
4
5// Config collects configuration parameters for s2k key-stretching
6// transformations. A nil *Config is valid and results in all default
7// values.
8type Config struct {
9 // S2K (String to Key) mode, used for key derivation in the context of secret key encryption
10 // and passphrase-encrypted data. Either s2k.Argon2S2K or s2k.IteratedSaltedS2K may be used.
11 // If the passphrase is a high-entropy key, indicated by setting PassphraseIsHighEntropy to true,
12 // s2k.SaltedS2K can also be used.
13 // Note: Argon2 is the strongest option but not all OpenPGP implementations are compatible with it
14 //(pending standardisation).
15 // 0 (simple), 1(salted), 3(iterated), 4(argon2)
16 // 2(reserved) 100-110(private/experimental).
17 S2KMode Mode
18 // Only relevant if S2KMode is not set to s2k.Argon2S2K.
19 // Hash is the default hash function to be used. If
20 // nil, SHA256 is used.
21 Hash crypto.Hash
22 // Argon2 parameters for S2K (String to Key).
23 // Only relevant if S2KMode is set to s2k.Argon2S2K.
24 // If nil, default parameters are used.
25 // For more details on the choice of parameters, see https://tools.ietf.org/html/rfc9106#section-4.
26 Argon2Config *Argon2Config
27 // Only relevant if S2KMode is set to s2k.IteratedSaltedS2K.
28 // Iteration count for Iterated S2K (String to Key). It
29 // determines the strength of the passphrase stretching when
30 // the said passphrase is hashed to produce a key. S2KCount
31 // should be between 65536 and 65011712, inclusive. If Config
32 // is nil or S2KCount is 0, the value 16777216 used. Not all
33 // values in the above range can be represented. S2KCount will
34 // be rounded up to the next representable value if it cannot
35 // be encoded exactly. When set, it is strongly encrouraged to
36 // use a value that is at least 65536. See RFC 4880 Section
37 // 3.7.1.3.
38 S2KCount int
39 // Indicates whether the passphrase passed by the application is a
40 // high-entropy key (e.g. it's randomly generated or derived from
41 // another passphrase using a strong key derivation function).
42 // When true, allows the S2KMode to be s2k.SaltedS2K.
43 // When the passphrase is not a high-entropy key, using SaltedS2K is
44 // insecure, and not allowed by draft-ietf-openpgp-crypto-refresh-08.
45 PassphraseIsHighEntropy bool
46}
47
48// Argon2Config stores the Argon2 parameters
49// A nil *Argon2Config is valid and results in all default
50type Argon2Config struct {
51 NumberOfPasses uint8
52 DegreeOfParallelism uint8
53 // Memory specifies the desired Argon2 memory usage in kibibytes.
54 // For example memory=64*1024 sets the memory cost to ~64 MB.
55 Memory uint32
56}
57
58func (c *Config) Mode() Mode {
59 if c == nil {
60 return IteratedSaltedS2K
61 }
62 return c.S2KMode
63}
64
65func (c *Config) hash() crypto.Hash {
66 if c == nil || uint(c.Hash) == 0 {
67 return crypto.SHA256
68 }
69
70 return c.Hash
71}
72
73func (c *Config) Argon2() *Argon2Config {
74 if c == nil || c.Argon2Config == nil {
75 return nil
76 }
77 return c.Argon2Config
78}
79
80// EncodedCount get encoded count
81func (c *Config) EncodedCount() uint8 {
82 if c == nil || c.S2KCount == 0 {
83 return 224 // The common case. Corresponding to 16777216
84 }
85
86 i := c.S2KCount
87
88 switch {
89 case i < 65536:
90 i = 65536
91 case i > 65011712:
92 i = 65011712
93 }
94
95 return encodeCount(i)
96}
97
98func (c *Argon2Config) Passes() uint8 {
99 if c == nil || c.NumberOfPasses == 0 {
100 return 3
101 }
102 return c.NumberOfPasses
103}
104
105func (c *Argon2Config) Parallelism() uint8 {
106 if c == nil || c.DegreeOfParallelism == 0 {
107 return 4
108 }
109 return c.DegreeOfParallelism
110}
111
112func (c *Argon2Config) EncodedMemory() uint8 {
113 if c == nil || c.Memory == 0 {
114 return 16 // 64 MiB of RAM
115 }
116
117 memory := c.Memory
118 lowerBound := uint32(c.Parallelism()) * 8
119 upperBound := uint32(2147483648)
120
121 switch {
122 case memory < lowerBound:
123 memory = lowerBound
124 case memory > upperBound:
125 memory = upperBound
126 }
127
128 return encodeMemory(memory, c.Parallelism())
129}