mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	Switch to keybase go-crypto (for some elliptic curve key) + test (#1925)
* Switch to keybase go-crypto (for some elliptic curve key) + test
* Use assert.NoError 
and add a little more context to failing test description
* Use assert.(No)Error everywhere 🌈
and assert.Error in place of .Nil/.NotNil
			
			
This commit is contained in:
		
				
					committed by
					
						 Lunny Xiao
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							5e92b82ac6
						
					
				
				
					commit
					274149dd14
				
			
							
								
								
									
										326
									
								
								vendor/github.com/keybase/go-crypto/openpgp/s2k/s2k.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								vendor/github.com/keybase/go-crypto/openpgp/s2k/s2k.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,326 @@ | ||||
| // 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 "github.com/keybase/go-crypto/openpgp/s2k" | ||||
|  | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"hash" | ||||
| 	"io" | ||||
| 	"strconv" | ||||
|  | ||||
| 	"github.com/keybase/go-crypto/openpgp/errors" | ||||
| ) | ||||
|  | ||||
| // 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. | ||||
| 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 { | ||||
| 	if c == nil || uint(c.Hash) == 0 { | ||||
| 		// SHA1 is the historical default in this package. | ||||
| 		return crypto.SHA1 | ||||
| 	} | ||||
|  | ||||
| 	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) { | ||||
| 	Salted(out, h, in, 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 Salted(out []byte, h hash.Hash, in []byte, salt []byte) { | ||||
| 	done := 0 | ||||
| 	var digest []byte | ||||
|  | ||||
| 	for i := 0; done < len(out); i++ { | ||||
| 		h.Reset() | ||||
| 		for j := 0; j < i; j++ { | ||||
| 			h.Write(zero[:]) | ||||
| 		} | ||||
| 		h.Write(salt) | ||||
| 		h.Write(in) | ||||
| 		digest = h.Sum(digest[:0]) | ||||
| 		n := copy(out[done:], digest) | ||||
| 		done += n | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 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 Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { | ||||
| 	combined := make([]byte, len(in)+len(salt)) | ||||
| 	copy(combined, salt) | ||||
| 	copy(combined[len(salt):], in) | ||||
|  | ||||
| 	if count < len(combined) { | ||||
| 		count = len(combined) | ||||
| 	} | ||||
|  | ||||
| 	done := 0 | ||||
| 	var digest []byte | ||||
| 	for i := 0; done < len(out); i++ { | ||||
| 		h.Reset() | ||||
| 		for j := 0; j < i; j++ { | ||||
| 			h.Write(zero[:]) | ||||
| 		} | ||||
| 		written := 0 | ||||
| 		for written < count { | ||||
| 			if written+len(combined) > count { | ||||
| 				todo := count - written | ||||
| 				h.Write(combined[:todo]) | ||||
| 				written = count | ||||
| 			} else { | ||||
| 				h.Write(combined) | ||||
| 				written += len(combined) | ||||
| 			} | ||||
| 		} | ||||
| 		digest = h.Sum(digest[:0]) | ||||
| 		n := copy(out[done:], digest) | ||||
| 		done += n | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func parseGNUExtensions(r io.Reader) (f func(out, in []byte), err error) { | ||||
| 	var buf [9]byte | ||||
|  | ||||
| 	// A three-byte string identifier | ||||
| 	_, err = io.ReadFull(r, buf[:3]) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	gnuExt := string(buf[:3]) | ||||
|  | ||||
| 	if gnuExt != "GNU" { | ||||
| 		return nil, errors.UnsupportedError("Malformed GNU extension: " + gnuExt) | ||||
| 	} | ||||
| 	_, err = io.ReadFull(r, buf[:1]) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	gnuExtType := int(buf[0]) | ||||
| 	switch gnuExtType { | ||||
| 	case 1: | ||||
| 		return nil, nil | ||||
| 	case 2: | ||||
| 		// Read a serial number, which is prefixed by a 1-byte length. | ||||
| 		// The maximum length is 16. | ||||
| 		var lenBuf [1]byte | ||||
| 		_, err = io.ReadFull(r, lenBuf[:]) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		maxLen := 16 | ||||
| 		ivLen := int(lenBuf[0]) | ||||
| 		if ivLen > maxLen { | ||||
| 			ivLen = maxLen | ||||
| 		} | ||||
| 		ivBuf := make([]byte, ivLen) | ||||
| 		// For now we simply discard the IV | ||||
| 		_, err = io.ReadFull(r, ivBuf) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		return nil, nil | ||||
| 	default: | ||||
| 		return nil, errors.UnsupportedError("unknown S2K GNU protection mode: " + strconv.Itoa(int(gnuExtType))) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Parse reads a binary specification for a string-to-key transformation from r | ||||
| // and returns a function which performs that transform. | ||||
| func Parse(r io.Reader) (f func(out, in []byte), err error) { | ||||
| 	var buf [9]byte | ||||
|  | ||||
| 	_, err = io.ReadFull(r, buf[:2]) | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// GNU Extensions; handle them before we try to look for a hash, which won't | ||||
| 	// be needed in most cases anyway. | ||||
| 	if buf[0] == 101 { | ||||
| 		return parseGNUExtensions(r) | ||||
| 	} | ||||
|  | ||||
| 	hash, ok := HashIdToHash(buf[1]) | ||||
| 	if !ok { | ||||
| 		return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) | ||||
| 	} | ||||
| 	if !hash.Available() { | ||||
| 		return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) | ||||
| 	} | ||||
| 	h := hash.New() | ||||
|  | ||||
| 	switch buf[0] { | ||||
| 	case 0: | ||||
| 		f := func(out, in []byte) { | ||||
| 			Simple(out, h, in) | ||||
| 		} | ||||
| 		return f, nil | ||||
| 	case 1: | ||||
| 		_, err = io.ReadFull(r, buf[:8]) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		f := func(out, in []byte) { | ||||
| 			Salted(out, h, in, buf[:8]) | ||||
| 		} | ||||
| 		return f, nil | ||||
| 	case 3: | ||||
| 		_, err = io.ReadFull(r, buf[:9]) | ||||
| 		if err != nil { | ||||
| 			return | ||||
| 		} | ||||
| 		count := decodeCount(buf[8]) | ||||
| 		f := func(out, in []byte) { | ||||
| 			Iterated(out, h, in, buf[:8], count) | ||||
| 		} | ||||
| 		return f, 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 Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { | ||||
| 	var buf [11]byte | ||||
| 	buf[0] = 3 /* iterated and salted */ | ||||
| 	buf[1], _ = HashToHashId(c.hash()) | ||||
| 	salt := buf[2:10] | ||||
| 	if _, err := io.ReadFull(rand, salt); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	encodedCount := c.encodedCount() | ||||
| 	count := decodeCount(encodedCount) | ||||
| 	buf[10] = encodedCount | ||||
| 	if _, err := w.Write(buf[:]); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	Iterated(key, c.hash().New(), passphrase, salt, count) | ||||
| 	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 HashIdToHash(id byte) (h crypto.Hash, ok bool) { | ||||
| 	for _, m := range hashToHashIdMapping { | ||||
| 		if m.id == id { | ||||
| 			return m.hash, true | ||||
| 		} | ||||
| 	} | ||||
| 	return 0, false | ||||
| } | ||||
|  | ||||
| // HashIdToString returns the name of the hash function corresponding to the | ||||
| // given OpenPGP hash id, or panics if id is unknown. | ||||
| func HashIdToString(id byte) (name string, ok bool) { | ||||
| 	for _, m := range hashToHashIdMapping { | ||||
| 		if m.id == id { | ||||
| 			return m.name, true | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return "", false | ||||
| } | ||||
|  | ||||
| // HashIdToHash returns an OpenPGP hash id which corresponds the given Hash. | ||||
| func HashToHashId(h crypto.Hash) (id byte, ok bool) { | ||||
| 	for _, m := range hashToHashIdMapping { | ||||
| 		if m.hash == h { | ||||
| 			return m.id, true | ||||
| 		} | ||||
| 	} | ||||
| 	return 0, false | ||||
| } | ||||
		Reference in New Issue
	
	Block a user