-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgoidgen.go
126 lines (107 loc) · 3.28 KB
/
goidgen.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package goidgen
import (
"crypto/rand"
"errors"
rand2 "math/rand"
"time"
)
// properties for a goidgen instance
type goidgen struct {
ASCII_LOWERCASE string
ASCII_UPPERCASE string
ASCII_LETTERS string
DIGITS string
HEXDIGITS string
OCTDIGITS string
PUNCTUATION string
URL_SAFE string
PRINTABLE string
}
// New returns a new goidgen instance
func New() goidgen {
// seed random
rand2.Seed(time.Now().UTC().UnixNano())
// fill fields with predefined character sets
return goidgen{
ASCII_LOWERCASE: "abcdefghijklmnopqrstuvwxyz",
ASCII_UPPERCASE: "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
ASCII_LETTERS: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
DIGITS: "0123456789",
HEXDIGITS: "0123456789abcdefABCDEF",
OCTDIGITS: "01234567",
PUNCTUATION: "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~",
URL_SAFE: "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
PRINTABLE: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c",
}
}
// Generate generates secure, random ID's
// Accepts optional parameter - alphabet to use for ID generation. If omitted, it will default to URL-safe characters
func (g *goidgen) Generate(length int, alphabet ...string) (string, error) {
// error checking
if length <= 0 {
return "", errors.New("length must be >= 0")
} else if len(alphabet) > 0 && len(alphabet[0]) > 255 {
return "", errors.New("alphabet size must be <= 255 characters")
}
// establish char set to be used
var chars string
// check if an alphabet was provided
if len(alphabet) > 0 {
// use provided alphabet
chars = alphabet[0]
} else {
// use url_safe characters
chars = g.URL_SAFE
}
// randomly generate random bytes
b := make([]byte, length)
x, _ := rand.Read(b)
_ = x
// len of chars as byte
len := byte(len(chars))
// result byte buffer
result := make([]byte, length)
// iterate length times
for i := 0; i < length; i++ {
// write randomly-drawn byte to builder
result[i] = chars[(b[i]/(255/len))%len]
}
// return builder's string
return string(result), nil
}
// Generate generates unsecure, random ID's
// "Unsecure" refers to math/rand being used for RNG rather than a crypto-safe solution
// Accepts optional parameter - alphabet to use for ID generation. If omitted, it will default to URL-safe characters
func (g *goidgen) GenerateUnsecure(length int, alphabet ...string) (string, error) {
// error checking
if length <= 0 {
return "", errors.New("length must be >= 0")
} else if len(alphabet) > 0 && len(alphabet[0]) > 255 {
return "", errors.New("alphabet size must be <= 255 characters")
}
// establish char set to be used
var chars string
// check if an alphabet was provided
if len(alphabet) > 0 {
// use provided alphabet
chars = alphabet[0]
} else {
// use url_safe characters
chars = g.URL_SAFE
}
// randomly generate random bytes
b := make([]byte, length)
x, _ := rand2.Read(b)
_ = x
// len of chars as byte
len := byte(len(chars))
// result byte buffer
result := make([]byte, length)
// iterate length times
for i := 0; i < length; i++ {
// write randomly-drawn byte to builder
result[i] = chars[(b[i]/(255/len))%len]
}
// return builder's string
return string(result), nil
}