From e00e40e3283d48b7302a193afe0fd40aa0be0bcd Mon Sep 17 00:00:00 2001 From: tian Date: Mon, 1 Mar 2021 10:10:52 +0800 Subject: [PATCH] add comment --- .github/workflows/golangci-lint.yml | 2 +- .github/workflows/static_check.yml | 4 +- security/cipher.go | 5 +- string/string.go | 8 +++ tlsutil/tls.go | 53 ++++++++--------- tlsutil/tls_test.go | 89 ++++++++++++++++++++++++++--- 6 files changed, 122 insertions(+), 39 deletions(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 9640ae5..2d43d8b 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -16,4 +16,4 @@ jobs: uses: golangci/golangci-lint-action@v2 with: version: v1.29 - args: --skip-dirs=examples --out-format=colored-line-number --skip-files=.*_test.go$ \ No newline at end of file + args: --skip-dirs=examples,tls --out-format=colored-line-number --skip-files=.*_test.go$ \ No newline at end of file diff --git a/.github/workflows/static_check.yml b/.github/workflows/static_check.yml index 4a380b6..dc2d3ec 100644 --- a/.github/workflows/static_check.yml +++ b/.github/workflows/static_check.yml @@ -5,10 +5,10 @@ jobs: name: Merge check runs-on: ubuntu-latest steps: - - name: Set up Go 1.13 + - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.13 + go-version: 1.16 id: go - name: UT uses: actions/checkout@v1 diff --git a/security/cipher.go b/security/cipher.go index 85acd36..1586a96 100644 --- a/security/cipher.go +++ b/security/cipher.go @@ -13,10 +13,13 @@ * limitations under the License. */ -// Package security is deprecated plz use github.com/go-chassis/cari/security +// Package security is deprecated +// Deprecated: use github.com/go-chassis/cari/security package security //Cipher interface declares two function for encryption and decryption +// +// Deprecated: use github.com/go-chassis/cari/security type Cipher interface { Encrypt(src string) (string, error) diff --git a/string/string.go b/string/string.go index c63049c..c29b4f4 100755 --- a/string/string.go +++ b/string/string.go @@ -7,6 +7,7 @@ import ( ) // Deprecated StringInSlice convert string to bool +// Deprecated: use github.com/go-chassis/foundation/stringutil func StringInSlice(a string, list []string) bool { for _, b := range list { if b == a { @@ -17,6 +18,7 @@ func StringInSlice(a string, list []string) bool { } // Deprecated Str2bytes convert string to array of byte +// Deprecated: use github.com/go-chassis/foundation/stringutil func Str2bytes(s string) []byte { x := (*[2]uintptr)(unsafe.Pointer(&s)) h := [3]uintptr{x[0], x[1], x[1]} @@ -24,11 +26,13 @@ func Str2bytes(s string) []byte { } // Deprecated Bytes2str convert array of byte to string +// Deprecated: use github.com/go-chassis/foundation/stringutil func Bytes2str(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } // Deprecated SplitToTwo split the string +// Deprecated: use github.com/go-chassis/foundation/stringutil func SplitToTwo(s, sep string) (string, string) { index := strings.Index(s, sep) if index < 0 { @@ -38,6 +42,7 @@ func SplitToTwo(s, sep string) (string, string) { } // Deprecated SplitFirstSep split the string +// Deprecated: use github.com/go-chassis/foundation/stringutil func SplitFirstSep(s, sep string) string { index := strings.Index(s, sep) if index < 0 { @@ -47,6 +52,7 @@ func SplitFirstSep(s, sep string) string { } // Deprecated MinInt check the minimum value of two integers +// Deprecated: use github.com/go-chassis/foundation/stringutil func MinInt(x, y int) int { if x <= y { return x @@ -57,6 +63,7 @@ func MinInt(x, y int) int { // Deprecated ClearStringMemory clear string memory, for very sensitive security related data //you should clear it in memory after use +// Deprecated: use github.com/go-chassis/foundation/stringutil func ClearStringMemory(src *string) { p := (*struct { ptr uintptr @@ -74,6 +81,7 @@ func ClearStringMemory(src *string) { // Deprecated ClearByteMemory clear byte memory, for very sensitive security related data //you should clear it in memory after use +// Deprecated: use github.com/go-chassis/foundation/stringutil func ClearByteMemory(src []byte) { len := MinInt(len(src), 32) for idx := 0; idx < len; idx = idx + 1 { diff --git a/tlsutil/tls.go b/tlsutil/tls.go index 10c13f3..9c6e36d 100644 --- a/tlsutil/tls.go +++ b/tlsutil/tls.go @@ -4,7 +4,6 @@ import ( "crypto/tls" "crypto/x509" "encoding/pem" - "errors" "fmt" "io/ioutil" ) @@ -24,50 +23,48 @@ func GetX509CACertPool(caCertFile string) (*x509.CertPool, error) { } //LoadTLSCertificate is a function used to load a certificate -func LoadTLSCertificate(certFile, keyFile, passphase string, decrypt Decrypt) ([]tls.Certificate, error) { +// RFC 1423 is insecure, password and decrypt is not required +func LoadTLSCertificate(certFile, keyFile, password string, decrypt Decrypt) ([]tls.Certificate, error) { certContent, err := ioutil.ReadFile(certFile) if err != nil { - errorMsg := "read cert file" + certFile + "failed." - return nil, errors.New(errorMsg) + return nil, err } keyContent, err := ioutil.ReadFile(keyFile) if err != nil { - errorMsg := "read key file" + keyFile + "failed." - return nil, errors.New(errorMsg) + return nil, err } keyBlock, _ := pem.Decode(keyContent) if keyBlock == nil { - errorMsg := "decode key file " + keyFile + " failed" - return nil, errors.New(errorMsg) - } - - plainpass, err := decrypt(passphase) - if err != nil { - return nil, err + return nil, fmt.Errorf("decrypt key file "+keyFile+" failed: %w", err) } - - if x509.IsEncryptedPEMBlock(keyBlock) { - keyData, err := x509.DecryptPEMBlock(keyBlock, []byte(plainpass)) - if err != nil { - errorMsg := "decrypt key file " + keyFile + " failed." - return nil, errors.New(errorMsg) + if password != "" { + var plainpass string + if decrypt != nil { + plainpass, err = decrypt(password) + if err != nil { + return nil, err + } } + if x509.IsEncryptedPEMBlock(keyBlock) { + keyData, err := x509.DecryptPEMBlock(keyBlock, []byte(plainpass)) + if err != nil { + return nil, fmt.Errorf("decrypt key file "+keyFile+" failed. err: %w", err) + } - // 解密成功,重新编码为无加密的PEM格式文件 - plainKeyBlock := &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: keyData, - } + // 解密成功,重新编码为无加密的PEM格式文件 + keyBlock = &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: keyData, + } - keyContent = pem.EncodeToMemory(plainKeyBlock) + } } - + keyContent = pem.EncodeToMemory(keyBlock) cert, err := tls.X509KeyPair(certContent, keyContent) if err != nil { - errorMsg := "load X509 key pair from cert file " + certFile + " with key file " + keyFile + " failed." - return nil, errors.New(errorMsg) + return nil, fmt.Errorf("load cert failed:%w", err) } var certs []tls.Certificate diff --git a/tlsutil/tls_test.go b/tlsutil/tls_test.go index 8456b47..b92a4bc 100644 --- a/tlsutil/tls_test.go +++ b/tlsutil/tls_test.go @@ -1,16 +1,91 @@ package tlsutil_test import ( - "testing" - "github.com/go-chassis/foundation/tlsutil" "github.com/stretchr/testify/assert" + "io" + "os" + "path/filepath" + "testing" ) -func TestLoadTLSCertificateFileNotExist(t *testing.T) { - tlsCert, err := tlsutil.LoadTLSCertificate("abc.txt", "abc.txt", "fakepassphase", func(src string) (s string, err error) { - return "fakepassphase", nil +var rsaCertPEM = `-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJANq58YD5coE2MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX +aWRnaXRzIFB0eSBMdGQwHhcNMjEwMzAxMDQzMDAzWhcNMjEwMzMxMDQzMDAzWjBF +MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 +ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAySqpnHOj42/LcGguAIj/ZYDb96ccdAjhuSgScWnOiF2obMVuBxAkaYRa +IcBvphv2N6dCs/AiOzwhyi7d4X82NQ5ftMBjzEHZaRCXQtS2JLHmNi4iuA5GHN0Z +EjinwXeT8ZsJP1wIHtnqF7D8PZdhS8V/SYimx4ejYG3J/+AIDU4YYyb14/3jjVzy +X4UnMy1igPbPtx6CbjNxUaVCmy4RUbrLwYdY1k+QbGguhfk4YERiV0P5W2pZzVqn +9rjvrEdFn0lgyRjNqvsRVneEcd7Y+OqgXvB69wiFrEeoEq/qbsDYQNFEm30Bx0wi +cbqMMYsuZTDRcXPz8gveyjNw0E2zDQIDAQABo1AwTjAdBgNVHQ4EFgQUGL3vXIio +1B7uvqGmzTXNaDZ/u7YwHwYDVR0jBBgwFoAUGL3vXIio1B7uvqGmzTXNaDZ/u7Yw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAAjBY2o/Jyh6MLo4DletW +PyS/8f46HMWo8kPTeZ77oh7iJNnpzbI4pgJ5yVTR4RqAj25ibSE0UuOrRRAgEWzT +5Y4C0r+XZghxyt9XET2RSC+BJxm4rC+bvsIIE0fNgX21o5hhSfSBpIl5NZOdVIbw +3VkvFi2hOtViVRxkk28SdvymDgDYU6djixf3qGYlvE+YSMUfDNFflxLWNCRXOyK0 +9YLSOLZyaX8VkENVSZb3OmSDQoCTpnmrVEKHp4OcjbqfKB2o1bvREJ4CRBHmGMgd +pkM+Xeu/qofei+ekZsGLIaceM+cSV4w42vaHdwC5HkTpV4fIaGHEwsI8FD7aWKrU +eA== +-----END CERTIFICATE----- +` + +var rsaKeyPEM = []byte(`-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEAySqpnHOj42/LcGguAIj/ZYDb96ccdAjhuSgScWnOiF2obMVu +BxAkaYRaIcBvphv2N6dCs/AiOzwhyi7d4X82NQ5ftMBjzEHZaRCXQtS2JLHmNi4i +uA5GHN0ZEjinwXeT8ZsJP1wIHtnqF7D8PZdhS8V/SYimx4ejYG3J/+AIDU4YYyb1 +4/3jjVzyX4UnMy1igPbPtx6CbjNxUaVCmy4RUbrLwYdY1k+QbGguhfk4YERiV0P5 +W2pZzVqn9rjvrEdFn0lgyRjNqvsRVneEcd7Y+OqgXvB69wiFrEeoEq/qbsDYQNFE +m30Bx0wicbqMMYsuZTDRcXPz8gveyjNw0E2zDQIDAQABAoIBAQC3Yoz8cu8UhvWO +o2pMUpeAkNf2DAGERhSAFme5vBrrdXX0soZ7KdwH1P/VhPhDFXp/gZrtLhwGo+qp +xc+/oZhpBZF51Wkk62KmxNkfs4nYKdUTzzsXTuvbpDMWyU8krz3PIuZrPBqrBTzC +HDXWcAniaUiAYHKpspzdaziaakDs3obT5grtg6UNB/s/mPBrvHH9ftmolOBOxLhH +rvNxoCyP/tAB8AW1AJ6g3TSK1SANPgqzROe0X0ZHzW1T6/bZAC3OPA2PdhhnkdjN +zH2OLu3cU1Ybgtku/Ce7/AO1yKX2qdTn3v9iO0xO8swqAetepAqk8RKhfx0w61yc +Nugyya6BAoGBAOW5IzpB9USbTTzDuvVBBTS1e4OJRmkkR9KtZTfLNjVY7aY1mhrl +/Fi3JX+qPT9OsLyiRq9/UKuNcVeBYiVamBV4eBtmYqivOnnMe6P8V20RCWmhgZqw +2nyQfgIVFgSnTOlVdg5YD+GXptnfl/pqO2f2Pl4vQdM/nemyIk/HodgPAoGBAOAt +UZ8HTTzVnzyjPq1VGe2mQBmwC1fMkpmD2/d56TIDT4vVbAsu9ge106mdB52ZvlNc +nkl6KvsBcCXyJT6S/bpOINFViFAvigRpmez1rmFMqBf2OvTnELtlZ3kTn8/X1uIX +bFIX2G1XAKAQ6MBCYLzvCLMTf+EkebENA4kQr0cjAoGBAJrdfY8nqgYvQBmHxgDS +bYUEF5ksMQhuifDQLh035HqAUe2r0xDxHHZeOWxgQtvr25+/MjHbfXG5b8BTG+wc +r8xBo46tLjOTtbMok+2QDwwa4SKR24KCWTiCXEBhIK/QbTwb/fNbkJE/oB7e6mDJ +vvSt/4uVBiY4i+dgzFrGNSgnAoGBAJ/RbzkSuYu/N/DA6LQl0YBNX7FwggWsAG+V +Q8JglVFkbtdf5dDrP9crV6S6IG3I55kClI4JnI6p7cv/n3HG1UB25oqWkcGowpp2 +tpfqZtFTFxtOHaXu/Uy79FKrHOnOFJHG5SB5g4Af4IA8zdITAGhxeSBBrI9Ts7X3 +cyfKT0tFAoGBAJvS+AZK93SLYvsRdyytevKuYMAqIO+YRBOfZ+NN9+vosGlzbmuj +8zHkQQ8yeMJASbTpEAakz2ybJeN5zNELMKGUrsGVefiW0Z/5skO2toeF1PWtF0G8 +FF2uvhCC6xWFT/PzYycBYMzq6gUus3aJQ+wjFnEflZYj7wGzf4tGzA5I +-----END RSA PRIVATE KEY----- + +`) + +func TestLoadTLSCertificate(t *testing.T) { + td := t.TempDir() + f1, err := os.Create(filepath.Join(td, "key.pem")) + assert.NoError(t, err) + defer f1.Close() + _, err = io.WriteString(f1, string(rsaKeyPEM)) + assert.NoError(t, err) + + f2, err := os.Create(filepath.Join(td, "cert.pem")) + assert.NoError(t, err) + defer f1.Close() + _, err = io.WriteString(f2, rsaCertPEM) + assert.NoError(t, err) + + t.Run("given no file,should failed", func(t *testing.T) { + tlsCert, err := tlsutil.LoadTLSCertificate("abc.txt", "abc.txt", "fakepassphase", func(src string) (s string, err error) { + return "fakepassphase", nil + }) + assert.Nil(t, tlsCert) + assert.Error(t, err) + }) + t.Run("given rsa key pair,should success", func(t *testing.T) { + tlsCert, err := tlsutil.LoadTLSCertificate(f2.Name(), f1.Name(), "", nil) + assert.NotNil(t, tlsCert) + assert.NoError(t, err) }) - assert.Nil(t, tlsCert) - assert.Error(t, err) }