From af8e2f91e2de1ef0ed0d38578d45cc343c3487a2 Mon Sep 17 00:00:00 2001 From: Alexander Schau Date: Sun, 30 Oct 2022 13:45:03 +0000 Subject: [PATCH] Initial commit --- README.md | 1 + base62.go | 43 +++++++++++++++++++++++++++++++++++++++++++ crc32.go | 14 ++++++++++++++ go.mod | 3 +++ main.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+) create mode 100644 README.md create mode 100644 base62.go create mode 100644 crc32.go create mode 100644 go.mod create mode 100644 main.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..4e1e0c7 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Go Access Token \ No newline at end of file diff --git a/base62.go b/base62.go new file mode 100644 index 0000000..564e57f --- /dev/null +++ b/base62.go @@ -0,0 +1,43 @@ +package accessToken + +import ( + "crypto/rand" +) + +func generateRandomBytes(n int) ([]byte, error) { + b := make([]byte, n) + _, err := rand.Read(b) + // Note that err == nil only if we read len(b) bytes. + if err != nil { + return nil, err + } + + return b, nil +} +func randomBase62String(n int) (string, error) { + const letters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + bytes, err := generateRandomBytes(n) + if err != nil { + return "", err + } + for i, b := range bytes { + bytes[i] = letters[b%byte(len(letters))] + } + return string(bytes), nil +} + +func EncodeBase62(n int) (string, error) { + letters := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + if n == 0 { + return "0", nil + } + + var base62 string + + for n > 0 { + base62 = letters[n%62:n%62+1] + base62 + n = n / 62 + } + + return base62, nil +} diff --git a/crc32.go b/crc32.go new file mode 100644 index 0000000..8e258ad --- /dev/null +++ b/crc32.go @@ -0,0 +1,14 @@ +package accessToken + +import "hash/crc32" + +func getChecksum(text string) (string, error) { + checksum, err := EncodeBase62(int(crc32.ChecksumIEEE([]byte(text)))) + if err != nil { + return "", err + } + checksum = "000000" + checksum + checksum = checksum[len(checksum)-6:] + + return checksum, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8652448 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.alxs.xyz/alexander/go_access_token + +go 1.19 diff --git a/main.go b/main.go new file mode 100644 index 0000000..2dd860c --- /dev/null +++ b/main.go @@ -0,0 +1,44 @@ +package accessToken + +import ( + "errors" + "fmt" + "regexp" +) + +func Generate(prefix string, secret string) (string, error) { + + if len(prefix) != 3 { + return "", errors.New("prefix is not 3 characters long") + } + + randomString, err := randomBase62String(30) + if err != nil { + return "", err + } + + firstPart := fmt.Sprintf("%s_%s", prefix, randomString) + + checksum, err := getChecksum(firstPart + secret) + if err != nil { + return "", err + } + + return firstPart + checksum, nil +} + +func Validate(token string, secret string) (bool, error) { + + exp := regexp.MustCompile("([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]{3})_([0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]{30})([0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]{6})") + + if !exp.Match([]byte(token)) { + return false, errors.New("wrong token format") + } + + checksum, err := getChecksum(token[:len(token)-6] + secret) + if err != nil { + return false, err + } + + return token[len(token)-6:] == checksum, nil +}