|
|
@@ -23,6 +23,17 @@ type Config struct {
|
|
|
// Hash is the default hash function to be used. If
|
|
|
// nil, SHA1 is used.
|
|
|
Hash crypto.Hash
|
|
|
+ // S2KCount is only used for symmetric encryption. It
|
|
|
+ // determines the strength of the passphrase stretching when
|
|
|
+ // the said passphrase is hashed to produce a key. S2KCount
|
|
|
+ // should be between 1024 and 65011712, inclusive. If Config
|
|
|
+ // is nil or S2KCount is 0, the value 65536 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.
|
|
|
+ S2KCount int
|
|
|
}
|
|
|
|
|
|
func (c *Config) hash() crypto.Hash {
|
|
|
@@ -34,6 +45,49 @@ func (c *Config) hash() crypto.Hash {
|
|
|
return c.Hash
|
|
|
}
|
|
|
|
|
|
+func (c *Config) encodedCount() uint8 {
|
|
|
+ if c == nil || c.S2KCount == 0 {
|
|
|
+ return 96 // The common case. Correspoding to 65536
|
|
|
+ }
|
|
|
+
|
|
|
+ i := c.S2KCount
|
|
|
+ switch {
|
|
|
+ // Behave like GPG. Should we make 65536 the lowest value used?
|
|
|
+ case i < 1024:
|
|
|
+ i = 1024
|
|
|
+ case i > 65011712:
|
|
|
+ i = 65011712
|
|
|
+ }
|
|
|
+
|
|
|
+ return encodeCount(i)
|
|
|
+}
|
|
|
+
|
|
|
+// encodeCount converts an iterative "count" in the range 1024 to
|
|
|
+// 65011712, inclusive, to an encoded count. The return value is the
|
|
|
+// octet that is actually stored in the GPG file. encodeCount panics
|
|
|
+// if i is not in the above range (encodedCount above takes care to
|
|
|
+// pass i in the correct range). See RFC 4880 Section 3.7.7.1.
|
|
|
+func encodeCount(i int) uint8 {
|
|
|
+ if i < 1024 || i > 65011712 {
|
|
|
+ panic("count arg i outside the required range")
|
|
|
+ }
|
|
|
+
|
|
|
+ for encoded := 0; encoded < 256; encoded++ {
|
|
|
+ count := decodeCount(uint8(encoded))
|
|
|
+ if count >= i {
|
|
|
+ return uint8(encoded)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 255
|
|
|
+}
|
|
|
+
|
|
|
+// decodeCount returns the s2k mode 3 iterative "count" corresponding to
|
|
|
+// the encoded octet c.
|
|
|
+func decodeCount(c uint8) int {
|
|
|
+ return (16 + int(c&15)) << (uint32(c>>4) + 6)
|
|
|
+}
|
|
|
+
|
|
|
// Simple writes to out the result of computing the Simple S2K function (RFC
|
|
|
// 4880, section 3.7.1.1) using the given hash and input passphrase.
|
|
|
func Simple(out []byte, h hash.Hash, in []byte) {
|
|
|
@@ -136,7 +190,7 @@ func Parse(r io.Reader) (f func(out, in []byte), err error) {
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
- count := (16 + int(buf[8]&15)) << (uint32(buf[8]>>4) + 6)
|
|
|
+ count := decodeCount(buf[8])
|
|
|
f := func(out, in []byte) {
|
|
|
Iterated(out, h, in, buf[:8], count)
|
|
|
}
|
|
|
@@ -158,8 +212,9 @@ func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Co
|
|
|
if _, err := io.ReadFull(rand, salt); err != nil {
|
|
|
return err
|
|
|
}
|
|
|
- const count = 65536 // this is the default in gpg
|
|
|
- buf[10] = 96 // 65536 iterations
|
|
|
+ encodedCount := c.encodedCount()
|
|
|
+ count := decodeCount(encodedCount)
|
|
|
+ buf[10] = encodedCount
|
|
|
if _, err := w.Write(buf[:]); err != nil {
|
|
|
return err
|
|
|
}
|