github.com/pion/dtls/v2@v2.2.12/pkg/crypto/signaturehash/signaturehash.go (about) 1 // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly> 2 // SPDX-License-Identifier: MIT 3 4 // Package signaturehash provides the SignatureHashAlgorithm as defined in TLS 1.2 5 package signaturehash 6 7 import ( 8 "crypto" 9 "crypto/ecdsa" 10 "crypto/ed25519" 11 "crypto/rsa" 12 "crypto/tls" 13 "fmt" 14 15 "github.com/pion/dtls/v2/pkg/crypto/hash" 16 "github.com/pion/dtls/v2/pkg/crypto/signature" 17 ) 18 19 // Algorithm is a signature/hash algorithm pairs which may be used in 20 // digital signatures. 21 // 22 // https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 23 type Algorithm struct { 24 Hash hash.Algorithm 25 Signature signature.Algorithm 26 } 27 28 // Algorithms are all the know SignatureHash Algorithms 29 func Algorithms() []Algorithm { 30 return []Algorithm{ 31 {hash.SHA256, signature.ECDSA}, 32 {hash.SHA384, signature.ECDSA}, 33 {hash.SHA512, signature.ECDSA}, 34 {hash.SHA256, signature.RSA}, 35 {hash.SHA384, signature.RSA}, 36 {hash.SHA512, signature.RSA}, 37 {hash.Ed25519, signature.Ed25519}, 38 } 39 } 40 41 // SelectSignatureScheme returns most preferred and compatible scheme. 42 func SelectSignatureScheme(sigs []Algorithm, privateKey crypto.PrivateKey) (Algorithm, error) { 43 for _, ss := range sigs { 44 if ss.isCompatible(privateKey) { 45 return ss, nil 46 } 47 } 48 return Algorithm{}, errNoAvailableSignatureSchemes 49 } 50 51 // isCompatible checks that given private key is compatible with the signature scheme. 52 func (a *Algorithm) isCompatible(privateKey crypto.PrivateKey) bool { 53 switch privateKey.(type) { 54 case ed25519.PrivateKey: 55 return a.Signature == signature.Ed25519 56 case *ecdsa.PrivateKey: 57 return a.Signature == signature.ECDSA 58 case *rsa.PrivateKey: 59 return a.Signature == signature.RSA 60 default: 61 return false 62 } 63 } 64 65 // ParseSignatureSchemes translates []tls.SignatureScheme to []signatureHashAlgorithm. 66 // It returns default signature scheme list if no SignatureScheme is passed. 67 func ParseSignatureSchemes(sigs []tls.SignatureScheme, insecureHashes bool) ([]Algorithm, error) { 68 if len(sigs) == 0 { 69 return Algorithms(), nil 70 } 71 out := []Algorithm{} 72 for _, ss := range sigs { 73 sig := signature.Algorithm(ss & 0xFF) 74 if _, ok := signature.Algorithms()[sig]; !ok { 75 return nil, 76 fmt.Errorf("SignatureScheme %04x: %w", ss, errInvalidSignatureAlgorithm) 77 } 78 h := hash.Algorithm(ss >> 8) 79 if _, ok := hash.Algorithms()[h]; !ok || (ok && h == hash.None) { 80 return nil, fmt.Errorf("SignatureScheme %04x: %w", ss, errInvalidHashAlgorithm) 81 } 82 if h.Insecure() && !insecureHashes { 83 continue 84 } 85 out = append(out, Algorithm{ 86 Hash: h, 87 Signature: sig, 88 }) 89 } 90 91 if len(out) == 0 { 92 return nil, errNoAvailableSignatureSchemes 93 } 94 95 return out, nil 96 }