Reject signatures using insecure hash algorithms (#52)

This commit is contained in:
Daniel Huigens 2020-06-25 13:45:59 +02:00 committed by GitHub
parent 3e28b51abb
commit 608bedaaf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 15 deletions

View file

@ -2,6 +2,7 @@ package crypto
import (
"bytes"
"crypto"
"fmt"
"io"
"math"
@ -15,6 +16,13 @@ import (
"github.com/ProtonMail/gopenpgp/v2/internal"
)
var allowedHashes = []crypto.Hash{
crypto.SHA224,
crypto.SHA256,
crypto.SHA384,
crypto.SHA512,
}
// SignatureVerificationError is returned from Decrypt and VerifyDetached
// functions when signature verification fails.
type SignatureVerificationError struct {
@ -40,6 +48,15 @@ func newSignatureFailed() SignatureVerificationError {
}
}
// newSignatureInsecure creates a new SignatureVerificationError, type
// SignatureFailed, with a message describing the signature as insecure.
func newSignatureInsecure() SignatureVerificationError {
return SignatureVerificationError{
constants.SIGNATURE_FAILED,
"Insecure signature",
}
}
// newSignatureNotSigned creates a new SignatureVerificationError, type
// SignatureNotSigned.
func newSignatureNotSigned() SignatureVerificationError {
@ -81,20 +98,21 @@ func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) {
// verifyDetailsSignature verifies signature from message details.
func verifyDetailsSignature(md *openpgp.MessageDetails, verifierKey *KeyRing) error {
if md.IsSigned {
if md.SignedBy == nil || len(verifierKey.entities) == 0 {
return newSignatureNoVerifier()
}
matches := verifierKey.entities.KeysById(md.SignedByKeyId)
if len(matches) > 0 {
if md.SignatureError == nil {
return nil
}
return newSignatureFailed()
}
if !md.IsSigned ||
md.SignedBy == nil ||
len(verifierKey.entities) == 0 ||
len(verifierKey.entities.KeysById(md.SignedByKeyId)) == 0 {
return newSignatureNoVerifier()
}
return newSignatureNoVerifier()
if md.SignatureError != nil {
return newSignatureFailed()
}
if md.Signature == nil ||
md.Signature.Hash < allowedHashes[0] ||
md.Signature.Hash > allowedHashes[len(allowedHashes)-1] {
return newSignatureInsecure()
}
return nil
}
// verifySignature verifies if a signature is valid with the entity list.
@ -111,7 +129,7 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText io.Reader, signa
}
signatureReader := bytes.NewReader(signature)
signer, err := openpgp.CheckDetachedSignature(pubKeyEntries, origText, signatureReader, config)
signer, err := openpgp.CheckDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config)
if err == pgpErrors.ErrSignatureExpired && signer != nil && verifyTime > 0 {
// if verifyTime = 0: time check disabled, everything is okay
@ -126,7 +144,7 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText io.Reader, signa
return newSignatureFailed()
}
signer, err = openpgp.CheckDetachedSignature(pubKeyEntries, origText, signatureReader, config)
signer, err = openpgp.CheckDetachedSignatureAndHash(pubKeyEntries, origText, signatureReader, allowedHashes, config)
if err != nil {
return newSignatureFailed()
}