From f9b9e0387f75d5f0fb29df90caedfccd254eb97b Mon Sep 17 00:00:00 2001 From: David Voisin Date: Mon, 26 Aug 2024 17:23:15 +0200 Subject: [PATCH 1/7] Simplify passwords generation * default password length is raised from 20 to 24 characters long * generated passwords contain only alphanumeric and underscore characters * not related to the issue, upgrade to go 1.23 --- CHANGELOG.md | 4 ++++ README.md | 4 ++-- go.mod | 2 +- gopassword.go | 17 ++++++----------- gopassword_test.go | 23 ++++++++++++++++++----- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbbeafe..0d648f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## To be Released +* chore(go): use go 1.23 +* Raise default length from 20 to 24 +* Allow `_` only as special character + ## 1.0.3 * chore(go): use go 1.20 diff --git a/README.md b/README.md index 936ed2f..f180263 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Simple password generator in Go. Use `crypto/rand` ```go -// Passowrd of 20 characters +// Password of 24 characters gopassword.Generate() // Password of 42 characters @@ -17,7 +17,7 @@ Bump new version number in `CHANGELOG.md` and `README.md`. Commit, tag and create a new release: ```sh -version="1.0.3" +version="1.0.4" git switch --create release/${version} git add CHANGELOG.md README.md git commit -m "Bump v${version}" diff --git a/go.mod b/go.mod index d02acfe..72b4fe6 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/Scalingo/gopassword -go 1.20 +go 1.23 require github.com/stretchr/testify v1.9.0 diff --git a/gopassword.go b/gopassword.go index 7a89347..daa98e7 100644 --- a/gopassword.go +++ b/gopassword.go @@ -3,12 +3,14 @@ package gopassword import ( "crypto/rand" "encoding/base64" - "fmt" "strings" ) +const defaultLength = 24 +const defaultSpecialChar = "_" + func Generate(n ...int) string { - length := 20 + length := defaultLength if len(n) > 0 { length = n[0] } @@ -23,15 +25,8 @@ func Generate(n ...int) string { randString := base64.StdEncoding.EncodeToString(randBytes) password := randString[:length] - password = strings.Replace(password, "+", "_", -1) - password = strings.Replace(password, "/", "-", -1) - - if password[0] == '-' { - password = fmt.Sprintf("_%s", password[1:]) - } - if password[length-1] == '-' { - password = fmt.Sprintf("%s_", password[:length-1]) - } + password = strings.Replace(password, "+", defaultSpecialChar, -1) + password = strings.Replace(password, "/", defaultSpecialChar, -1) return password } diff --git a/gopassword_test.go b/gopassword_test.go index d846ba6..4a6ea51 100644 --- a/gopassword_test.go +++ b/gopassword_test.go @@ -1,6 +1,7 @@ package gopassword import ( + "regexp" "testing" "github.com/stretchr/testify/assert" @@ -8,22 +9,34 @@ import ( func TestGenerate(t *testing.T) { t.Run("When we want to generate a password", func(t *testing.T) { - t.Run("By default, it should be 20 characters", func(t *testing.T) { - assert.Len(t, Generate(), 20) + t.Run("By default, it must be 24 characters", func(t *testing.T) { + assert.Len(t, Generate(), 24) }) - t.Run("With an argument, the generated password should have its length", func(t *testing.T) { + t.Run("With an argument, the generated password must have its length", func(t *testing.T) { + assert.Len(t, Generate(10), 10) assert.Len(t, Generate(42), 42) + assert.Len(t, Generate(999), 999) }) - t.Run("With several arguments, only the first should be considered", func(t *testing.T) { + t.Run("With several arguments, only the first must be considered", func(t *testing.T) { assert.Len(t, Generate(10, 20, 30), 10) }) + + t.Run("It must contain only alphanumeric or underscore characters", func(t *testing.T) { + allowedCharacters, _ := regexp.Compile("^[a-zA-Z0-9_]+$") + + // Try various times to ensure the result is not casual + for _ = range 1000 { + passwd := Generate(99) + assert.True(t, allowedCharacters.MatchString(passwd)) + } + }) }) t.Run("Given a generated password", func(t *testing.T) { passwd := Generate(20) - t.Run("The character frequency should be low", func(t *testing.T) { + t.Run("The character frequency must be low", func(t *testing.T) { fm := frequencyMap(passwd) maxFreq := max(fm) assert.LessOrEqual(t, maxFreq, 3) From 667a13a0abb3ef741bc419d84bbb5180cca921b4 Mon Sep 17 00:00:00 2001 From: David Voisin Date: Mon, 26 Aug 2024 22:02:22 +0200 Subject: [PATCH 2/7] Linter --- gopassword.go | 4 ++-- gopassword_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gopassword.go b/gopassword.go index daa98e7..0763845 100644 --- a/gopassword.go +++ b/gopassword.go @@ -25,8 +25,8 @@ func Generate(n ...int) string { randString := base64.StdEncoding.EncodeToString(randBytes) password := randString[:length] - password = strings.Replace(password, "+", defaultSpecialChar, -1) - password = strings.Replace(password, "/", defaultSpecialChar, -1) + password = strings.ReplaceAll(password, "+", defaultSpecialChar) + password = strings.ReplaceAll(password, "/", defaultSpecialChar) return password } diff --git a/gopassword_test.go b/gopassword_test.go index 4a6ea51..bf3c257 100644 --- a/gopassword_test.go +++ b/gopassword_test.go @@ -24,7 +24,7 @@ func TestGenerate(t *testing.T) { }) t.Run("It must contain only alphanumeric or underscore characters", func(t *testing.T) { - allowedCharacters, _ := regexp.Compile("^[a-zA-Z0-9_]+$") + allowedCharacters := regexp.MustCompile("^[a-zA-Z0-9_]+$") // Try various times to ensure the result is not casual for _ = range 1000 { From f0c2083fd6fbe406fe8f9a3f1464e0c7a2eb49fb Mon Sep 17 00:00:00 2001 From: David Voisin Date: Tue, 27 Aug 2024 09:29:33 +0200 Subject: [PATCH 3/7] Bump version --- CHANGELOG.md | 2 +- README.md | 2 +- gopassword_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d648f5..a0eca47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## To be Released +## 1.0.4 * chore(go): use go 1.23 * Raise default length from 20 to 24 diff --git a/README.md b/README.md index f180263..1acd692 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Go Password v1.0.3 +# Go Password v1.0.4 Simple password generator in Go. Use `crypto/rand` diff --git a/gopassword_test.go b/gopassword_test.go index bf3c257..b8c05b2 100644 --- a/gopassword_test.go +++ b/gopassword_test.go @@ -27,7 +27,7 @@ func TestGenerate(t *testing.T) { allowedCharacters := regexp.MustCompile("^[a-zA-Z0-9_]+$") // Try various times to ensure the result is not casual - for _ = range 1000 { + for range 1000 { passwd := Generate(99) assert.True(t, allowedCharacters.MatchString(passwd)) } From 447abebe9f234cc5516fc4ff84f90248e3d81f5b Mon Sep 17 00:00:00 2001 From: David Voisin Date: Tue, 27 Aug 2024 09:40:43 +0200 Subject: [PATCH 4/7] Revert bump version --- CHANGELOG.md | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0eca47..0d648f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 1.0.4 +## To be Released * chore(go): use go 1.23 * Raise default length from 20 to 24 diff --git a/README.md b/README.md index 1acd692..0ae9f89 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Go Password v1.0.4 +# Go Password v1.0.3 Simple password generator in Go. Use `crypto/rand` @@ -17,7 +17,7 @@ Bump new version number in `CHANGELOG.md` and `README.md`. Commit, tag and create a new release: ```sh -version="1.0.4" +version="1.0.3" git switch --create release/${version} git add CHANGELOG.md README.md git commit -m "Bump v${version}" From 607d4ec3d993aa6e2f08140535b30b4f6880579c Mon Sep 17 00:00:00 2001 From: David Voisin Date: Tue, 27 Aug 2024 09:43:31 +0200 Subject: [PATCH 5/7] Upgrade to go 1.22 instead of 1.23 As per our servers Go version. --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 72b4fe6..a80f1a0 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/Scalingo/gopassword -go 1.23 +go 1.22 require github.com/stretchr/testify v1.9.0 From 313d0c661422005003accf839cf7f4c007461fe3 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 27 Aug 2024 09:59:38 +0200 Subject: [PATCH 6/7] Update CHANGELOG.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Étienne M. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d648f5..749d8cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## To be Released -* chore(go): use go 1.23 +* chore(go): use go 1.22 * Raise default length from 20 to 24 * Allow `_` only as special character From c866c851d8c150e5e9f46d7d9285ba1ca4bc9ba0 Mon Sep 17 00:00:00 2001 From: David Voisin Date: Tue, 27 Aug 2024 10:18:57 +0200 Subject: [PATCH 7/7] Raise default password length to 64 --- CHANGELOG.md | 2 +- README.md | 2 +- gopassword.go | 2 +- gopassword_test.go | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 749d8cf..35d0fea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ## To be Released * chore(go): use go 1.22 -* Raise default length from 20 to 24 +* Raise default length from 20 to 64 * Allow `_` only as special character ## 1.0.3 diff --git a/README.md b/README.md index 0ae9f89..2d63dc4 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Simple password generator in Go. Use `crypto/rand` ```go -// Password of 24 characters +// Password of 64 characters gopassword.Generate() // Password of 42 characters diff --git a/gopassword.go b/gopassword.go index 0763845..43c679a 100644 --- a/gopassword.go +++ b/gopassword.go @@ -6,7 +6,7 @@ import ( "strings" ) -const defaultLength = 24 +const defaultLength = 64 const defaultSpecialChar = "_" func Generate(n ...int) string { diff --git a/gopassword_test.go b/gopassword_test.go index b8c05b2..879204a 100644 --- a/gopassword_test.go +++ b/gopassword_test.go @@ -9,8 +9,8 @@ import ( func TestGenerate(t *testing.T) { t.Run("When we want to generate a password", func(t *testing.T) { - t.Run("By default, it must be 24 characters", func(t *testing.T) { - assert.Len(t, Generate(), 24) + t.Run("By default, it must be 64 characters", func(t *testing.T) { + assert.Len(t, Generate(), 64) }) t.Run("With an argument, the generated password must have its length", func(t *testing.T) {