فهرست منبع

go.crypto/openpgp: test that hashes are compiled in before using them.

Previously, if Encrypt decided to use a hash function that wasn't
compiled in then it would panic.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/12055043
Adam Langley 12 سال پیش
والد
کامیت
f23aef828f
2فایلهای تغییر یافته به همراه43 افزوده شده و 14 حذف شده
  1. 20 7
      openpgp/s2k/s2k.go
  2. 23 7
      openpgp/write.go

+ 20 - 7
openpgp/s2k/s2k.go

@@ -151,14 +151,15 @@ func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte) error
 var hashToHashIdMapping = []struct {
 	id   byte
 	hash crypto.Hash
+	name string
 }{
-	{1, crypto.MD5},
-	{2, crypto.SHA1},
-	{3, crypto.RIPEMD160},
-	{8, crypto.SHA256},
-	{9, crypto.SHA384},
-	{10, crypto.SHA512},
-	{11, crypto.SHA224},
+	{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
@@ -172,6 +173,18 @@ func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
 	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 {

+ 23 - 7
openpgp/write.go

@@ -224,16 +224,32 @@ func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHint
 		}
 	}
 
-	hashFunc := candidateHashes[0]
-	// If the hash specified by config is a candidate, we'll use that.
-	configuredHash := config.Hash()
-	for _, h := range candidateHashes {
-		if h == uint8(configuredHash) {
-			hashFunc = h
+	var hash crypto.Hash
+	for _, hashId := range candidateHashes {
+		if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() {
+			hash = h
 			break
 		}
 	}
-	hash, _ := s2k.HashIdToHash(hashFunc)
+
+	// If the hash specified by config is a candidate, we'll use that.
+	if configuredHash := config.Hash(); configuredHash.Available() {
+		for _, hashId := range candidateHashes {
+			if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash {
+				hash = h
+				break
+			}
+		}
+	}
+
+	if hash == 0 {
+		hashId := candidateHashes[0]
+		name, ok := s2k.HashIdToString(hashId)
+		if !ok {
+			name = "#" + strconv.Itoa(int(hashId))
+		}
+		return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
+	}
 
 	symKey := make([]byte, cipher.KeySize())
 	if _, err := io.ReadFull(config.Random(), symKey); err != nil {