@crela/license 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Felix Bonetsmüller
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # @crela/license (Node.js / Electron)
2
+
3
+ License verification SDK for tools on the [Crela](https://crela.io) marketplace.
4
+
5
+ Mandatory for paid tools: the review pipeline looks for a per-tool marker inside your binary (KO-10), and this SDK is what puts it there and checks the licence at startup.
6
+
7
+ ## Quick start
8
+
9
+ For Node.js and Electron projects, let the init tool wire everything up:
10
+
11
+ ```bash
12
+ cd my-tool/
13
+ npx @crela/init
14
+ ```
15
+
16
+ It detects your entry point and bundler, fetches the SDK marker via the API, injects `verifyOrExit()`, and patches your bundler config. After that, just run `npm run build`.
17
+
18
+ ## How it works
19
+
20
+ The SDK never prompts for a licence key. It reads a JWT signed by the Crela launcher — either from the environment variable `CRELA_LICENSE_JWT` or from a cache file — and verifies it **offline** against an Ed25519 public key. No network call happens.
21
+
22
+ Activation, heartbeat and device management are handled entirely by the Crela launcher, so your tool does not need its own licence UI. Your integration is one call:
23
+
24
+ ```ts
25
+ import { verifyOrExit } from '@crela/license'
26
+
27
+ verifyOrExit('my-tool', process.env.CRELA_SDK_MARKER!)
28
+ ```
29
+
30
+ ## Manual build-time setup
31
+
32
+ If you do not use `npx @crela/init`, set the variables yourself before building:
33
+
34
+ ```bash
35
+ # Marker token from the creator dashboard:
36
+ export CRELA_SDK_MARKER=CRELA_SDKv2_xxxxxxxxxxxxxx
37
+
38
+ # Ed25519 public key (64 hex chars) for JWT verification:
39
+ export CRELA_LICENSE_PUBKEY_HEX=abcdef...
40
+ ```
41
+
42
+ With esbuild:
43
+ ```bash
44
+ esbuild main.ts \
45
+ --define:CRELA_SDK_MARKER=\"$CRELA_SDK_MARKER\" \
46
+ --define:CRELA_LICENSE_PUBKEY_HEX=\"$CRELA_LICENSE_PUBKEY_HEX\"
47
+ ```
48
+
49
+ With Webpack:
50
+ ```js
51
+ new webpack.DefinePlugin({
52
+ CRELA_SDK_MARKER: JSON.stringify(process.env.CRELA_SDK_MARKER),
53
+ CRELA_LICENSE_PUBKEY_HEX: JSON.stringify(process.env.CRELA_LICENSE_PUBKEY_HEX),
54
+ })
55
+ ```
56
+
57
+ The marker has to survive bundling as a literal string — reading it from a config file at runtime does not satisfy KO-10.
58
+
59
+ ## Usage
60
+
61
+ ```ts
62
+ import { verifyOrExit } from '@crela/license'
63
+
64
+ // In electron main.ts, before app.whenReady():
65
+ verifyOrExit('my-tool', CRELA_SDK_MARKER)
66
+
67
+ app.whenReady().then(createWindow)
68
+ ```
69
+
70
+ On failure: a message on stderr and `process.exit(0xC1)`.
71
+
72
+ ## Verification order
73
+
74
+ 1. `CRELA_DEV_MODE=1` env → `isDev=true` claims, no verification
75
+ 2. `CRELA_LICENSE_JWT` env → verify token
76
+ 3. Cache file `<DATA_LOCAL_DIR>/crela/licenses/<slug>.jwt` → verify token
77
+ 4. Nothing found → `LicenseError` with code `NOT_LAUNCHED_FROM_CRELA`
78
+
79
+ ## Advanced
80
+
81
+ ```ts
82
+ import { LicenseVerifier } from '@crela/license'
83
+
84
+ const verifier = new LicenseVerifier({
85
+ toolSlug: 'my-tool',
86
+ markerToken: CRELA_SDK_MARKER,
87
+ pubkeyHex: CRELA_LICENSE_PUBKEY_HEX,
88
+ })
89
+
90
+ try {
91
+ const claims = verifier.verify()
92
+ console.log(`Licence valid, exp=${claims.exp}`)
93
+ } catch (e) {
94
+ console.error(`Licence invalid: ${e.message}`)
95
+ process.exit(1)
96
+ }
97
+ ```
98
+
99
+ ## Other languages
100
+
101
+ Crela ships a ready-made SDK for Node.js/Electron and for [Rust/Tauri](https://crates.io/crates/crela-license). For anything else (.NET, Java, Python, C++, Go) there is no SDK — embed the marker string as a compile-time constant and the review will accept it. Enforcing the licence at runtime is then up to you. See the [creator guidelines](https://crela.io/creator-guidelines#sdk).
102
+
103
+ ## Tests
104
+
105
+ ```bash
106
+ npm test
107
+ ```
108
+
109
+ ## Licence
110
+
111
+ MIT
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Crela License SDK v3 - Node.js / Electron
3
+ *
4
+ * Pflicht-Integration fuer Tools auf dem Crela-Marktplatz (paid + free).
5
+ * Die SDK liest ein vom Crela-Launcher signiertes JWT entweder aus der
6
+ * Umgebungsvariable `CRELA_LICENSE_JWT` oder aus einer gemeinsamen
7
+ * Cache-Datei und verifiziert es offline gegen einen einkompilierten
8
+ * Ed25519-Public-Key. Es findet kein Netzwerk-Aufruf statt.
9
+ *
10
+ * Typische Nutzung in Electron-`main.ts`:
11
+ *
12
+ * import { verifyOrExit, CRELA_SDK_MARKER } from '@crela/license'
13
+ * verifyOrExit('mein-tool', CRELA_SDK_MARKER)
14
+ *
15
+ * Marker und Public-Key werden ueblicherweise via Bundler-Define beim
16
+ * Build injiziert oder aus einer build-time-generierten Datei gelesen.
17
+ */
18
+ /** Prefix des v2-Markers; der vollstaendige Token kommt vom Creator-Dashboard. */
19
+ export declare const CRELA_SDK_MARKER_PREFIX: "CRELA_SDKv2_";
20
+ export declare const CRELA_SDK_MARKER_CONST: string | undefined;
21
+ export declare class LicenseError extends Error {
22
+ code: LicenseErrorCode;
23
+ constructor(code: LicenseErrorCode, message: string);
24
+ }
25
+ export type LicenseErrorCode = 'NOT_LAUNCHED_FROM_CRELA' | 'INVALID_JWT_FORMAT' | 'INVALID_SIGNATURE' | 'EXPIRED' | 'WRONG_TOOL' | 'WRONG_DEVICE' | 'MISSING_CLAIM' | 'INVALID_PUBKEY' | 'INVALID_MARKER';
26
+ export interface LicenseClaims {
27
+ /** License-ID (UUID) */
28
+ sub: string;
29
+ /** Tool-Slug */
30
+ tool: string;
31
+ /** Device-Fingerprint */
32
+ fp: string;
33
+ /** Unix-Timestamp Ausstellung */
34
+ iat: number;
35
+ /** Unix-Timestamp Ablauf */
36
+ exp: number;
37
+ /** Grace-Period in Sekunden */
38
+ grace: number;
39
+ /** True wenn CRELA_DEV_MODE=1 (Verifikation uebersprungen) */
40
+ isDev: boolean;
41
+ }
42
+ export interface VerifierOptions {
43
+ /** Tool-Slug, muss mit JWT-Claim `tool` matchen */
44
+ toolSlug: string;
45
+ /** Marker-Token aus dem Creator-Dashboard. Muss mit CRELA_SDKv2_ beginnen. */
46
+ markerToken: string;
47
+ /** Ed25519-Public-Key (32 Bytes hex). Default: BUILD_TIME_PUBKEY_HEX-Konstante. */
48
+ pubkeyHex?: string;
49
+ /** Cache-Pfad ueberschreiben (Default: <DATA_LOCAL>/crela/licenses/<slug>.jwt). */
50
+ cachePath?: string;
51
+ /**
52
+ * Dev-Mode (`CRELA_DEV_MODE=1`) zulassen. Default: FALSE. Muss fuer lokale
53
+ * Entwicklung explizit aktiviert werden; ausgelieferte Tools lassen es aus,
54
+ * damit Endnutzer die Lizenzpruefung nicht per Umgebungsvariable umgehen.
55
+ */
56
+ allowDevMode?: boolean;
57
+ /**
58
+ * Lokalen Geraete-Fingerprint ueberschreiben (nur fuer Tests). Production
59
+ * nutzt die machine-id (node-machine-id, original) - dieselbe Quelle wie der
60
+ * Launcher.
61
+ */
62
+ deviceFp?: string;
63
+ }
64
+ export declare class LicenseVerifier {
65
+ private readonly toolSlug;
66
+ private readonly pubkeyHex;
67
+ private readonly cachePath;
68
+ private readonly allowDevMode;
69
+ private readonly deviceFp;
70
+ constructor(opts: VerifierOptions);
71
+ /**
72
+ * Lokaler Geraete-Fingerprint. Quelle ist node-machine-id (original) - die
73
+ * MachineGuid/IOPlatformUUID/machine-id, exakt das, was der Launcher
74
+ * (machine-uid 0.5) ins JWT schreibt. Ein gesetztes Override hat Vorrang
75
+ * (Tests). Liefert null, wenn die ID nicht ermittelbar ist.
76
+ */
77
+ private resolveDeviceFp;
78
+ verify(): LicenseClaims;
79
+ /** Bei Fehler: stderr-Meldung + process.exit(0xC1). */
80
+ verifyOrExit(): LicenseClaims;
81
+ private resolveToken;
82
+ private resolveCachePath;
83
+ private readCacheFile;
84
+ private devClaims;
85
+ private verifyJwt;
86
+ }
87
+ /** Convenience: verifiziert und exitet bei Fehler. */
88
+ export declare function verifyOrExit(toolSlug: string, markerToken: string, pubkeyHex?: string): LicenseClaims;
89
+ /** Fingerprint-Helfer (oeffentlich fuer Apps die ihn loggen). */
90
+ export declare function deviceFingerprint(): string;
91
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AASH,kFAAkF;AAClF,eAAO,MAAM,uBAAuB,EAAG,cAAuB,CAAA;AAY9D,eAAO,MAAM,sBAAsB,EAAE,MAAM,GAAG,SAC0B,CAAA;AAIxE,qBAAa,YAAa,SAAQ,KAAK;IAClB,IAAI,EAAE,gBAAgB;gBAAtB,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM;CAI3D;AAED,MAAM,MAAM,gBAAgB,GACxB,yBAAyB,GACzB,oBAAoB,GACpB,mBAAmB,GACnB,SAAS,GACT,YAAY,GACZ,cAAc,GACd,eAAe,GACf,gBAAgB,GAChB,gBAAgB,CAAA;AAEpB,MAAM,WAAW,aAAa;IAC5B,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,iCAAiC;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAA;IACnB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAiBD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAoB;gBAEjC,IAAI,EAAE,eAAe;IAYjC;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IAavB,MAAM,IAAI,aAAa;IAoCvB,uDAAuD;IACvD,YAAY,IAAI,aAAa;IAW7B,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,SAAS;CAgDlB;AAED,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,aAAa,CAErG;AAED,iEAAiE;AACjE,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C"}
package/dist/index.js ADDED
@@ -0,0 +1,254 @@
1
+ /**
2
+ * Crela License SDK v3 - Node.js / Electron
3
+ *
4
+ * Pflicht-Integration fuer Tools auf dem Crela-Marktplatz (paid + free).
5
+ * Die SDK liest ein vom Crela-Launcher signiertes JWT entweder aus der
6
+ * Umgebungsvariable `CRELA_LICENSE_JWT` oder aus einer gemeinsamen
7
+ * Cache-Datei und verifiziert es offline gegen einen einkompilierten
8
+ * Ed25519-Public-Key. Es findet kein Netzwerk-Aufruf statt.
9
+ *
10
+ * Typische Nutzung in Electron-`main.ts`:
11
+ *
12
+ * import { verifyOrExit, CRELA_SDK_MARKER } from '@crela/license'
13
+ * verifyOrExit('mein-tool', CRELA_SDK_MARKER)
14
+ *
15
+ * Marker und Public-Key werden ueblicherweise via Bundler-Define beim
16
+ * Build injiziert oder aus einer build-time-generierten Datei gelesen.
17
+ */
18
+ import { readFileSync } from 'node:fs';
19
+ import { existsSync } from 'node:fs';
20
+ import { join } from 'node:path';
21
+ import { homedir, hostname, platform } from 'node:os';
22
+ import { createRequire } from 'node:module';
23
+ import { createHash, createPublicKey, verify as cryptoVerify } from 'node:crypto';
24
+ /** Prefix des v2-Markers; der vollstaendige Token kommt vom Creator-Dashboard. */
25
+ export const CRELA_SDK_MARKER_PREFIX = 'CRELA_SDKv2_';
26
+ export const CRELA_SDK_MARKER_CONST = typeof CRELA_SDK_MARKER !== 'undefined' ? CRELA_SDK_MARKER : undefined;
27
+ const SKEW_SECONDS = 300; // 5 Minuten Clock-Skew-Toleranz
28
+ export class LicenseError extends Error {
29
+ code;
30
+ constructor(code, message) {
31
+ super(message);
32
+ this.code = code;
33
+ this.name = 'LicenseError';
34
+ }
35
+ }
36
+ /**
37
+ * Production-Public-Key fuer Ed25519-JWT-Verifikation gegen crela.io.
38
+ * Pubkey aus dem `x`-Feld der Production CRELA_LICENSE_SIGNING_JWK,
39
+ * base64url-decoded und als 32-Byte-Hex. Wird als Default genutzt, kann
40
+ * via Bundler-Define (CRELA_LICENSE_PUBKEY_HEX) ueberschrieben werden
41
+ * (z.B. fuer Self-Hosted-Crela-Instanzen).
42
+ */
43
+ const PRODUCTION_PUBKEY_HEX = 'c6c37639c659cb9168d6af510d9696d141d980c5145212232f800b21a8210231';
44
+ const BUILD_TIME_PUBKEY_HEX = typeof CRELA_LICENSE_PUBKEY_HEX !== 'undefined' && CRELA_LICENSE_PUBKEY_HEX.length === 64
45
+ ? CRELA_LICENSE_PUBKEY_HEX
46
+ : PRODUCTION_PUBKEY_HEX;
47
+ export class LicenseVerifier {
48
+ toolSlug;
49
+ pubkeyHex;
50
+ cachePath;
51
+ allowDevMode;
52
+ deviceFp;
53
+ constructor(opts) {
54
+ if (!opts.toolSlug)
55
+ throw new LicenseError('MISSING_CLAIM', 'toolSlug ist erforderlich');
56
+ if (!opts.markerToken || !opts.markerToken.startsWith(CRELA_SDK_MARKER_PREFIX)) {
57
+ throw new LicenseError('INVALID_MARKER', `markerToken muss mit "${CRELA_SDK_MARKER_PREFIX}" beginnen`);
58
+ }
59
+ this.toolSlug = opts.toolSlug;
60
+ this.pubkeyHex = opts.pubkeyHex ?? BUILD_TIME_PUBKEY_HEX;
61
+ this.cachePath = opts.cachePath;
62
+ this.allowDevMode = opts.allowDevMode ?? false;
63
+ this.deviceFp = opts.deviceFp;
64
+ }
65
+ /**
66
+ * Lokaler Geraete-Fingerprint. Quelle ist node-machine-id (original) - die
67
+ * MachineGuid/IOPlatformUUID/machine-id, exakt das, was der Launcher
68
+ * (machine-uid 0.5) ins JWT schreibt. Ein gesetztes Override hat Vorrang
69
+ * (Tests). Liefert null, wenn die ID nicht ermittelbar ist.
70
+ */
71
+ resolveDeviceFp() {
72
+ if (this.deviceFp !== undefined)
73
+ return this.deviceFp;
74
+ try {
75
+ const mod = createRequire(import.meta.url)('node-machine-id');
76
+ const id = mod.machineIdSync(true);
77
+ return id && id.length > 0 ? id : null;
78
+ }
79
+ catch {
80
+ return null;
81
+ }
82
+ }
83
+ verify() {
84
+ if (this.allowDevMode && process.env.CRELA_DEV_MODE === '1') {
85
+ return this.devClaims();
86
+ }
87
+ const token = this.resolveToken();
88
+ const claims = this.verifyJwt(token);
89
+ if (claims.tool !== this.toolSlug) {
90
+ throw new LicenseError('WRONG_TOOL', `JWT ist fuer "${claims.tool}" ausgestellt, erwartet "${this.toolSlug}"`);
91
+ }
92
+ const now = nowSeconds();
93
+ if (claims.exp + SKEW_SECONDS < now) {
94
+ throw new LicenseError('EXPIRED', 'JWT ist abgelaufen');
95
+ }
96
+ // Geraetebindung: der fp-Claim muss zur lokalen Maschine passen, sonst
97
+ // laesst sich ein gueltiges Token einfach auf beliebig viele Rechner
98
+ // kopieren. Quelle ist node-machine-id (original) - dieselbe ID, die der
99
+ // Launcher (machine-uid) ins JWT schreibt. Fail-closed, wenn die ID nicht
100
+ // ermittelbar ist (ein vom Launcher gestartetes Tool hat immer eine).
101
+ const localFp = this.resolveDeviceFp();
102
+ if (localFp === null || localFp.toLowerCase() !== claims.fp.toLowerCase()) {
103
+ throw new LicenseError('WRONG_DEVICE', 'JWT ist an ein anderes Geraet gebunden (Lizenz wurde auf eine fremde Maschine kopiert)');
104
+ }
105
+ return claims;
106
+ }
107
+ /** Bei Fehler: stderr-Meldung + process.exit(0xC1). */
108
+ verifyOrExit() {
109
+ try {
110
+ return this.verify();
111
+ }
112
+ catch (e) {
113
+ const msg = e instanceof Error ? e.message : String(e);
114
+ process.stderr.write(`crela-license: ${msg}\n`);
115
+ process.stderr.write('Bitte starte diese App ueber den Crela Launcher.\n');
116
+ process.exit(0xc1);
117
+ }
118
+ }
119
+ resolveToken() {
120
+ const envToken = process.env.CRELA_LICENSE_JWT;
121
+ if (envToken && envToken.length > 0)
122
+ return envToken;
123
+ const cached = this.readCacheFile();
124
+ if (cached)
125
+ return cached;
126
+ throw new LicenseError('NOT_LAUNCHED_FROM_CRELA', 'Kein Lizenz-Token gefunden (weder env-var noch Cache-File). Bitte starte diese App ueber den Crela Launcher.');
127
+ }
128
+ resolveCachePath() {
129
+ if (this.cachePath)
130
+ return this.cachePath;
131
+ return join(dataLocalDir(), 'crela', 'licenses', `${this.toolSlug}.jwt`);
132
+ }
133
+ readCacheFile() {
134
+ const path = this.resolveCachePath();
135
+ if (!existsSync(path))
136
+ return null;
137
+ try {
138
+ const raw = readFileSync(path, 'utf-8').trim();
139
+ return raw.length > 0 ? raw : null;
140
+ }
141
+ catch {
142
+ return null;
143
+ }
144
+ }
145
+ devClaims() {
146
+ const now = nowSeconds();
147
+ return {
148
+ sub: 'dev-mode',
149
+ tool: this.toolSlug,
150
+ fp: 'dev-fingerprint',
151
+ iat: now,
152
+ exp: now + 86_400,
153
+ grace: 86_400,
154
+ isDev: true,
155
+ };
156
+ }
157
+ verifyJwt(token) {
158
+ if (!this.pubkeyHex || this.pubkeyHex.length !== 64) {
159
+ throw new LicenseError('INVALID_PUBKEY', 'Ed25519-Public-Key fehlt oder ist ungueltig');
160
+ }
161
+ const parts = token.split('.');
162
+ if (parts.length !== 3) {
163
+ throw new LicenseError('INVALID_JWT_FORMAT', 'JWT-Format ungueltig');
164
+ }
165
+ let payloadBytes;
166
+ let sigBytes;
167
+ try {
168
+ payloadBytes = base64UrlDecode(parts[1]);
169
+ sigBytes = base64UrlDecode(parts[2]);
170
+ }
171
+ catch {
172
+ throw new LicenseError('INVALID_JWT_FORMAT', 'JWT-Base64-Decode fehlgeschlagen');
173
+ }
174
+ if (sigBytes.length !== 64) {
175
+ throw new LicenseError('INVALID_JWT_FORMAT', `JWT-Signatur falsche Laenge: ${sigBytes.length}`);
176
+ }
177
+ const signingInput = Buffer.from(`${parts[0]}.${parts[1]}`);
178
+ const pubkey = ed25519PublicKey(this.pubkeyHex);
179
+ const ok = cryptoVerify(null, signingInput, pubkey, sigBytes);
180
+ if (!ok) {
181
+ throw new LicenseError('INVALID_SIGNATURE', 'JWT-Signatur konnte nicht verifiziert werden');
182
+ }
183
+ let raw;
184
+ try {
185
+ raw = JSON.parse(payloadBytes.toString('utf-8'));
186
+ }
187
+ catch {
188
+ throw new LicenseError('INVALID_JWT_FORMAT', 'JWT-Payload ist kein gueltiges JSON');
189
+ }
190
+ return {
191
+ sub: requireString(raw, 'sub'),
192
+ tool: requireString(raw, 'tool'),
193
+ fp: requireString(raw, 'fp'),
194
+ iat: typeof raw.iat === 'number' ? raw.iat : 0,
195
+ exp: requireNumber(raw, 'exp'),
196
+ grace: typeof raw.grace === 'number' ? raw.grace : 0,
197
+ isDev: false,
198
+ };
199
+ }
200
+ }
201
+ /** Convenience: verifiziert und exitet bei Fehler. */
202
+ export function verifyOrExit(toolSlug, markerToken, pubkeyHex) {
203
+ return new LicenseVerifier({ toolSlug, markerToken, pubkeyHex }).verifyOrExit();
204
+ }
205
+ /** Fingerprint-Helfer (oeffentlich fuer Apps die ihn loggen). */
206
+ export function deviceFingerprint() {
207
+ const h = createHash('sha256');
208
+ try {
209
+ h.update(hostname());
210
+ }
211
+ catch { /* ignore */ }
212
+ // Note: kein MAC-Fallback in Node-SDK; Apps die exakte FP brauchen rufen
213
+ // direkt die node-mac-address lib.
214
+ return h.digest('hex');
215
+ }
216
+ function base64UrlDecode(s) {
217
+ const pad = s.length % 4 === 0 ? '' : '='.repeat(4 - (s.length % 4));
218
+ return Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/') + pad, 'base64');
219
+ }
220
+ function ed25519PublicKey(hex) {
221
+ // SubjectPublicKeyInfo DER prefix fuer Ed25519: 302a300506032b6570032100
222
+ const prefix = Buffer.from('302a300506032b6570032100', 'hex');
223
+ const keyBytes = Buffer.from(hex, 'hex');
224
+ const spki = Buffer.concat([prefix, keyBytes]);
225
+ return createPublicKey({ key: spki, format: 'der', type: 'spki' });
226
+ }
227
+ function dataLocalDir() {
228
+ const p = platform();
229
+ if (p === 'win32') {
230
+ return process.env.LOCALAPPDATA ?? join(homedir(), 'AppData', 'Local');
231
+ }
232
+ if (p === 'darwin') {
233
+ return join(homedir(), 'Library', 'Application Support');
234
+ }
235
+ return process.env.XDG_DATA_HOME ?? join(homedir(), '.local', 'share');
236
+ }
237
+ function nowSeconds() {
238
+ return Math.floor(Date.now() / 1000);
239
+ }
240
+ function requireString(o, key) {
241
+ const v = o[key];
242
+ if (typeof v !== 'string' || v.length === 0) {
243
+ throw new LicenseError('MISSING_CLAIM', `JWT-Claim "${key}" fehlt oder ist kein String`);
244
+ }
245
+ return v;
246
+ }
247
+ function requireNumber(o, key) {
248
+ const v = o[key];
249
+ if (typeof v !== 'number') {
250
+ throw new LicenseError('MISSING_CLAIM', `JWT-Claim "${key}" fehlt oder ist keine Number`);
251
+ }
252
+ return v;
253
+ }
254
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@crela/license",
3
+ "version": "1.0.0",
4
+ "description": "License verification SDK for Crela marketplace tools (Node.js / Electron). Reads JWT from launcher-injected env var or cache file, verifies offline via Ed25519.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "README.md",
18
+ "LICENSE"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "test": "vitest run",
23
+ "prepublishOnly": "npm run build && npm test"
24
+ },
25
+ "engines": {
26
+ "node": ">=18"
27
+ },
28
+ "keywords": [
29
+ "crela",
30
+ "license",
31
+ "drm",
32
+ "marketplace",
33
+ "electron"
34
+ ],
35
+ "license": "MIT",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "homepage": "https://crela.io/docs#sdk-marker",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/Boniihhh/Crela",
43
+ "directory": "packages/sdk-node"
44
+ },
45
+ "devDependencies": {
46
+ "typescript": "^5.5.0",
47
+ "vitest": "^4.1.7"
48
+ },
49
+ "dependencies": {
50
+ "node-machine-id": "^1.1.12"
51
+ }
52
+ }