Skip to content

Commit 244eb1c

Browse files
committed
fix(clearsign): Enforce acceptable hash functions in clearsign
1 parent a994e32 commit 244eb1c

File tree

1 file changed

+51
-4
lines changed

1 file changed

+51
-4
lines changed

openpgp/clearsign/clearsign.go

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ func Decode(data []byte) (b *Block, rest []byte) {
206206
type dashEscaper struct {
207207
buffered *bufio.Writer
208208
hashers []hash.Hash // one per key in privateKeys
209-
hashType crypto.Hash
209+
hashTypes []crypto.Hash
210210
toHash io.Writer // writes to all the hashes in hashers
211211
salts [][]byte // salts for the signatures if v6
212212
armorHeader map[string]string // Armor headers
@@ -328,7 +328,7 @@ func (d *dashEscaper) Close() (err error) {
328328
sig.Version = k.Version
329329
sig.SigType = packet.SigTypeText
330330
sig.PubKeyAlgo = k.PubKeyAlgo
331-
sig.Hash = d.hashType
331+
sig.Hash = d.hashTypes[i]
332332
sig.CreationTime = t
333333
sig.IssuerKeyId = &k.KeyId
334334
sig.IssuerFingerprint = k.Fingerprint
@@ -398,11 +398,22 @@ func EncodeMultiWithHeader(w io.Writer, privateKeys []*packet.PrivateKey, config
398398
if !hashType.Available() {
399399
return nil, errors.UnsupportedError("unsupported hash type: " + strconv.Itoa(int(hashType)))
400400
}
401+
401402
var hashers []hash.Hash
403+
var hashTypes []crypto.Hash
402404
var ws []io.Writer
403405
var salts [][]byte
404406
for _, sk := range privateKeys {
405-
h := hashType.New()
407+
acceptedHashes := acceptableHashesToWrite(&sk.PublicKey)
408+
// acceptedHashes contains at least one hash
409+
selectedHashType := acceptedHashes[0]
410+
for _, acceptedHash := range acceptedHashes {
411+
if hashType == acceptedHash {
412+
selectedHashType = hashType
413+
break
414+
}
415+
}
416+
h := selectedHashType.New()
406417
if sk.Version == 6 {
407418
// generate salt
408419
var salt []byte
@@ -416,6 +427,7 @@ func EncodeMultiWithHeader(w io.Writer, privateKeys []*packet.PrivateKey, config
416427
salts = append(salts, salt)
417428
}
418429
hashers = append(hashers, h)
430+
hashTypes = append(hashTypes, selectedHashType)
419431
ws = append(ws, h)
420432
}
421433
toHash := io.MultiWriter(ws...)
@@ -446,7 +458,7 @@ func EncodeMultiWithHeader(w io.Writer, privateKeys []*packet.PrivateKey, config
446458
plaintext = &dashEscaper{
447459
buffered: buffered,
448460
hashers: hashers,
449-
hashType: hashType,
461+
hashTypes: hashTypes,
450462
toHash: toHash,
451463
salts: salts,
452464
armorHeader: headers,
@@ -489,3 +501,38 @@ func nameOfHash(h crypto.Hash) string {
489501
}
490502
return ""
491503
}
504+
505+
func acceptableHashesToWrite(singingKey *packet.PublicKey) []crypto.Hash {
506+
switch singingKey.PubKeyAlgo {
507+
case packet.PubKeyAlgoEd448:
508+
return []crypto.Hash{
509+
crypto.SHA512,
510+
crypto.SHA3_512,
511+
}
512+
case packet.PubKeyAlgoECDSA, packet.PubKeyAlgoEdDSA:
513+
if curve, err := singingKey.Curve(); err == nil {
514+
if curve == packet.Curve448 ||
515+
curve == packet.CurveNistP521 ||
516+
curve == packet.CurveBrainpoolP512 {
517+
return []crypto.Hash{
518+
crypto.SHA512,
519+
crypto.SHA3_512,
520+
}
521+
} else if curve == packet.CurveBrainpoolP384 ||
522+
curve == packet.CurveNistP384 {
523+
return []crypto.Hash{
524+
crypto.SHA384,
525+
crypto.SHA512,
526+
crypto.SHA3_512,
527+
}
528+
}
529+
}
530+
}
531+
return []crypto.Hash{
532+
crypto.SHA256,
533+
crypto.SHA384,
534+
crypto.SHA512,
535+
crypto.SHA3_256,
536+
crypto.SHA3_512,
537+
}
538+
}

0 commit comments

Comments
 (0)