github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/pgp_warnings.go (about) 1 package libkb 2 3 import ( 4 "bytes" 5 "crypto" 6 "fmt" 7 "io" 8 9 "github.com/keybase/go-crypto/openpgp/armor" 10 11 "github.com/keybase/go-crypto/openpgp" 12 "github.com/keybase/go-crypto/openpgp/errors" 13 "github.com/keybase/go-crypto/openpgp/packet" 14 ) 15 16 func ExtractPGPSignatureHashMethod(keyring openpgp.KeyRing, sig []byte) (crypto.Hash, uint64, error) { 17 var ( 18 rd io.Reader 19 20 p packet.Packet 21 hashFunc crypto.Hash 22 issuerFingerprint []byte 23 issuerKeyID uint64 24 err error 25 ) 26 27 if IsArmored(sig) { 28 armored, err := armor.Decode(bytes.NewReader(sig)) 29 if err != nil { 30 return 0, 0, err 31 } 32 rd = armored.Body 33 } else { 34 rd = bytes.NewReader(sig) 35 } 36 37 packets := packet.NewReader(rd) 38 for { 39 p, err = packets.Next() 40 if err == io.EOF { 41 if hashFunc != 0 { 42 return hashFunc, 0, nil 43 } 44 45 return 0, 0, errors.ErrUnknownIssuer 46 } 47 if err != nil { 48 return 0, 0, err 49 } 50 51 switch sig := p.(type) { 52 case *packet.Signature: 53 if sig.IssuerKeyId == nil { 54 return 0, 0, errors.StructuralError("signature doesn't have an issuer") 55 } 56 issuerKeyID = *sig.IssuerKeyId 57 hashFunc = sig.Hash 58 issuerFingerprint = sig.IssuerFingerprint 59 case *packet.SignatureV3: 60 issuerKeyID = sig.IssuerKeyId 61 hashFunc = sig.Hash 62 default: 63 return 0, 0, errors.StructuralError("non signature packet found") 64 } 65 66 if keyring != nil { 67 keys := keyring.KeysByIdUsage(issuerKeyID, issuerFingerprint, packet.KeyFlagSign) 68 if len(keys) > 0 { 69 return hashFunc, issuerKeyID, nil 70 } 71 } 72 } 73 } 74 75 var HashToName = map[crypto.Hash]string{ 76 crypto.MD4: "MD4", 77 crypto.MD5: "MD5", 78 crypto.SHA1: "SHA1", 79 crypto.SHA224: "SHA2-224", 80 crypto.SHA256: "SHA2-256", 81 crypto.SHA384: "SHA2-384", 82 crypto.SHA512: "SHA2-512", 83 crypto.RIPEMD160: "RIPEMD-160", 84 crypto.SHA3_224: "SHA3-224", 85 crypto.SHA3_256: "SHA3-256", 86 crypto.SHA3_384: "SHA3-384", 87 crypto.SHA3_512: "SHA3-512", 88 crypto.SHA512_224: "SHA2-512/224", 89 crypto.SHA512_256: "SHA2-512/256", 90 crypto.BLAKE2s_256: "BLAKE2s-256", 91 crypto.BLAKE2b_256: "BLAKE2b-256", 92 crypto.BLAKE2b_384: "BLAKE2b-384", 93 crypto.BLAKE2b_512: "BLAKE2b-512", 94 } 95 96 func IsHashSecure(hash crypto.Hash) bool { 97 switch hash { 98 case crypto.SHA224, 99 crypto.SHA256, 100 crypto.SHA384, 101 crypto.SHA512, 102 crypto.SHA3_224, 103 crypto.SHA3_256, 104 crypto.SHA3_384, 105 crypto.SHA3_512, 106 crypto.SHA512_224, 107 crypto.SHA512_256, 108 crypto.BLAKE2s_256, 109 crypto.BLAKE2b_256, 110 crypto.BLAKE2b_384, 111 crypto.BLAKE2b_512: 112 return true 113 default: 114 return false 115 } 116 } 117 118 type HashSecurityWarningType uint8 119 120 const ( 121 HashSecurityWarningUnknown HashSecurityWarningType = iota 122 HashSecurityWarningSignatureHash 123 HashSecurityWarningSignersIdentityHash 124 HashSecurityWarningRecipientsIdentityHash 125 HashSecurityWarningOurIdentityHash 126 ) 127 128 type HashSecurityWarning struct { 129 kind HashSecurityWarningType 130 hash crypto.Hash 131 fingerprint *PGPFingerprint 132 } 133 134 func NewHashSecurityWarning(kind HashSecurityWarningType, hash crypto.Hash, fp *PGPFingerprint) HashSecurityWarning { 135 return HashSecurityWarning{kind: kind, hash: hash, fingerprint: fp} 136 } 137 138 func (h HashSecurityWarning) String() string { 139 switch h.kind { 140 case HashSecurityWarningSignatureHash: 141 return fmt.Sprintf("Message was signed using an insecure hash scheme (%s)", HashToName[h.hash]) 142 case HashSecurityWarningSignersIdentityHash: 143 return fmt.Sprintf("Signer's key %s uses an insecure hash scheme (%s)", h.fingerprint.String(), HashToName[h.hash]) 144 case HashSecurityWarningRecipientsIdentityHash: 145 return fmt.Sprintf("Recipient's key %s uses an insecure hash scheme (%s)", h.fingerprint.String(), HashToName[h.hash]) 146 case HashSecurityWarningOurIdentityHash: 147 return fmt.Sprintf("Our PGP key %s uses an insecure hash scheme (%s)", h.fingerprint.String(), HashToName[h.hash]) 148 default: 149 return fmt.Sprintf("Hash security warning was passed an incorrect kind, got %d", h.kind) 150 } 151 } 152 153 type HashSecurityWarnings []HashSecurityWarning 154 155 func (hs HashSecurityWarnings) Strings() (res []string) { 156 for _, h := range hs { 157 res = append(res, h.String()) 158 } 159 return 160 }