(tested on version 1.11.5)
package main import ( "encoding/base64" "encoding/json" "fmt" "golang.org/x/crypto/ssh" "log" "time" ) var pubKey = `ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC4dK1cTSWe/6IkGpB8Xqc8YEFUKPLDFvl37Or4WacQhIhH+yb7dKAae0t866/ViZHf6qjwuWD4iXhmmQm5hDS9yiGGjEzmovhW8PiuJ7qhdkuliBbWmn5knOT9A4b9QSNubsVhk5qGExbK9hoFLR/97fqeCsuy67jvhXABPh7fBQ==` var lic = "eyJsaWNlbnNlIjoie1wibmFtZVwiOlwiSm9obm55IFdhbGtlclwiLFwidHlwZVwiOlwicGVyc29uYWxcIixcInN0YXJ0XCI6XCIyMDE5LTAyLTI2VDEzOjUxOjIzKzAyOjAwXCIsXCJlbmRcIjpudWxsLFwiYXJ0aWNsZXNcIjpbe1wibmFtZVwiOlwiUFJPRElELXRlc3RcIixcInBheWxvYWRcIjpudWxsfV19Iiwic2lnbmF0dXJlIjp7IkZvcm1hdCI6InNzaC1yc2EiLCJCbG9iIjoiSFhqejE5bThuZktOMGtrMitkMHFFcGRWcUtDbWgvQytBdXNkMTJWditITE54YitiUWcwS1gvUndpaFA3WUdDRUlrNHlLbEZCZUl6Umk3VlQvaU1xNEFkaWY4Q3VQVzBUQWJLcGN4TDg1RS94YVFlM2ZJT0pteUNSSEFIbXIxdk56TUs2eDR2SC9DbFRuZVlveEhlTndNV2hmWG0yUURBUy85NHMrekgxLzhJPSJ9fQ==" type signed struct { License string `json:"license"` Signature ssh.Signature `json:"signature"` } type article struct { Name string `json:"name"` } type license struct { LicensedTo string `json:"name"` LicType string `json:"type"` Start time.Time `json:"start"` End *time.Time `json:"end"` Articles []article `json:"articles"` } func checkLicense(prodId, pubKey, licString string) *license { pub, _, _, _, e := ssh.ParseAuthorizedKey([]byte(pubKey)) die(e) var sl signed bytes, e := base64.StdEncoding.DecodeString(licString) die(e) e = json.Unmarshal(bytes, &sl) die(e) e = pub.Verify([]byte(sl.License), &sl.Signature) die(e) var lic1 license e = json.Unmarshal([]byte(sl.License), &lic1) if e == nil { if time.Now().After(lic1.Start) { if lic1.End == nil || time.Now().Before(*lic1.End) { for _, a := range lic1.Articles { if prodId == a.Name { return &lic1 } } } } } return nil } func main() { const prodId = "PRODID-test" lic1 := checkLicense(prodId, pubKey, lic) fmt.Printf("License verified: %t\n", lic1 != nil) if lic1 != nil { fmt.Printf("You have %s license for product \"%s\" registered to %s.\n", lic1.LicType, prodId, lic1.LicensedTo) } } func die(e error) { if e != nil { log.Fatal(e) } }
(tested on version 3.6.4)
import base64 import json import re from datetime import datetime, timezone # pycryptodome from Crypto.Hash import SHA256 from Crypto.PublicKey import RSA from Crypto.Signature import PKCS1_v1_5 pub_key = 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC4dK1cTSWe/6IkGpB8Xqc8YEFUKPLDFvl37Or4WacQhIhH+yb7dKAae0t866/ViZHf6qjwuWD4iXhmmQm5hDS9yiGGjEzmovhW8PiuJ7qhdkuliBbWmn5knOT9A4b9QSNubsVhk5qGExbK9hoFLR/97fqeCsuy67jvhXABPh7fBQ==' lic_str = 'eyJsaWNlbnNlIjoie1wibmFtZVwiOlwiSm9obm55IFdhbGtlclwiLFwidHlwZVwiOlwicGVyc29uYWxcIixcInN0YXJ0XCI6XCIyMDE5LTAyLTI2VDEzOjUxOjIzKzAyOjAwXCIsXCJlbmRcIjpudWxsLFwiYXJ0aWNsZXNcIjpbe1wibmFtZVwiOlwiUFJPRElELXRlc3RcIixcInBheWxvYWRcIjpudWxsfV19Iiwic2lnbmF0dXJlIjp7IkZvcm1hdCI6InNzaC1yc2EiLCJCbG9iIjoiSFhqejE5bThuZktOMGtrMitkMHFFcGRWcUtDbWgvQytBdXNkMTJWditITE54YitiUWcwS1gvUndpaFA3WUdDRUlrNHlLbEZCZUl6Umk3VlQvaU1xNEFkaWY4Q3VQVzBUQWJLcGN4TDg1RS94YVFlM2ZJT0pteUNSSEFIbXIxdk56TUs2eDR2SC9DbFRuZVlveEhlTndNV2hmWG0yUURBUy85NHMrekgxLzhJPSJ9fQ==' def date_decode(s): if s is None: return None pat = re.compile(r'^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\+\d{2}):(\d{2})$', re.M | re.I) m = pat.match(s) if m is not None: s = m.group(1) + m.group(2) return datetime.strptime(s, "%Y-%m-%dT%H:%M:%S%z") return s def check_license(prod_id, pub_key, lic_string): sl = json.loads(base64.b64decode(lic_string)) rsakey = RSA.importKey(pub_key) signer = PKCS1_v1_5.new(rsakey) digest = SHA256.new() digest.update(bytes(sl['license'], 'utf8')) sign = sl['signature']['Blob'] try: signer.verify(digest, bytes(sign, 'utf8')) except ValueError: return None lic = json.loads(sl['license']) now = datetime.now(tz=timezone.utc) if now > date_decode(lic['start']): if lic['end'] is None or now < date_decode(lic['end']): arts = lic['articles'] for i in range(len(arts)): a = arts[i] if prod_id == a['name']: return lic return None prod_id = "PRODID-test" lic = check_license(prod_id, pub_key, lic_str) print("License verified: %s" % (lic is not None)) if lic is not None: print("You have %s license for product \"%s\" registered to %s.\n" % (lic['type'], prod_id, lic['name']))
(tested on version 7.3)
<?php // phpseclib 1.0 include('Crypt/RSA.php'); $pub_key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC4dK1cTSWe/6IkGpB8Xqc8YEFUKPLDFvl37Or4WacQhIhH+yb7dKAae0t866/ViZHf6qjwuWD4iXhmmQm5hDS9yiGGjEzmovhW8PiuJ7qhdkuliBbWmn5knOT9A4b9QSNubsVhk5qGExbK9hoFLR/97fqeCsuy67jvhXABPh7fBQ=="; $lic_str = "eyJsaWNlbnNlIjoie1wibmFtZVwiOlwiSm9obm55IFdhbGtlclwiLFwidHlwZVwiOlwicGVyc29uYWxcIixcInN0YXJ0XCI6XCIyMDE5LTAyLTI2VDEzOjUxOjIzKzAyOjAwXCIsXCJlbmRcIjpudWxsLFwiYXJ0aWNsZXNcIjpbe1wibmFtZVwiOlwiUFJPRElELXRlc3RcIixcInBheWxvYWRcIjpudWxsfV19Iiwic2lnbmF0dXJlIjp7IkZvcm1hdCI6InNzaC1yc2EiLCJCbG9iIjoiSFhqejE5bThuZktOMGtrMitkMHFFcGRWcUtDbWgvQytBdXNkMTJWditITE54YitiUWcwS1gvUndpaFA3WUdDRUlrNHlLbEZCZUl6Umk3VlQvaU1xNEFkaWY4Q3VQVzBUQWJLcGN4TDg1RS94YVFlM2ZJT0pteUNSSEFIbXIxdk56TUs2eDR2SC9DbFRuZVlveEhlTndNV2hmWG0yUURBUy85NHMrekgxLzhJPSJ9fQ=="; function check_license($prod_id, $pub_key, $lic_string) { $sl = json_decode(base64_decode($lic_string)); $rsa = new Crypt_RSA(); $rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_OPENSSH); $key_created = $rsa->loadKey($pub_key); if (!$key_created) return null; $rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1); $signature = base64_decode($sl->signature->Blob); $verified = $rsa->verify($sl->license, $signature); if (!$verified) return null; $lic = json_decode($sl->license); $now = time(); if ($now > strtotime($lic->start)) { if ($lic->end === null || $now < strtotime($lic->end)) { $arts = $lic->articles; foreach($arts as $a) { if ($prod_id == $a->name) return $lic; } } } return null; } $prod_id = "PRODID-test"; $lic = check_license($prod_id, $pub_key, $lic_str); echo "License verified: " . ($lic !== null ? "true" : "false") . "\n"; if ($lic !== null) echo "You have " . $lic->type . " license for product \"$prod_id\" registered to " . $lic->name . ".\n";