@notur/sdk 1.1.2 → 1.1.3
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/README.md +31 -0
- package/bin/notur-keygen.js +46 -0
- package/bin/notur-pack.js +61 -2
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -89,6 +89,37 @@ This creates a `.notur` file (tar.gz archive) containing:
|
|
|
89
89
|
|
|
90
90
|
Upload the resulting `.notur` file to your Pterodactyl admin panel at `/admin/notur/extensions`.
|
|
91
91
|
|
|
92
|
+
## Signing Extensions
|
|
93
|
+
|
|
94
|
+
The SDK provides tools for Ed25519 signing of extension archives, compatible with the PHP `notur:keygen` and `notur:export --sign` commands.
|
|
95
|
+
|
|
96
|
+
### Generating a Keypair
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
npx notur-keygen
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
This generates a new Ed25519 keypair and outputs:
|
|
103
|
+
- **Public Key** (64 hex characters) -- Share with panel administrators
|
|
104
|
+
- **Secret Key** (128 hex characters) -- Keep private, used for signing
|
|
105
|
+
|
|
106
|
+
### Signing an Archive
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Using environment variable
|
|
110
|
+
NOTUR_SECRET_KEY=your_secret_key npx notur-pack --sign
|
|
111
|
+
|
|
112
|
+
# Or with --secret-key flag
|
|
113
|
+
npx notur-pack --sign --secret-key your_secret_key
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This produces three files:
|
|
117
|
+
- `vendor-name-1.0.0.notur` -- The extension archive
|
|
118
|
+
- `vendor-name-1.0.0.notur.sha256` -- SHA-256 checksum
|
|
119
|
+
- `vendor-name-1.0.0.notur.sig` -- Ed25519 signature (hex-encoded)
|
|
120
|
+
|
|
121
|
+
The `.sig` file format is compatible with PHP's `SignatureVerifier::verify()` and panels with `require_signatures` enabled.
|
|
122
|
+
|
|
92
123
|
## Build
|
|
93
124
|
|
|
94
125
|
```bash
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* notur-keygen - Generate Ed25519 keypair for signing Notur extensions
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx notur-keygen
|
|
8
|
+
* bunx notur-keygen
|
|
9
|
+
*
|
|
10
|
+
* Generates a new Ed25519 keypair and outputs both keys in hex format.
|
|
11
|
+
* The output format matches the PHP `php artisan notur:keygen` command.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const sodium = require('libsodium-wrappers');
|
|
15
|
+
|
|
16
|
+
async function main() {
|
|
17
|
+
await sodium.ready;
|
|
18
|
+
|
|
19
|
+
const keypair = sodium.crypto_sign_keypair();
|
|
20
|
+
|
|
21
|
+
const publicKeyHex = sodium.to_hex(keypair.publicKey);
|
|
22
|
+
const secretKeyHex = sodium.to_hex(keypair.privateKey);
|
|
23
|
+
|
|
24
|
+
console.log('Ed25519 keypair generated successfully.');
|
|
25
|
+
console.log('');
|
|
26
|
+
console.log('Public Key:');
|
|
27
|
+
console.log(publicKeyHex);
|
|
28
|
+
console.log('');
|
|
29
|
+
console.log('Secret Key:');
|
|
30
|
+
console.log(secretKeyHex);
|
|
31
|
+
console.log('');
|
|
32
|
+
console.log('Store the secret key securely. It is used to sign extension archives.');
|
|
33
|
+
console.log('Add the public key to your panel configuration:');
|
|
34
|
+
console.log('');
|
|
35
|
+
console.log(` NOTUR_PUBLIC_KEY=${publicKeyHex}`);
|
|
36
|
+
console.log('');
|
|
37
|
+
console.log('To sign an archive, set the secret key as an environment variable:');
|
|
38
|
+
console.log('');
|
|
39
|
+
console.log(` NOTUR_SECRET_KEY=${secretKeyHex}`);
|
|
40
|
+
console.log(' npx notur-pack --sign');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
main().catch(err => {
|
|
44
|
+
console.error('Error:', err.message);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
});
|
package/bin/notur-pack.js
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Usage:
|
|
7
7
|
* npx notur-pack [path] # Pack extension at path (default: current dir)
|
|
8
8
|
* npx notur-pack --output foo.notur
|
|
9
|
+
* npx notur-pack --sign # Sign using NOTUR_SECRET_KEY env var
|
|
10
|
+
* npx notur-pack --sign --secret-key xxx
|
|
9
11
|
* bunx notur-pack
|
|
10
12
|
*
|
|
11
13
|
* A .notur file is a tar.gz archive containing:
|
|
@@ -34,11 +36,17 @@ function parseArgs() {
|
|
|
34
36
|
const options = {
|
|
35
37
|
path: '.',
|
|
36
38
|
output: null,
|
|
39
|
+
sign: false,
|
|
40
|
+
secretKey: null,
|
|
37
41
|
};
|
|
38
42
|
|
|
39
43
|
for (let i = 0; i < args.length; i++) {
|
|
40
44
|
if (args[i] === '--output' || args[i] === '-o') {
|
|
41
45
|
options.output = args[++i];
|
|
46
|
+
} else if (args[i] === '--sign' || args[i] === '-s') {
|
|
47
|
+
options.sign = true;
|
|
48
|
+
} else if (args[i] === '--secret-key') {
|
|
49
|
+
options.secretKey = args[++i];
|
|
42
50
|
} else if (!args[i].startsWith('-')) {
|
|
43
51
|
options.path = args[i];
|
|
44
52
|
}
|
|
@@ -123,7 +131,45 @@ function computeChecksums(dir, files) {
|
|
|
123
131
|
return checksums;
|
|
124
132
|
}
|
|
125
133
|
|
|
126
|
-
function
|
|
134
|
+
async function signArchive(archivePath, secretKeyHex) {
|
|
135
|
+
const sodium = require('libsodium-wrappers');
|
|
136
|
+
await sodium.ready;
|
|
137
|
+
|
|
138
|
+
const content = fs.readFileSync(archivePath);
|
|
139
|
+
const secretKey = sodium.from_hex(secretKeyHex);
|
|
140
|
+
const signature = sodium.crypto_sign_detached(content, secretKey);
|
|
141
|
+
|
|
142
|
+
return sodium.to_hex(signature);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function getSecretKey(options) {
|
|
146
|
+
// Check --secret-key argument first, then environment variable
|
|
147
|
+
const secretKey = options.secretKey || process.env.NOTUR_SECRET_KEY;
|
|
148
|
+
|
|
149
|
+
if (!secretKey) {
|
|
150
|
+
console.error('Error: --sign requires a secret key.');
|
|
151
|
+
console.error('');
|
|
152
|
+
console.error('Provide it via:');
|
|
153
|
+
console.error(' NOTUR_SECRET_KEY=xxx npx notur-pack --sign');
|
|
154
|
+
console.error(' npx notur-pack --sign --secret-key xxx');
|
|
155
|
+
console.error('');
|
|
156
|
+
console.error('Generate a keypair with: npx notur-keygen');
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Validate format: Ed25519 secret keys are 64 bytes = 128 hex chars
|
|
161
|
+
if (!/^[0-9a-fA-F]{128}$/.test(secretKey)) {
|
|
162
|
+
console.error('Error: Invalid secret key format.');
|
|
163
|
+
console.error('Expected 128 hexadecimal characters (64 bytes).');
|
|
164
|
+
console.error('');
|
|
165
|
+
console.error('Generate a valid keypair with: npx notur-keygen');
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return secretKey;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function pack(sourceDir, outputPath, options = {}) {
|
|
127
173
|
const resolvedDir = path.resolve(sourceDir);
|
|
128
174
|
|
|
129
175
|
if (!fs.existsSync(resolvedDir)) {
|
|
@@ -174,6 +220,16 @@ function pack(sourceDir, outputPath) {
|
|
|
174
220
|
|
|
175
221
|
console.log(`\nCreated: ${outputFullPath}`);
|
|
176
222
|
console.log(`Checksum: ${archiveChecksum}`);
|
|
223
|
+
|
|
224
|
+
// Sign the archive if requested
|
|
225
|
+
if (options.sign) {
|
|
226
|
+
const secretKey = getSecretKey(options);
|
|
227
|
+
const signature = await signArchive(outputFullPath, secretKey);
|
|
228
|
+
const sigPath = outputFullPath + '.sig';
|
|
229
|
+
fs.writeFileSync(sigPath, signature + '\n');
|
|
230
|
+
console.log(`Signature: ${sigPath}`);
|
|
231
|
+
}
|
|
232
|
+
|
|
177
233
|
console.log(`\nUpload this file to your Pterodactyl admin panel at /admin/notur/extensions`);
|
|
178
234
|
|
|
179
235
|
} finally {
|
|
@@ -186,4 +242,7 @@ function pack(sourceDir, outputPath) {
|
|
|
186
242
|
|
|
187
243
|
// Main
|
|
188
244
|
const options = parseArgs();
|
|
189
|
-
pack(options.path, options.output)
|
|
245
|
+
pack(options.path, options.output, options).catch(err => {
|
|
246
|
+
console.error('Error:', err.message);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notur/sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "Notur Extension Developer SDK",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"access": "public"
|
|
16
16
|
},
|
|
17
17
|
"bin": {
|
|
18
|
-
"notur-pack": "./bin/notur-pack.js"
|
|
18
|
+
"notur-pack": "./bin/notur-pack.js",
|
|
19
|
+
"notur-keygen": "./bin/notur-keygen.js"
|
|
19
20
|
},
|
|
20
21
|
"keywords": [
|
|
21
22
|
"notur",
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"react-dom": "^16.14.0"
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
44
|
+
"libsodium-wrappers": "^0.7.13",
|
|
43
45
|
"yaml": "^2.3.0"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|