From 9607750b5e9001ab379fa8deab0dadbb6219c66e Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 28 Nov 2022 19:19:18 +0800 Subject: [PATCH] Replace fmt.Sprintf with hex.EncodeToString (#21960) `hex.EncodeToString` has better performance than `fmt.Sprintf("%x", []byte)`, we should use it as much as possible. I'm not an extreme fan of performance, so I think there are some exceptions: - `fmt.Sprintf("%x", func(...)[N]byte())` - We can't slice the function return value directly, and it's not worth adding lines. ```diff func A()[20]byte { ... } - a := fmt.Sprintf("%x", A()) - a := hex.EncodeToString(A()[:]) // invalid + tmp := A() + a := hex.EncodeToString(tmp[:]) ``` - `fmt.Sprintf("%X", []byte)` - `strings.ToUpper(hex.EncodeToString(bytes))` has even worse performance. --- models/auth/twofactor.go | 3 ++- models/migrations/base/hash.go | 4 ++-- models/migrations/v1_14/v166.go | 4 ++-- models/user/user.go | 2 +- modules/packages/hashed_buffer_test.go | 10 +++++----- modules/packages/multi_hasher_test.go | 18 +++++++++--------- routers/api/packages/maven/maven.go | 4 ++-- routers/api/packages/pypi/pypi.go | 4 ++-- services/packages/packages.go | 9 +++++---- 9 files changed, 30 insertions(+), 28 deletions(-) diff --git a/models/auth/twofactor.go b/models/auth/twofactor.go index 179d315364..5b3a9d011a 100644 --- a/models/auth/twofactor.go +++ b/models/auth/twofactor.go @@ -9,6 +9,7 @@ import ( "crypto/subtle" "encoding/base32" "encoding/base64" + "encoding/hex" "fmt" "code.gitea.io/gitea/models/db" @@ -78,7 +79,7 @@ func (t *TwoFactor) GenerateScratchToken() (string, error) { // HashToken return the hashable salt func HashToken(token, salt string) string { tempHash := pbkdf2.Key([]byte(token), []byte(salt), 10000, 50, sha256.New) - return fmt.Sprintf("%x", tempHash) + return hex.EncodeToString(tempHash) } // VerifyScratchToken verifies if the specified scratch token is valid. diff --git a/models/migrations/base/hash.go b/models/migrations/base/hash.go index 164f826b45..00fd1efd4a 100644 --- a/models/migrations/base/hash.go +++ b/models/migrations/base/hash.go @@ -5,12 +5,12 @@ package base import ( "crypto/sha256" - "fmt" + "encoding/hex" "golang.org/x/crypto/pbkdf2" ) func HashToken(token, salt string) string { tempHash := pbkdf2.Key([]byte(token), []byte(salt), 10000, 50, sha256.New) - return fmt.Sprintf("%x", tempHash) + return hex.EncodeToString(tempHash) } diff --git a/models/migrations/v1_14/v166.go b/models/migrations/v1_14/v166.go index 1eb7263347..f797930d6d 100644 --- a/models/migrations/v1_14/v166.go +++ b/models/migrations/v1_14/v166.go @@ -5,7 +5,7 @@ package v1_14 //nolint import ( "crypto/sha256" - "fmt" + "encoding/hex" "golang.org/x/crypto/argon2" "golang.org/x/crypto/bcrypt" @@ -53,7 +53,7 @@ func RecalculateUserEmptyPWD(x *xorm.Engine) (err error) { tempPasswd = pbkdf2.Key([]byte(passwd), []byte(salt), 10000, 50, sha256.New) } - return fmt.Sprintf("%x", tempPasswd) + return hex.EncodeToString(tempPasswd) } // ValidatePassword checks if given password matches the one belongs to the user. diff --git a/models/user/user.go b/models/user/user.go index 7e3ae388fb..915e4243cf 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -401,7 +401,7 @@ func hashPassword(passwd, salt, algo string) (string, error) { tempPasswd = pbkdf2.Key([]byte(passwd), saltBytes, 10000, 50, sha256.New) } - return fmt.Sprintf("%x", tempPasswd), nil + return hex.EncodeToString(tempPasswd), nil } // SetPassword hashes a password using the algorithm defined in the config value of PASSWORD_HASH_ALGO diff --git a/modules/packages/hashed_buffer_test.go b/modules/packages/hashed_buffer_test.go index 529262226f..e907aa0605 100644 --- a/modules/packages/hashed_buffer_test.go +++ b/modules/packages/hashed_buffer_test.go @@ -4,7 +4,7 @@ package packages import ( - "fmt" + "encoding/hex" "io" "strings" "testing" @@ -36,10 +36,10 @@ func TestHashedBuffer(t *testing.T) { assert.Equal(t, c.Data, string(data)) hashMD5, hashSHA1, hashSHA256, hashSHA512 := buf.Sums() - assert.Equal(t, c.HashMD5, fmt.Sprintf("%x", hashMD5)) - assert.Equal(t, c.HashSHA1, fmt.Sprintf("%x", hashSHA1)) - assert.Equal(t, c.HashSHA256, fmt.Sprintf("%x", hashSHA256)) - assert.Equal(t, c.HashSHA512, fmt.Sprintf("%x", hashSHA512)) + assert.Equal(t, c.HashMD5, hex.EncodeToString(hashMD5)) + assert.Equal(t, c.HashSHA1, hex.EncodeToString(hashSHA1)) + assert.Equal(t, c.HashSHA256, hex.EncodeToString(hashSHA256)) + assert.Equal(t, c.HashSHA512, hex.EncodeToString(hashSHA512)) assert.NoError(t, buf.Close()) } diff --git a/modules/packages/multi_hasher_test.go b/modules/packages/multi_hasher_test.go index 42c1ef416f..a37debbc95 100644 --- a/modules/packages/multi_hasher_test.go +++ b/modules/packages/multi_hasher_test.go @@ -4,7 +4,7 @@ package packages import ( - "fmt" + "encoding/hex" "testing" "github.com/stretchr/testify/assert" @@ -24,10 +24,10 @@ func TestMultiHasherSums(t *testing.T) { hashMD5, hashSHA1, hashSHA256, hashSHA512 := h.Sums() - assert.Equal(t, expectedMD5, fmt.Sprintf("%x", hashMD5)) - assert.Equal(t, expectedSHA1, fmt.Sprintf("%x", hashSHA1)) - assert.Equal(t, expectedSHA256, fmt.Sprintf("%x", hashSHA256)) - assert.Equal(t, expectedSHA512, fmt.Sprintf("%x", hashSHA512)) + assert.Equal(t, expectedMD5, hex.EncodeToString(hashMD5)) + assert.Equal(t, expectedSHA1, hex.EncodeToString(hashSHA1)) + assert.Equal(t, expectedSHA256, hex.EncodeToString(hashSHA256)) + assert.Equal(t, expectedSHA512, hex.EncodeToString(hashSHA512)) }) t.Run("State", func(t *testing.T) { @@ -45,9 +45,9 @@ func TestMultiHasherSums(t *testing.T) { hashMD5, hashSHA1, hashSHA256, hashSHA512 := h2.Sums() - assert.Equal(t, expectedMD5, fmt.Sprintf("%x", hashMD5)) - assert.Equal(t, expectedSHA1, fmt.Sprintf("%x", hashSHA1)) - assert.Equal(t, expectedSHA256, fmt.Sprintf("%x", hashSHA256)) - assert.Equal(t, expectedSHA512, fmt.Sprintf("%x", hashSHA512)) + assert.Equal(t, expectedMD5, hex.EncodeToString(hashMD5)) + assert.Equal(t, expectedSHA1, hex.EncodeToString(hashSHA1)) + assert.Equal(t, expectedSHA256, hex.EncodeToString(hashSHA256)) + assert.Equal(t, expectedSHA512, hex.EncodeToString(hashSHA512)) }) } diff --git a/routers/api/packages/maven/maven.go b/routers/api/packages/maven/maven.go index 0ca3fa1793..d0c9983cbf 100644 --- a/routers/api/packages/maven/maven.go +++ b/routers/api/packages/maven/maven.go @@ -8,9 +8,9 @@ import ( "crypto/sha1" "crypto/sha256" "crypto/sha512" + "encoding/hex" "encoding/xml" "errors" - "fmt" "io" "net/http" "path/filepath" @@ -128,7 +128,7 @@ func serveMavenMetadata(ctx *context.Context, params parameters) { tmp := sha512.Sum512(xmlMetadataWithHeader) hash = tmp[:] } - ctx.PlainText(http.StatusOK, fmt.Sprintf("%x", hash)) + ctx.PlainText(http.StatusOK, hex.EncodeToString(hash)) return } diff --git a/routers/api/packages/pypi/pypi.go b/routers/api/packages/pypi/pypi.go index 826f58095e..6cf9329bbb 100644 --- a/routers/api/packages/pypi/pypi.go +++ b/routers/api/packages/pypi/pypi.go @@ -4,7 +4,7 @@ package pypi import ( - "fmt" + "encoding/hex" "io" "net/http" "regexp" @@ -118,7 +118,7 @@ func UploadPackageFile(ctx *context.Context) { _, _, hashSHA256, _ := buf.Sums() - if !strings.EqualFold(ctx.Req.FormValue("sha256_digest"), fmt.Sprintf("%x", hashSHA256)) { + if !strings.EqualFold(ctx.Req.FormValue("sha256_digest"), hex.EncodeToString(hashSHA256)) { apiError(ctx, http.StatusBadRequest, "hash mismatch") return } diff --git a/services/packages/packages.go b/services/packages/packages.go index f819949c96..49f5a2fac4 100644 --- a/services/packages/packages.go +++ b/services/packages/packages.go @@ -5,6 +5,7 @@ package packages import ( "context" + "encoding/hex" "errors" "fmt" "io" @@ -229,10 +230,10 @@ func NewPackageBlob(hsr packages_module.HashedSizeReader) *packages_model.Packag return &packages_model.PackageBlob{ Size: hsr.Size(), - HashMD5: fmt.Sprintf("%x", hashMD5), - HashSHA1: fmt.Sprintf("%x", hashSHA1), - HashSHA256: fmt.Sprintf("%x", hashSHA256), - HashSHA512: fmt.Sprintf("%x", hashSHA512), + HashMD5: hex.EncodeToString(hashMD5), + HashSHA1: hex.EncodeToString(hashSHA1), + HashSHA256: hex.EncodeToString(hashSHA256), + HashSHA512: hex.EncodeToString(hashSHA512), } }