170 lines
3.5 KiB
Go
170 lines
3.5 KiB
Go
package util
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"errors"
|
|
"math/big"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const RandomLower = "abcdefghijklmnopqrstuvwxyz"
|
|
const RandomUpper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
const RandomDigit = "0123456789"
|
|
const RandomSpecial = "!_.~?-+=#@$%"
|
|
const RandomAlpha = RandomLower + RandomUpper
|
|
const RandomAll = RandomAlpha + RandomDigit + RandomSpecial
|
|
|
|
var RandomSlice = []string{RandomLower, RandomUpper, RandomDigit, RandomSpecial}
|
|
|
|
func RandomString(length int, str ...string) string {
|
|
chars := RandomAll
|
|
if len(str) != 0 {
|
|
chars = ""
|
|
for _, v := range str {
|
|
chars += v
|
|
}
|
|
}
|
|
charsLen := len(chars)
|
|
res := make([]byte, length)
|
|
for i := range res {
|
|
r, err := rand.Int(rand.Reader, big.NewInt(int64(charsLen)))
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
res[i] = chars[r.Int64()]
|
|
}
|
|
return string(res)
|
|
}
|
|
|
|
func RandomStringAtLeastOnce(length int, str ...string) string {
|
|
chars := RandomSlice
|
|
charsLen := len(RandomSlice)
|
|
if len(str) != 0 {
|
|
chars = str
|
|
charsLen = len(str)
|
|
}
|
|
charsPerLen := make([]int, charsLen)
|
|
for i := range charsPerLen {
|
|
charsPerLen[i] = len(chars[i])
|
|
}
|
|
res := make([]byte, length)
|
|
|
|
i := 0
|
|
for ; i < charsLen && i < length; i++ {
|
|
r, err := rand.Int(rand.Reader, big.NewInt(int64(charsPerLen[i])))
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
res[i] = chars[i][r.Int64()]
|
|
}
|
|
for ; i < length; i++ {
|
|
r, err := rand.Int(rand.Reader, big.NewInt(int64(charsLen)))
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
t := r.Int64()
|
|
r2, err := rand.Int(rand.Reader, big.NewInt(int64(charsPerLen[t])))
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
res[i] = chars[t][r2.Int64()]
|
|
}
|
|
|
|
for i = range res {
|
|
t, err := rand.Int(rand.Reader, big.NewInt(int64(length)))
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
res[i], res[t.Int64()] = res[t.Int64()], res[i]
|
|
}
|
|
return string(res)
|
|
}
|
|
|
|
const RandomStringWithTimestampTimeLength = 8
|
|
|
|
func RandomStringWithTimestamp(length int, unix ...int64) string {
|
|
if length < RandomStringWithTimestampTimeLength {
|
|
length = RandomStringWithTimestampTimeLength
|
|
}
|
|
var t int64
|
|
if len(unix) > 0 {
|
|
t = unix[0]
|
|
} else {
|
|
t = time.Now().Unix()
|
|
}
|
|
|
|
return TimeUnixToBase36(t, RandomStringWithTimestampTimeLength) + RandomString(length-RandomStringWithTimestampTimeLength)
|
|
}
|
|
|
|
func ParseRandomStringWithTimestamp(str string) (int64, string) {
|
|
if len(str) < RandomStringWithTimestampTimeLength {
|
|
return 0, ""
|
|
}
|
|
t := TimeBase36ToUnix(string([]byte(str)[:RandomStringWithTimestampTimeLength]))
|
|
if t == 0 {
|
|
return 0, ""
|
|
}
|
|
return t, string([]byte(str)[RandomStringWithTimestampTimeLength:])
|
|
}
|
|
|
|
type KeyResult struct {
|
|
key []byte
|
|
err error
|
|
}
|
|
|
|
func (k *KeyResult) Bytes() []byte {
|
|
if k.err != nil {
|
|
return []byte{}
|
|
}
|
|
return k.key
|
|
}
|
|
|
|
func (k *KeyResult) Upper() string {
|
|
if k.err != nil {
|
|
return ""
|
|
}
|
|
return strings.ToUpper(hex.EncodeToString(k.key))
|
|
}
|
|
|
|
func (k *KeyResult) Lower() string {
|
|
if k.err != nil {
|
|
return ""
|
|
}
|
|
return strings.ToLower(hex.EncodeToString(k.key))
|
|
}
|
|
|
|
func (k *KeyResult) Error() error {
|
|
return k.err
|
|
}
|
|
|
|
func NewKeyResult(data []byte, err error) *KeyResult {
|
|
res := &KeyResult{
|
|
key: make([]byte, len(data)),
|
|
err: err,
|
|
}
|
|
copy(res.key, data)
|
|
return res
|
|
}
|
|
|
|
func KeyResultFromHexString(hx string) *KeyResult {
|
|
k, err := hex.DecodeString(hx)
|
|
if err != nil {
|
|
return NewKeyResult(nil, err)
|
|
}
|
|
return NewKeyResult(k, nil)
|
|
}
|
|
|
|
func RandomKey(l int) *KeyResult {
|
|
k := make([]byte, l)
|
|
n, err := rand.Read(k)
|
|
if err != nil {
|
|
return NewKeyResult(nil, err)
|
|
}
|
|
if n != l {
|
|
return NewKeyResult(nil, errors.New("invalid length"))
|
|
}
|
|
return NewKeyResult(k, nil)
|
|
}
|