mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 05:40:50 +01:00
feat: implement func getLeafCertificate so that Certificate.Leaf can be nil. This behavior was changed with Go 1.23, according to https://go-review.googlesource.com/c/go/+/585856, also provieded tests
This commit is contained in:
parent
faffc025cb
commit
1970b24151
3 changed files with 94 additions and 6 deletions
30
msg.go
30
msg.go
|
@ -367,23 +367,45 @@ func (m *Msg) SignWithTLSCertificate(keyPairTlS *tls.Certificate) error {
|
|||
return fmt.Errorf("failed to parse intermediate certificate: %w", err)
|
||||
}
|
||||
|
||||
leafCertificate, err := getLeafCertificate(keyPairTlS)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get leaf certificate: %w", err)
|
||||
}
|
||||
|
||||
switch keyPairTlS.PrivateKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
if intermediateCertificate == nil {
|
||||
return m.SignWithSMimeRSA(keyPairTlS.PrivateKey.(*rsa.PrivateKey), keyPairTlS.Leaf, nil)
|
||||
return m.SignWithSMimeRSA(keyPairTlS.PrivateKey.(*rsa.PrivateKey), leafCertificate, nil)
|
||||
}
|
||||
return m.SignWithSMimeRSA(keyPairTlS.PrivateKey.(*rsa.PrivateKey), keyPairTlS.Leaf, intermediateCertificate)
|
||||
return m.SignWithSMimeRSA(keyPairTlS.PrivateKey.(*rsa.PrivateKey), leafCertificate, intermediateCertificate)
|
||||
|
||||
case *ecdsa.PrivateKey:
|
||||
if intermediateCertificate == nil {
|
||||
return m.SignWithSMimeECDSA(keyPairTlS.PrivateKey.(*ecdsa.PrivateKey), keyPairTlS.Leaf, nil)
|
||||
return m.SignWithSMimeECDSA(keyPairTlS.PrivateKey.(*ecdsa.PrivateKey), leafCertificate, nil)
|
||||
}
|
||||
return m.SignWithSMimeECDSA(keyPairTlS.PrivateKey.(*ecdsa.PrivateKey), keyPairTlS.Leaf, intermediateCertificate)
|
||||
return m.SignWithSMimeECDSA(keyPairTlS.PrivateKey.(*ecdsa.PrivateKey), leafCertificate, intermediateCertificate)
|
||||
default:
|
||||
return fmt.Errorf("unsupported private key type: %T", keyPairTlS.PrivateKey)
|
||||
}
|
||||
}
|
||||
|
||||
// getLeafCertificate returns the leaf certificate from a tls.Certificate.
|
||||
// PLEASE NOTE: Before Go 1.23 Certificate.Leaf was left nil, and the parsed certificate was
|
||||
// discarded. This behavior can be re-enabled by setting "x509keypairleaf=0"
|
||||
// in the GODEBUG environment variable.
|
||||
func getLeafCertificate(keyPairTlS *tls.Certificate) (*x509.Certificate, error) {
|
||||
if keyPairTlS.Leaf != nil {
|
||||
return keyPairTlS.Leaf, nil
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(keyPairTlS.Certificate[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
// This method allows you to specify a character set for the email message. The charset is
|
||||
// important for ensuring that the content of the message is correctly interpreted by
|
||||
// mail clients. Common charset values include UTF-8, ISO-8859-1, and others. If a charset
|
||||
|
|
57
msg_test.go
57
msg_test.go
|
@ -3379,6 +3379,47 @@ func TestSignWithSMime_ValidECDSAKeyPair(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestSignWithTLSCertificate tests SignWithTLSCertificate with given *tls.Certificate
|
||||
func TestSignWithTLSCertificate(t *testing.T) {
|
||||
keyPairTLS, err := getDummyKeyPairTLS()
|
||||
if err != nil {
|
||||
t.Errorf("failed to laod dummy crypto material. Cause: %v", err)
|
||||
}
|
||||
m := NewMsg()
|
||||
if err := m.SignWithTLSCertificate(keyPairTLS); err != nil {
|
||||
t.Errorf("failed to set sMime. Cause: %v", err)
|
||||
}
|
||||
if m.sMime.privateKey.ecdsa == nil {
|
||||
t.Errorf("SignWithTLSCertificate() - no private key is given")
|
||||
}
|
||||
if m.sMime.certificate == nil {
|
||||
t.Errorf("SignWithTLSCertificate() - no certificate is given")
|
||||
}
|
||||
}
|
||||
|
||||
// TestSignWithTLSCertificate tests SignWithTLSCertificate with given *tls.Certificate and nil leaf certificate
|
||||
// PLEASE NOTE: Before Go 1.23 Certificate.Leaf was left nil, and the parsed certificate was
|
||||
// discarded. This behavior can be re-enabled by setting "x509keypairleaf=0"
|
||||
// in the GODEBUG environment variable.
|
||||
func TestSignWithTLSCertificate_WithKeyPairLeafNil(t *testing.T) {
|
||||
t.Setenv("GODEBUG", "x509keypairleaf=0")
|
||||
|
||||
keyPairTLS, err := getDummyKeyPairTLS()
|
||||
if err != nil {
|
||||
t.Errorf("failed to laod dummy crypto material. Cause: %v", err)
|
||||
}
|
||||
m := NewMsg()
|
||||
if err := m.SignWithTLSCertificate(keyPairTLS); err != nil {
|
||||
t.Errorf("failed to set sMime. Cause: %v", err)
|
||||
}
|
||||
if m.sMime.privateKey.ecdsa == nil {
|
||||
t.Errorf("SignWithTLSCertificate() - no private key is given")
|
||||
}
|
||||
if m.sMime.certificate == nil {
|
||||
t.Errorf("SignWithTLSCertificate() - no certificate is given")
|
||||
}
|
||||
}
|
||||
|
||||
// TestSignWithSMime_InvalidPrivateKey tests WithSMimeSinging with given invalid private key
|
||||
func TestSignWithSMime_InvalidPrivateKey(t *testing.T) {
|
||||
m := NewMsg()
|
||||
|
@ -3511,3 +3552,19 @@ func TestMsg_signMessage(t *testing.T) {
|
|||
t.Errorf("createSignaturePart() method failed. Expected content should not be equal: %s, got: %s", body, signaturePart.GetEncoding())
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetLeafCertificate tests the Msg.getLeafCertificate method
|
||||
func TestGetLeafCertificate(t *testing.T) {
|
||||
keyPairTLS, err := getDummyKeyPairTLS()
|
||||
if err != nil {
|
||||
t.Errorf("failed to laod dummy crypto material. Cause: %v", err)
|
||||
}
|
||||
|
||||
leafCertificate, err := getLeafCertificate(keyPairTLS)
|
||||
if err != nil {
|
||||
t.Errorf("failed to get leaf certificate. Cause: %v", err)
|
||||
}
|
||||
if leafCertificate == nil {
|
||||
t.Errorf("failed to get leaf certificate")
|
||||
}
|
||||
}
|
||||
|
|
13
util_test.go
13
util_test.go
|
@ -19,7 +19,7 @@ const (
|
|||
keyECDSAFilePath = "dummy-child-key-ecdsa.pem"
|
||||
)
|
||||
|
||||
// getDummyRSACryptoMaterial loads a certificate (RSA) and the associated private key (ECDSA) form local disk for testing purposes
|
||||
// getDummyRSACryptoMaterial loads a certificate (RSA), the associated private key and certificate (RSA) is loaded from local disk for testing purposes
|
||||
func getDummyRSACryptoMaterial() (*rsa.PrivateKey, *x509.Certificate, *x509.Certificate, error) {
|
||||
keyPair, err := tls.LoadX509KeyPair(certRSAFilePath, keyRSAFilePath)
|
||||
if err != nil {
|
||||
|
@ -41,7 +41,7 @@ func getDummyRSACryptoMaterial() (*rsa.PrivateKey, *x509.Certificate, *x509.Cert
|
|||
return privateKey, certificate, intermediateCertificate, nil
|
||||
}
|
||||
|
||||
// getDummyECDSACryptoMaterial loads a certificate (ECDSA) and the associated private key (ECDSA) form local disk for testing purposes
|
||||
// getDummyECDSACryptoMaterial loads a certificate (ECDSA), the associated private key and certificate (ECDSA) is loaded from local disk for testing purposes
|
||||
func getDummyECDSACryptoMaterial() (*ecdsa.PrivateKey, *x509.Certificate, *x509.Certificate, error) {
|
||||
keyPair, err := tls.LoadX509KeyPair(certECDSAFilePath, keyECDSAFilePath)
|
||||
if err != nil {
|
||||
|
@ -62,3 +62,12 @@ func getDummyECDSACryptoMaterial() (*ecdsa.PrivateKey, *x509.Certificate, *x509.
|
|||
|
||||
return privateKey, certificate, intermediateCertificate, nil
|
||||
}
|
||||
|
||||
// getDummyKeyPairTLS loads a certificate (ECDSA) as *tls.Certificate, the associated private key and certificate (ECDSA) is loaded from local disk for testing purposes
|
||||
func getDummyKeyPairTLS() (*tls.Certificate, error) {
|
||||
keyPair, err := tls.LoadX509KeyPair(certECDSAFilePath, keyECDSAFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &keyPair, err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue