Skip to content

Commit 53df0bf

Browse files
GustedEarl Warren
authored andcommitted
chore(sec): unify usage of crypto/rand.Read (go-gitea#7453)
- Unify the usage of [`crypto/rand.Read`](https://pkg.go.dev/crypto/rand#Read) to `util.CryptoRandomBytes`. - Refactor `util.CryptoRandomBytes` to never return an error. It is documented by Go, https://go.dev/issue/66821, to always succeed. So if we still receive a error or if the returned bytes read is not equal to the expected bytes to be read we panic (just to be on the safe side). - This simplifies a lot of code to no longer care about error handling. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7453 Reviewed-by: Earl Warren <[email protected]> Co-authored-by: Gusted <[email protected]> Co-committed-by: Gusted <[email protected]>
1 parent 99fc04b commit 53df0bf

File tree

25 files changed

+61
-163
lines changed

25 files changed

+61
-163
lines changed

cmd/generate.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,7 @@ func runGenerateInternalToken(c *cli.Context) error {
7070
}
7171

7272
func runGenerateLfsJwtSecret(c *cli.Context) error {
73-
_, jwtSecretBase64, err := generate.NewJwtSecret()
74-
if err != nil {
75-
return err
76-
}
73+
_, jwtSecretBase64 := generate.NewJwtSecret()
7774

7875
fmt.Printf("%s", jwtSecretBase64)
7976

models/actions/runner.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,7 @@ func (r *ActionRunner) GenerateToken() (err error) {
168168
// UpdateSecret updates the hash based on the specified token. It does not
169169
// ensure that the runner's UUID matches the first 16 bytes of the token.
170170
func (r *ActionRunner) UpdateSecret(token string) error {
171-
saltBytes, err := util.CryptoRandomBytes(16)
172-
if err != nil {
173-
return fmt.Errorf("CryptoRandomBytes %v", err)
174-
}
175-
176-
salt := hex.EncodeToString(saltBytes)
171+
salt := hex.EncodeToString(util.CryptoRandomBytes(16))
177172

178173
r.Token = token
179174
r.TokenSalt = salt

models/actions/utils.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@ func generateSaltedToken() (string, string, string, string, error) {
2222
if err != nil {
2323
return "", "", "", "", err
2424
}
25-
buf, err := util.CryptoRandomBytes(20)
26-
if err != nil {
27-
return "", "", "", "", err
28-
}
29-
token := hex.EncodeToString(buf)
25+
token := hex.EncodeToString(util.CryptoRandomBytes(20))
3026
hash := auth_model.HashToken(token, salt)
3127
return token, salt, hash, token[len(token)-8:], nil
3228
}

models/auth/access_token.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,8 @@ func generateAccessToken(t *AccessToken) error {
111111
if err != nil {
112112
return err
113113
}
114-
token, err := util.CryptoRandomBytes(20)
115-
if err != nil {
116-
return err
117-
}
118114
t.TokenSalt = salt
119-
t.Token = hex.EncodeToString(token)
115+
t.Token = hex.EncodeToString(util.CryptoRandomBytes(20))
120116
t.TokenHash = HashToken(t.Token, t.TokenSalt)
121117
t.TokenLastEight = t.Token[len(t.Token)-8:]
122118
return nil

models/auth/auth_token.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ func (authToken *AuthorizationToken) IsExpired() bool {
6363
func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeStamp, purpose AuthorizationPurpose) (lookupKey, validator string, err error) {
6464
// Request 64 random bytes. The first 32 bytes will be used for the lookupKey
6565
// and the other 32 bytes will be used for the validator.
66-
rBytes, err := util.CryptoRandomBytes(64)
67-
if err != nil {
68-
return "", "", err
69-
}
66+
rBytes := util.CryptoRandomBytes(64)
7067
hexEncoded := hex.EncodeToString(rBytes)
7168
validator, lookupKey = hexEncoded[64:], hexEncoded[:64]
7269

models/auth/oauth2.go

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -184,13 +184,9 @@ var base32Lower = base32.NewEncoding(lowerBase32Chars).WithPadding(base32.NoPadd
184184

185185
// GenerateClientSecret will generate the client secret and returns the plaintext and saves the hash at the database
186186
func (app *OAuth2Application) GenerateClientSecret(ctx context.Context) (string, error) {
187-
rBytes, err := util.CryptoRandomBytes(32)
188-
if err != nil {
189-
return "", err
190-
}
191187
// Add a prefix to the base32, this is in order to make it easier
192188
// for code scanners to grab sensitive tokens.
193-
clientSecret := "gto_" + base32Lower.EncodeToString(rBytes)
189+
clientSecret := "gto_" + base32Lower.EncodeToString(util.CryptoRandomBytes(32))
194190

195191
hashedSecret, err := bcrypt.GenerateFromPassword([]byte(clientSecret), bcrypt.DefaultCost)
196192
if err != nil {
@@ -475,13 +471,9 @@ func (grant *OAuth2Grant) TableName() string {
475471

476472
// GenerateNewAuthorizationCode generates a new authorization code for a grant and saves it to the database
477473
func (grant *OAuth2Grant) GenerateNewAuthorizationCode(ctx context.Context, redirectURI, codeChallenge, codeChallengeMethod string) (code *OAuth2AuthorizationCode, err error) {
478-
rBytes, err := util.CryptoRandomBytes(32)
479-
if err != nil {
480-
return &OAuth2AuthorizationCode{}, err
481-
}
482474
// Add a prefix to the base32, this is in order to make it easier
483475
// for code scanners to grab sensitive tokens.
484-
codeSecret := "gta_" + base32Lower.EncodeToString(rBytes)
476+
codeSecret := "gta_" + base32Lower.EncodeToString(util.CryptoRandomBytes(32))
485477

486478
code = &OAuth2AuthorizationCode{
487479
Grant: grant,

models/auth/twofactor.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,13 @@ func init() {
6161
}
6262

6363
// GenerateScratchToken recreates the scratch token the user is using.
64-
func (t *TwoFactor) GenerateScratchToken() (string, error) {
65-
tokenBytes, err := util.CryptoRandomBytes(6)
66-
if err != nil {
67-
return "", err
68-
}
64+
func (t *TwoFactor) GenerateScratchToken() string {
6965
// these chars are specially chosen, avoid ambiguous chars like `0`, `O`, `1`, `I`.
7066
const base32Chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"
71-
token := base32.NewEncoding(base32Chars).WithPadding(base32.NoPadding).EncodeToString(tokenBytes)
67+
token := base32.NewEncoding(base32Chars).WithPadding(base32.NoPadding).EncodeToString(util.CryptoRandomBytes(6))
7268
t.ScratchSalt, _ = util.CryptoRandomString(10)
7369
t.ScratchHash = HashToken(token, t.ScratchSalt)
74-
return token, nil
70+
return token
7571
}
7672

7773
// HashToken return the hashable salt

models/organization/org.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -289,12 +289,8 @@ func CreateOrganization(ctx context.Context, org *Organization, owner *user_mode
289289
}
290290

291291
org.LowerName = strings.ToLower(org.Name)
292-
if org.Rands, err = user_model.GetUserSalt(); err != nil {
293-
return err
294-
}
295-
if org.Salt, err = user_model.GetUserSalt(); err != nil {
296-
return err
297-
}
292+
org.Rands = user_model.GetUserSalt()
293+
org.Salt = user_model.GetUserSalt()
298294
org.UseCustomAvatar = true
299295
org.MaxRepoCreation = -1
300296
org.NumTeams = 1

models/user/email_address.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,7 @@ func updateActivation(ctx context.Context, email *EmailAddress, activate bool) e
266266
if err != nil {
267267
return err
268268
}
269-
if user.Rands, err = GetUserSalt(); err != nil {
270-
return err
271-
}
269+
user.Rands = GetUserSalt()
272270
email.IsActivated = activate
273271
if _, err := db.GetEngine(ctx).ID(email.ID).Cols("is_activated").Update(email); err != nil {
274272
return err
@@ -403,9 +401,7 @@ func ActivateUserEmail(ctx context.Context, userID int64, email string, activate
403401
// The user's activation state should be synchronized with the primary email
404402
if user.IsActive != activate {
405403
user.IsActive = activate
406-
if user.Rands, err = GetUserSalt(); err != nil {
407-
return fmt.Errorf("unable to generate salt: %w", err)
408-
}
404+
user.Rands = GetUserSalt()
409405
if err = UpdateUserCols(ctx, user, "is_active", "rands"); err != nil {
410406
return fmt.Errorf("unable to updateUserCols() for user ID: %d: %w", userID, err)
411407
}

models/user/user.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,7 @@ func (u *User) SetPassword(passwd string) (err error) {
387387
return err
388388
}
389389

390-
if u.Salt, err = GetUserSalt(); err != nil {
391-
return err
392-
}
390+
u.Salt = GetUserSalt()
393391
if u.Passwd, err = hash.Parse(setting.PasswordHashAlgo).Hash(passwd, u.Salt); err != nil {
394392
return err
395393
}
@@ -559,13 +557,9 @@ func IsUserExist(ctx context.Context, uid int64, name string) (bool, error) {
559557
const SaltByteLength = 16
560558

561559
// GetUserSalt returns a random user salt token.
562-
func GetUserSalt() (string, error) {
563-
rBytes, err := util.CryptoRandomBytes(SaltByteLength)
564-
if err != nil {
565-
return "", err
566-
}
560+
func GetUserSalt() string {
567561
// Returns a 32 bytes long string.
568-
return hex.EncodeToString(rBytes), nil
562+
return hex.EncodeToString(util.CryptoRandomBytes(SaltByteLength))
569563
}
570564

571565
// Note: The set of characters here can safely expand without a breaking change,
@@ -772,9 +766,7 @@ func createUser(ctx context.Context, u *User, createdByAdmin bool, overwriteDefa
772766

773767
u.LowerName = strings.ToLower(u.Name)
774768
u.AvatarEmail = u.Email
775-
if u.Rands, err = GetUserSalt(); err != nil {
776-
return err
777-
}
769+
u.Rands = GetUserSalt()
778770
if u.Passwd != "" {
779771
if err = u.SetPassword(u.Passwd); err != nil {
780772
return err

0 commit comments

Comments
 (0)