codepi-package 0.0.0-stage → 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/README.md CHANGED
@@ -1,3 +1,38 @@
1
- # Temporary Holding Version
1
+ # Code[{π*}]
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Secure encryption toolkit using AES-256-GCM.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g codepi
9
+
10
+ ## Encrypt
11
+
12
+ codepi encrypt "Hello" "1234"
13
+
14
+ ## Decrypt
15
+
16
+ codepi decrypt "[{...}]" "1234"
17
+
18
+ ## Validate
19
+
20
+ codepi validate "[{...}]"
21
+
22
+ ## Features
23
+
24
+ - AES-256-GCM
25
+ - Random nonce
26
+ - Password authentication
27
+ - [{...}] format
28
+ - .Codepack[{}] validation
29
+ - Browser encryption
30
+ - No code execution during validation
31
+
32
+ ## License
33
+
34
+ MIT
35
+
36
+ ## GitHub
37
+
38
+ https://github.com/ScriptsSoftware/codepi
package/bin/codepi.js ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ const {encrypt}=require('../lib/encrypt');
3
+ const {decrypt}=require('../lib/decrypt');
4
+ const {validateCodepack}=require('../lib/codepack');
5
+
6
+ const [,,cmd,...a]=process.argv;
7
+ const VERSION='1.0.0';
8
+
9
+ try{
10
+ if(cmd==='--version'||cmd==='-v'){console.log(`Code[{π*}] v${VERSION}`);process.exit(0)}
11
+ if(cmd==='encrypt'){
12
+ if(!a[0]||!a[1])throw Error('Usage: codepi encrypt "message" "password"');
13
+ console.log(encrypt(a[0],a[1]));
14
+ }else if(cmd==='decrypt'){
15
+ if(!a[0]||!a[1])throw Error('Usage: codepi decrypt "[{...}]" "password"');
16
+ console.log(decrypt(a[0],a[1]));
17
+ }else if(cmd==='validate'){
18
+ if(!a[0])throw Error('Usage: codepi validate "[{...}]"');
19
+ console.log(validateCodepack(a[0]));
20
+ }else{
21
+ console.log('Code[{π*}]');
22
+ console.log('codepi encrypt "message" "password"');
23
+ console.log('codepi decrypt "[{...}]" "password"');
24
+ console.log('codepi validate "[{...}]"');
25
+ }
26
+ }catch(error){
27
+ console.error('Error:',error.message);
28
+ process.exit(1);
29
+ }
Binary file
@@ -0,0 +1,36 @@
1
+ const FORMAT = '[{...}]';
2
+
3
+ function isCodepack(value) {
4
+ if (typeof value !== 'string') return false;
5
+ if (!value.startsWith('[{') || !value.endsWith('}]')) return false;
6
+
7
+ const data = value.slice(2, -2);
8
+
9
+ if (!data || !/^[A-Za-z0-9_-]+$/.test(data)) {
10
+ return false;
11
+ }
12
+
13
+ return true;
14
+ }
15
+
16
+ function validateCodepack(value) {
17
+ if (!isCodepack(value)) {
18
+ return {
19
+ valid: false,
20
+ safe: false,
21
+ status: 'INVALID'
22
+ };
23
+ }
24
+
25
+ return {
26
+ valid: true,
27
+ safe: true,
28
+ status: 'VALID'
29
+ };
30
+ }
31
+
32
+ module.exports = {
33
+ FORMAT,
34
+ isCodepack,
35
+ validateCodepack
36
+ };
package/lib/decrypt.js ADDED
@@ -0,0 +1,67 @@
1
+ const crypto = require('crypto');
2
+
3
+ const PI = '3.14159265358979323846264338327950288419716939937510';
4
+ const FORMAT = `π+[${PI}]{}\/`;
5
+
6
+ function deriveKey(password) {
7
+ return crypto
8
+ .createHash('sha256')
9
+ .update(FORMAT + password, 'utf8')
10
+ .digest();
11
+ }
12
+
13
+ function decrypt(packet, password) {
14
+ if (typeof packet !== 'string') {
15
+ throw new TypeError('Codepack must be a string');
16
+ }
17
+
18
+ if (!packet.startsWith('[{') || !packet.endsWith('}]')) {
19
+ throw new Error('Invalid Codepack format');
20
+ }
21
+
22
+ if (typeof password !== 'string' || password.length === 0) {
23
+ throw new Error('Password is required');
24
+ }
25
+
26
+ const encoded = packet.slice(2, -2);
27
+
28
+ let data;
29
+ try {
30
+ data = Buffer.from(encoded, 'base64url');
31
+ } catch {
32
+ throw new Error('Invalid Codepack data');
33
+ }
34
+
35
+ // 12-byte nonce + 16-byte authentication tag + ciphertext
36
+ if (data.length < 28) {
37
+ throw new Error('Invalid Codepack data');
38
+ }
39
+
40
+ const nonce = data.subarray(0, 12);
41
+ const authTag = data.subarray(12, 28);
42
+ const encrypted = data.subarray(28);
43
+
44
+ const key = deriveKey(password);
45
+
46
+ try {
47
+ const decipher = crypto.createDecipheriv(
48
+ 'aes-256-gcm',
49
+ key,
50
+ nonce
51
+ );
52
+
53
+ decipher.setAAD(Buffer.from(FORMAT, 'utf8'));
54
+ decipher.setAuthTag(authTag);
55
+
56
+ return Buffer.concat([
57
+ decipher.update(encrypted),
58
+ decipher.final()
59
+ ]).toString('utf8');
60
+ } catch {
61
+ throw new Error('Authentication failed');
62
+ }
63
+ }
64
+
65
+ module.exports = {
66
+ decrypt
67
+ };
package/lib/encrypt.js ADDED
@@ -0,0 +1,54 @@
1
+ const crypto = require('crypto');
2
+
3
+ const PI = '3.14159265358979323846264338327950288419716939937510';
4
+ const FORMAT = `π+[${PI}]{}\/`;
5
+
6
+ function deriveKey(password) {
7
+ return crypto
8
+ .createHash('sha256')
9
+ .update(FORMAT + password, 'utf8')
10
+ .digest();
11
+ }
12
+
13
+ function encrypt(message, password) {
14
+ if (typeof message !== 'string') {
15
+ throw new TypeError('Message must be a string');
16
+ }
17
+
18
+ if (typeof password !== 'string' || password.length === 0) {
19
+ throw new Error('Password is required');
20
+ }
21
+
22
+ const key = deriveKey(password);
23
+
24
+ // Random 96-bit nonce
25
+ const nonce = crypto.randomBytes(12);
26
+
27
+ const cipher = crypto.createCipheriv(
28
+ 'aes-256-gcm',
29
+ key,
30
+ nonce
31
+ );
32
+
33
+ cipher.setAAD(Buffer.from(FORMAT, 'utf8'));
34
+
35
+ const encrypted = Buffer.concat([
36
+ cipher.update(message, 'utf8'),
37
+ cipher.final()
38
+ ]);
39
+
40
+ const authTag = cipher.getAuthTag();
41
+
42
+ // nonce + authentication tag + encrypted data
43
+ const packet = Buffer.concat([
44
+ nonce,
45
+ authTag,
46
+ encrypted
47
+ ]);
48
+
49
+ return `[{${packet.toString('base64url')}}]`;
50
+ }
51
+
52
+ module.exports = {
53
+ encrypt
54
+ };
package/package.json CHANGED
@@ -1,6 +1,23 @@
1
1
  {
2
2
  "name": "codepi-package",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "Secure encryption toolkit with the .Codepack[{}] format",
5
+ "main": "lib/codepack.js",
6
+ "bin": {
7
+ "codepi": "bin/codepi.js"
8
+ },
9
+ "scripts": {
10
+ "test": "node --check bin/codepi.js && node --check lib/encrypt.js && node --check lib/decrypt.js && node --check lib/codepack.js"
11
+ },
12
+ "keywords": [
13
+ "encryption",
14
+ "aes-256-gcm",
15
+ "codepack",
16
+ "security",
17
+ "termux"
18
+ ],
19
+ "license": "MIT",
20
+ "engines": {
21
+ "node": ">=18"
22
+ }
23
+ }
package/web/index.html ADDED
@@ -0,0 +1,91 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width,initial-scale=1">
6
+ <title>Code[{π*}]</title>
7
+ <style>
8
+ *{box-sizing:border-box}
9
+ body{margin:0;background:#0b0d12;color:#eee;font:15px Arial}
10
+ main{max-width:700px;margin:auto;padding:35px 18px}
11
+ header{text-align:center;margin-bottom:30px}
12
+ h1{font-size:34px;margin:0}
13
+ header p{color:#888}
14
+ .card{background:#13161d;border:1px solid #252a35;border-radius:14px;padding:18px;margin:15px 0}
15
+ h2{margin-top:0}
16
+ textarea,input,button{width:100%;padding:12px;margin:6px 0;border-radius:9px;border:1px solid #303642;background:#0d1016;color:#fff}
17
+ textarea{min-height:110px;resize:vertical}
18
+ button{cursor:pointer;font-weight:bold;background:#eee;color:#111}
19
+ .status{color:#888;font-size:13px}
20
+ </style>
21
+ </head>
22
+ <body>
23
+ <main>
24
+ <header>
25
+ <h1>Code[{π*}]</h1>
26
+ <p>Secure encryption toolkit</p>
27
+ </header>
28
+
29
+ <section class="card">
30
+ <h2>Encrypt</h2>
31
+ <textarea id="m" placeholder="Enter your message"></textarea>
32
+ <input id="ep" type="password" placeholder="Password">
33
+ <button onclick="encrypt()">Encrypt</button>
34
+ <textarea id="out" readonly placeholder="[{...}]"></textarea>
35
+ </section>
36
+
37
+ <section class="card">
38
+ <h2>Decrypt</h2>
39
+ <textarea id="in" placeholder="Paste [{...}]"></textarea>
40
+ <input id="dp" type="password" placeholder="Password">
41
+ <button onclick="decrypt()">Decrypt</button>
42
+ <textarea id="result" readonly placeholder="Decrypted message"></textarea>
43
+ </section>
44
+
45
+ <p class="status">AES-256-GCM · Local browser encryption</p>
46
+ <script>
47
+ const F="π+[3.14159265358979323846264338327950288419716939937510]{}/";
48
+ const E=new TextEncoder(),D=new TextDecoder();
49
+
50
+ async function key(p){
51
+ const h=await crypto.subtle.digest("SHA-256",E.encode(F+p));
52
+ return crypto.subtle.importKey("raw",h,{name:"AES-GCM"},false,["encrypt","decrypt"]);
53
+ }
54
+
55
+ function b64(a){
56
+ return btoa(String.fromCharCode(...a))
57
+ .replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");
58
+ }
59
+
60
+ function unb64(s){
61
+ s=s.replace(/-/g,"+").replace(/_/g,"/");
62
+ while(s.length%4)s+="=";
63
+ return Uint8Array.from(atob(s),x=>x.charCodeAt(0));
64
+ }
65
+
66
+ async function encrypt(){
67
+ const n=crypto.getRandomValues(new Uint8Array(12));
68
+ const c=new Uint8Array(await crypto.subtle.encrypt(
69
+ {name:"AES-GCM",iv:n,additionalData:E.encode(F)},
70
+ await key(ep.value),E.encode(m.value)
71
+ ));
72
+ const a=new Uint8Array(12+c.length);
73
+ a.set(n);a.set(c,12);
74
+ out.value="[{"+b64(a)+"}]";
75
+ }
76
+
77
+ async function decrypt(){
78
+ try{
79
+ const a=unb64(in.value.slice(2,-2));
80
+ result.value=D.decode(await crypto.subtle.decrypt(
81
+ {name:"AES-GCM",iv:a.slice(0,12),additionalData:E.encode(F)},
82
+ await key(dp.value),a.slice(12)
83
+ ));
84
+ }catch{
85
+ result.value="Authentication failed.";
86
+ }
87
+ }
88
+ </script>
89
+ </main>
90
+ </body>
91
+ </html>