Copyright 2011 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 s2k implements the various OpenPGP string-to-key transforms as specified in RFC 4800 section 3.7.1.
package s2k // import "golang.org/x/crypto/openpgp/s2k"

import (
	
	
	
	

	
)
Config collects configuration parameters for s2k key-stretching transformatioms. A nil *Config is valid and results in all default values. Currently, Config is used only by the Serialize function in this package.
Hash is the default hash function to be used. If nil, SHA1 is used.
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 ( *Config) () crypto.Hash {
SHA1 is the historical default in this package.
		return crypto.SHA1
	}

	return .Hash
}

func ( *Config) () uint8 {
	if  == nil || .S2KCount == 0 {
		return 96 // The common case. Correspoding to 65536
	}

	 := .S2KCount
Behave like GPG. Should we make 65536 the lowest value used?
	case  < 1024:
		 = 1024
	case  > 65011712:
		 = 65011712
	}

	return encodeCount()
}
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 ( int) uint8 {
	if  < 1024 ||  > 65011712 {
		panic("count arg i outside the required range")
	}

	for  := 0;  < 256; ++ {
		 := decodeCount(uint8())
		if  >=  {
			return uint8()
		}
	}

	return 255
}
decodeCount returns the s2k mode 3 iterative "count" corresponding to the encoded octet c.
func ( uint8) int {
	return (16 + int(&15)) << (uint32(>>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 ( []byte,  hash.Hash,  []byte) {
	Salted(, , , nil)
}

var zero [1]byte
Salted writes to out the result of computing the Salted S2K function (RFC 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
func ( []byte,  hash.Hash,  []byte,  []byte) {
	 := 0
	var  []byte

	for  := 0;  < len(); ++ {
		.Reset()
		for  := 0;  < ; ++ {
			.Write(zero[:])
		}
		.Write()
		.Write()
		 = .Sum([:0])
		 := copy([:], )
		 += 
	}
}
Iterated writes to out the result of computing the Iterated and Salted S2K function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, salt and iteration count.
func ( []byte,  hash.Hash,  []byte,  []byte,  int) {
	 := make([]byte, len()+len())
	copy(, )
	copy([len():], )

	if  < len() {
		 = len()
	}

	 := 0
	var  []byte
	for  := 0;  < len(); ++ {
		.Reset()
		for  := 0;  < ; ++ {
			.Write(zero[:])
		}
		 := 0
		for  <  {
			if +len() >  {
				 :=  - 
				.Write([:])
				 = 
			} else {
				.Write()
				 += len()
			}
		}
		 = .Sum([:0])
		 := copy([:], )
		 += 
	}
}
Parse reads a binary specification for a string-to-key transformation from r and returns a function which performs that transform.
func ( io.Reader) ( func(,  []byte),  error) {
	var  [9]byte

	_,  = io.ReadFull(, [:2])
	if  != nil {
		return
	}

	,  := HashIdToHash([1])
	if ! {
		return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int([1])))
	}
	if !.Available() {
		return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int()))
	}
	 := .New()

	switch [0] {
	case 0:
		 := func(,  []byte) {
			Simple(, , )
		}
		return , nil
	case 1:
		_,  = io.ReadFull(, [:8])
		if  != nil {
			return
		}
		 := func(,  []byte) {
			Salted(, , , [:8])
		}
		return , nil
	case 3:
		_,  = io.ReadFull(, [:9])
		if  != nil {
			return
		}
		 := decodeCount([8])
		 := func(,  []byte) {
			Iterated(, , , [:8], )
		}
		return , nil
	}

	return nil, errors.UnsupportedError("S2K function")
}
Serialize salts and stretches the given passphrase and writes the resulting key into key. It also serializes an S2K descriptor to w. The key stretching can be configured with c, which may be nil. In that case, sensible defaults will be used.
func ( io.Writer,  []byte,  io.Reader,  []byte,  *Config) error {
	var  [11]byte
	[0] = 3 /* iterated and salted */
	[1], _ = HashToHashId(.hash())
	 := [2:10]
	if ,  := io.ReadFull(, );  != nil {
		return 
	}
	 := .encodedCount()
	 := decodeCount()
	[10] = 
	if ,  := .Write([:]);  != nil {
		return 
	}

	Iterated(, .hash().New(), , , )
	return nil
}
hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with Go's crypto.Hash type. See RFC 4880, section 9.4.
var hashToHashIdMapping = []struct {
	id   byte
	hash crypto.Hash
	name string
}{
	{1, crypto.MD5, "MD5"},
	{2, crypto.SHA1, "SHA1"},
	{3, crypto.RIPEMD160, "RIPEMD160"},
	{8, crypto.SHA256, "SHA256"},
	{9, crypto.SHA384, "SHA384"},
	{10, crypto.SHA512, "SHA512"},
	{11, crypto.SHA224, "SHA224"},
}
HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP hash id.
func ( byte) ( crypto.Hash,  bool) {
	for ,  := range hashToHashIdMapping {
		if .id ==  {
			return .hash, true
		}
	}
	return 0, false
}
HashIdToString returns the name of the hash function corresponding to the given OpenPGP hash id.
func ( byte) ( string,  bool) {
	for ,  := range hashToHashIdMapping {
		if .id ==  {
			return .name, true
		}
	}

	return "", false
}
HashIdToHash returns an OpenPGP hash id which corresponds the given Hash.
func ( crypto.Hash) ( byte,  bool) {
	for ,  := range hashToHashIdMapping {
		if .hash ==  {
			return .id, true
		}
	}
	return 0, false