41 lines
1.1 KiB
Go
41 lines
1.1 KiB
Go
|
package usecase
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"math/big"
|
||
|
)
|
||
|
|
||
|
// ErrInvalidDigits is returned when the number of digits is invalid
|
||
|
var ErrInvalidDigits = errors.New("invalid number of digits")
|
||
|
|
||
|
// generateVerifyCode generates a cryptographically secure verification code.
|
||
|
// The digits parameter specifies the number of digits in the code (4-10).
|
||
|
// If digits is 0 or negative, it defaults to 6 digits.
|
||
|
func generateVerifyCode(digits int) (string, error) {
|
||
|
// Default to 6 digits if not specified or invalid
|
||
|
if digits <= 0 {
|
||
|
digits = 6
|
||
|
}
|
||
|
|
||
|
// Validate digit range
|
||
|
if digits < 4 || digits > 10 {
|
||
|
return "", fmt.Errorf("%w: digits must be between 4 and 10, got %d", ErrInvalidDigits, digits)
|
||
|
}
|
||
|
|
||
|
// Calculate maximum value (10^digits - 1)
|
||
|
exp := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(digits)), nil)
|
||
|
|
||
|
// Generate cryptographically secure random number
|
||
|
randomNumber, err := rand.Int(rand.Reader, exp)
|
||
|
if err != nil {
|
||
|
return "", fmt.Errorf("failed to generate random number: %w", err)
|
||
|
}
|
||
|
|
||
|
// Convert to string with zero padding
|
||
|
verifyCode := fmt.Sprintf("%0*d", digits, randomNumber)
|
||
|
|
||
|
return verifyCode, nil
|
||
|
}
|