add go-license
This commit is contained in:
commit
0ddeb7d4aa
16 changed files with 462 additions and 0 deletions
3
go-license/go.mod
Normal file
3
go-license/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module git.rdctd.de/timo/blog/go-license
|
||||
|
||||
go 1.23.2
|
89
go-license/license.go
Normal file
89
go-license/license.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
package golicense
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
secret = []byte("superDuperSecret123!")
|
||||
ErrorHmacMismatch = errors.New("checksum mismatch - not a valid license key")
|
||||
)
|
||||
|
||||
type Data struct {
|
||||
Feature1 bool
|
||||
Feature2 int
|
||||
ValidTill time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type Envelope struct {
|
||||
Data Data
|
||||
Checksum []byte
|
||||
}
|
||||
|
||||
func (e *Envelope) String() (string, error) {
|
||||
d, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
str := base64.StdEncoding.EncodeToString(d)
|
||||
return str, nil
|
||||
}
|
||||
|
||||
func New(feature1 bool, feature2 int, expire int) (*Envelope, error) {
|
||||
d := Data{
|
||||
Feature1: feature1,
|
||||
Feature2: feature2,
|
||||
ValidTill: time.Now().AddDate(0, 0, expire),
|
||||
}
|
||||
|
||||
e := Envelope{
|
||||
Data: d,
|
||||
}
|
||||
|
||||
db, err := json.Marshal(&d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hmac := hmac.New(sha256.New, secret)
|
||||
hmac.Write(db)
|
||||
dh := hmac.Sum(nil)
|
||||
|
||||
e.Checksum = dh
|
||||
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
func Verify(in string) (*Envelope, error) {
|
||||
d, err := base64.StdEncoding.DecodeString(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var e Envelope
|
||||
if err := json.Unmarshal(d, &e); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
db, err := json.Marshal(e.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hm := hmac.New(sha256.New, secret)
|
||||
hm.Write(db)
|
||||
dh := hm.Sum(nil)
|
||||
|
||||
if !hmac.Equal(e.Checksum, dh) {
|
||||
return nil, ErrorHmacMismatch
|
||||
}
|
||||
|
||||
return &e, nil
|
||||
}
|
57
go-license/license_test.go
Normal file
57
go-license/license_test.go
Normal file
|
@ -0,0 +1,57 @@
|
|||
package golicense
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestVerify(t *testing.T) {
|
||||
e, err := New(true, 5, 365)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
key, err := e.String()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
e2, err := Verify(key)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if e2.Data.Feature1 != e.Data.Feature1 {
|
||||
t.Error("Feature1 mismatch")
|
||||
}
|
||||
|
||||
if e2.Data.Feature2 != e.Data.Feature2 {
|
||||
t.Error("Feature2 mismatchh")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyMismatch(t *testing.T) {
|
||||
e1, _ := New(true, 5, 365)
|
||||
|
||||
e2, _ := New(false, 5, 365)
|
||||
|
||||
key1, _ := e1.String()
|
||||
key2, _ := e2.String()
|
||||
|
||||
if key1 == key2 {
|
||||
t.Error("same keys, different license data")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVerifyModifiedData(t *testing.T) {
|
||||
e, _ := New(false, 5, 365)
|
||||
|
||||
e.Data.Feature1 = true
|
||||
|
||||
key, _ := e.String()
|
||||
|
||||
_, err := Verify(key)
|
||||
|
||||
if err != ErrorHmacMismatch {
|
||||
t.Error("No HmacMismatch error")
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue