mirror of
https://github.com/wneessen/go-mail.git
synced 2024-11-22 13:50:49 +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)
|
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) {
|
switch keyPairTlS.PrivateKey.(type) {
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
if intermediateCertificate == nil {
|
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:
|
case *ecdsa.PrivateKey:
|
||||||
if intermediateCertificate == nil {
|
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:
|
default:
|
||||||
return fmt.Errorf("unsupported private key type: %T", keyPairTlS.PrivateKey)
|
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
|
// 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
|
// 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
|
// 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
|
// TestSignWithSMime_InvalidPrivateKey tests WithSMimeSinging with given invalid private key
|
||||||
func TestSignWithSMime_InvalidPrivateKey(t *testing.T) {
|
func TestSignWithSMime_InvalidPrivateKey(t *testing.T) {
|
||||||
m := NewMsg()
|
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())
|
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"
|
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) {
|
func getDummyRSACryptoMaterial() (*rsa.PrivateKey, *x509.Certificate, *x509.Certificate, error) {
|
||||||
keyPair, err := tls.LoadX509KeyPair(certRSAFilePath, keyRSAFilePath)
|
keyPair, err := tls.LoadX509KeyPair(certRSAFilePath, keyRSAFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -41,7 +41,7 @@ func getDummyRSACryptoMaterial() (*rsa.PrivateKey, *x509.Certificate, *x509.Cert
|
||||||
return privateKey, certificate, intermediateCertificate, nil
|
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) {
|
func getDummyECDSACryptoMaterial() (*ecdsa.PrivateKey, *x509.Certificate, *x509.Certificate, error) {
|
||||||
keyPair, err := tls.LoadX509KeyPair(certECDSAFilePath, keyECDSAFilePath)
|
keyPair, err := tls.LoadX509KeyPair(certECDSAFilePath, keyECDSAFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -62,3 +62,12 @@ func getDummyECDSACryptoMaterial() (*ecdsa.PrivateKey, *x509.Certificate, *x509.
|
||||||
|
|
||||||
return privateKey, certificate, intermediateCertificate, nil
|
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