add go-license

This commit is contained in:
Timo Zimmermann 2025-02-27 17:06:37 +00:00
commit 0ddeb7d4aa
16 changed files with 462 additions and 0 deletions

3
go-license/go.mod Normal file
View file

@ -0,0 +1,3 @@
module git.rdctd.de/timo/blog/go-license
go 1.23.2

89
go-license/license.go Normal file
View 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
}

View 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")
}
}