| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 | package licenseimport (	"bytes"	"crypto/aes"	"crypto/cipher"	"crypto/rand"	"encoding/base32"	"errors"	"fmt"	"io"	"os"	"strconv"	"time")var (	ErrLicenseInvalid            = errors.New("license: invalid")	ErrLicenseUnsupportedVersion = errors.New("license: unsupported version")	ErrLicenseExpired            = errors.New("license: expired"))type EncryptVersion uint8const (	EncryptV1 EncryptVersion = 1)const (	// EncryptDefault 默认加密版本	EncryptDefault = EncryptV1)type Info interface {	CreateAt() time.Time	ExpireAt() time.Time	Expired() bool}type InvalidLicense struct {	Create time.Time}func (e *InvalidLicense) CreateAt() time.Time {	if e.Create.IsZero() {		e.Create = time.Now()	}	return e.Create}func (e *InvalidLicense) ExpireAt() time.Time {	return e.Create}func (e *InvalidLicense) Expired() bool {	return true}// License 密钥授权type License struct {	key []byte}// New 使用 expiration 作为过期时间创建一个密钥// 创建时会注入[创建者]操作系统的时间到密钥中用于解密时的时间范围验证func (l *License) New(expiration time.Time) (string, error) {	if expiration.IsZero() {		return "", fmt.Errorf("invalid expiration: %s", expiration)	}	plaintext, err := l.NewWith(EncryptDefault, expiration)	if err != nil {		return "", err	}	encrypted, err := l.Encrypt(plaintext)	if err != nil {		return "", err	}	return base32.StdEncoding.WithPadding(base32.NoPadding).EncodeToString(encrypted), nil}// Stat 解密 encryptedKey 并返回许可证信息func (l *License) Stat(encryptedKey string) (Info, error) {	encrypted, err := base32.StdEncoding.WithPadding(base32.NoPadding).DecodeString(encryptedKey)	if err != nil {		return nil, err	}	plaintext, err := l.Decrypt(encrypted)	if err != nil {		return nil, err	}	return l.StatWith(EncryptDefault, plaintext)}// NewWith 与 New 相等, 但指定加密版本号func (l *License) NewWith(v EncryptVersion, expiration time.Time) ([]byte, error) {	switch v {	case EncryptV1:		return l.newV1(expiration)	default:		return nil, ErrLicenseUnsupportedVersion	}}// StatWith 与 Stat 相等, 但指定加密版本号func (l *License) StatWith(v EncryptVersion, plaintext []byte) (Info, error) {	switch v {	case EncryptV1:		return l.statV1(plaintext)	default:		return nil, ErrLicenseUnsupportedVersion	}}// Encrypt 使用 AES-128-GCM 加密 plaintext 并返回密文func (l *License) Encrypt(plaintext []byte) ([]byte, error) {	block, err := aes.NewCipher(l.key)	if err != nil {		return nil, err	}	gcm, err := cipher.NewGCMWithRandomNonce(block)	if err != nil {		return nil, err	}	// 生成随机 nonce	nonce := make([]byte, gcm.NonceSize())	if _, err = io.ReadFull(rand.Reader, nonce); err != nil {		return nil, err	}	ciphertext := gcm.Seal(nil, nonce, plaintext, nil)	return append(nonce, ciphertext...), nil}// Decrypt 使用 AES-128-GCM 解密 encrypted 并返回明文func (l *License) Decrypt(encrypted []byte) ([]byte, error) {	block, err := aes.NewCipher(l.key)	if err != nil {		return nil, err	}	// 创建 GCM 解密器	gcm, err := cipher.NewGCMWithRandomNonce(block)	if err != nil {		return nil, err	}	// 提取 nonce	nonceSize := gcm.NonceSize()	if len(encrypted) < nonceSize {		return nil, fmt.Errorf("invalid encrypted data")	}	nonce := encrypted[:nonceSize]	ciphertext := encrypted[nonceSize:]	// 使用 GCM 解密	plaintext, err := gcm.Open(nil, nonce, ciphertext, nil)	if err != nil {		return nil, err	}	return plaintext, nil}// isValidDate 检查有效期func (l *License) isValidDate(now, sub time.Time) bool {	if now.After(sub) {		return true // [当前时间] 大于 [密钥创建时间] 时有效	}	// [当前时间] 小于 [密钥创建时间] 并且误差在 1 小时内时有效	return now.Sub(sub).Abs() < 1*time.Hour}// v1Info 实现 EncryptV1 版本的 Infotype v1Info struct {	createdAt time.Time	expiresAt time.Time}func (v *v1Info) CreateAt() time.Time {	return v.createdAt}func (v *v1Info) ExpireAt() time.Time {	return v.expiresAt}func (v *v1Info) Expired() bool {	return time.Now().After(v.expiresAt)}// newV1 创建 EncryptV1 所需明文func (l *License) newV1(expiration time.Time) ([]byte, error) {	now := time.Now().Local().Format(time.RFC3339)	exp := expiration.Local().Format(time.RFC3339)	plaintext := []byte(fmt.Sprintf("1|%s|%s", now, exp))	return plaintext, nil}// statV1 查看 newV1 创建的明文func (l *License) statV1(plaintext []byte) (Info, error) {	clips := bytes.Split(plaintext, []byte("|"))	if len(clips) != 3 {		return nil, ErrLicenseInvalid	}	ver, err := strconv.ParseUint(string(clips[0]), 10, 32)	if err != nil {		return nil, ErrLicenseInvalid	}	if ver != 1 {		return nil, ErrLicenseInvalid	}	// 当前时间	now := time.Now().Local()	// 创建时间	createAt, err := time.ParseInLocation(time.RFC3339, string(clips[1]), time.Local)	if err != nil {		return nil, ErrLicenseInvalid	}	if !l.isValidDate(now, createAt) {		return nil, ErrLicenseInvalid	}	// 过期时间	expAt, err := time.ParseInLocation(time.RFC3339, string(clips[2]), time.Local)	if err != nil {		return nil, ErrLicenseExpired	}	return &v1Info{		createdAt: createAt,		expiresAt: expAt,	}, nil}var (	// key = []byte("2c64d157-a68d-4150-b9a6-ef873f51")	key = []byte("SIMANC-LEGENDARY") // key 16bit = AES-128)var (	globalLicense = &License{key: key})func New(expiration time.Time) (string, error) {	return globalLicense.New(expiration)}func Stat(encryptedKey string) (Info, error) {	return globalLicense.Stat(encryptedKey)}func Open(name string) (Info, error) {	fi, err := os.ReadFile(name)	if err != nil {		return nil, err	}	return globalLicense.Stat(string(fi))}
 |