1 package s2k 2 3 import "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. 8 type 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 50 type Argon2Config struct { 51 NumberOfPasses uint8 52 DegreeOfParallelism uint8 53 // The memory parameter for Argon2 specifies desired memory usage in kibibytes. 54 // For example memory=64*1024 sets the memory cost to ~64 MB. 55 Memory uint32 56 } 57 58 func (c *Config) Mode() Mode { 59 if c == nil { 60 return IteratedSaltedS2K 61 } 62 return c.S2KMode 63 } 64 65 func (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 73 func (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 81 func (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 98 func (c *Argon2Config) Passes() uint8 { 99 if c == nil || c.NumberOfPasses == 0 { 100 return 3 101 } 102 return c.NumberOfPasses 103 } 104 105 func (c *Argon2Config) Parallelism() uint8 { 106 if c == nil || c.DegreeOfParallelism == 0 { 107 return 4 108 } 109 return c.DegreeOfParallelism 110 } 111 112 func (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 } 130