lpgp 0.2.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.
Files changed (48) hide show
  1. package/LICENSE +52 -0
  2. package/README.md +218 -0
  3. package/dist/config.d.ts +17 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +31 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/db.d.ts +80 -0
  8. package/dist/db.d.ts.map +1 -0
  9. package/dist/db.js +284 -0
  10. package/dist/db.js.map +1 -0
  11. package/dist/decrypt.d.ts +2 -0
  12. package/dist/decrypt.d.ts.map +1 -0
  13. package/dist/decrypt.js +25 -0
  14. package/dist/decrypt.js.map +1 -0
  15. package/dist/encrypt.d.ts +2 -0
  16. package/dist/encrypt.d.ts.map +1 -0
  17. package/dist/encrypt.js +18 -0
  18. package/dist/encrypt.js.map +1 -0
  19. package/dist/key-manager.d.ts +119 -0
  20. package/dist/key-manager.d.ts.map +1 -0
  21. package/dist/key-manager.js +1235 -0
  22. package/dist/key-manager.js.map +1 -0
  23. package/dist/key-utils.d.ts +47 -0
  24. package/dist/key-utils.d.ts.map +1 -0
  25. package/dist/key-utils.js +199 -0
  26. package/dist/key-utils.js.map +1 -0
  27. package/dist/keychain.d.ts +22 -0
  28. package/dist/keychain.d.ts.map +1 -0
  29. package/dist/keychain.js +73 -0
  30. package/dist/keychain.js.map +1 -0
  31. package/dist/pgp-tool.d.ts +3 -0
  32. package/dist/pgp-tool.d.ts.map +1 -0
  33. package/dist/pgp-tool.js +1061 -0
  34. package/dist/pgp-tool.js.map +1 -0
  35. package/dist/prompts.d.ts +11 -0
  36. package/dist/prompts.d.ts.map +1 -0
  37. package/dist/prompts.js +109 -0
  38. package/dist/prompts.js.map +1 -0
  39. package/dist/schema.sql +86 -0
  40. package/dist/system-keys.d.ts +32 -0
  41. package/dist/system-keys.d.ts.map +1 -0
  42. package/dist/system-keys.js +123 -0
  43. package/dist/system-keys.js.map +1 -0
  44. package/dist/ui.d.ts +94 -0
  45. package/dist/ui.d.ts.map +1 -0
  46. package/dist/ui.js +175 -0
  47. package/dist/ui.js.map +1 -0
  48. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,52 @@
1
+ Source Available Educational License
2
+
3
+ Copyright (c) 2025 Layerbase, LLC
4
+
5
+ IMPORTANT: This is NOT an open source license. The source code is made publicly
6
+ available for educational purposes, security auditing, and learning only.
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to use,
10
+ copy, modify, and study the Software for educational and non-commercial purposes
11
+ only, subject to the following conditions:
12
+
13
+ 1. PERMITTED USES:
14
+ - Educational and learning purposes
15
+ - Security auditing and code review
16
+ - Personal, non-commercial projects
17
+ - Academic research and teaching
18
+
19
+ 2. PROHIBITED USES:
20
+ - Commercial use of any kind
21
+ - Use by for-profit enterprises or organizations
22
+ - Integration into commercial products or services
23
+ - Use in production environments for business purposes
24
+ - Distribution or sale of the Software or derivatives for profit
25
+
26
+ 3. ATTRIBUTION:
27
+ The above copyright notice and this permission notice shall be included in all
28
+ copies or substantial portions of the Software.
29
+
30
+ 4. MODIFICATIONS:
31
+ You may create derivative works for educational purposes only. Any derivative
32
+ works must carry this same license and may not be used commercially.
33
+
34
+ 5. NO COMMERCIAL LICENSING:
35
+ Commercial use requires explicit written permission from the copyright holder.
36
+ Contact information for commercial licensing inquiries can be provided upon
37
+ request.
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
45
+ SOFTWARE.
46
+
47
+ ---
48
+
49
+ This software is source-available for transparency and educational purposes,
50
+ but is NOT open source as defined by the Open Source Initiative. It is designed
51
+ as a learning project to explore PGP encryption, progressive enhancement, and
52
+ building web applications that work without JavaScript.
package/README.md ADDED
@@ -0,0 +1,218 @@
1
+ # LPGP
2
+
3
+ Interactive CLI tool for PGP encryption/decryption with SQLite key management.
4
+
5
+ > **Note:** This is a personal side project created to learn more about encryption and PGP. It's a work in progress and should be used for educational purposes.
6
+
7
+ ## Project Status
8
+
9
+ This project is **actively being developed** as a learning exercise. While functional, it may contain bugs or security considerations that need addressing. Use at your own discretion and avoid using it for highly sensitive production data.
10
+
11
+ ## Features
12
+
13
+ - **PGP Encryption/Decryption** - Secure message encryption using OpenPGP
14
+ - **SQLite Key Management** - Store and manage multiple keypairs and contacts
15
+ - **System Keychain Integration** - Passphrases stored securely in your OS keychain
16
+ - **Clipboard Integration** - Seamlessly encrypt/decrypt from clipboard
17
+ - **Multiple Input Methods** - Clipboard, text editor, or inline terminal input
18
+ - **Cross-Platform Support** - Works on Linux, macOS, and Windows
19
+ - **Smart Editor Detection** - Auto-detects available editors (VS Code, Vim, Nano, etc.)
20
+
21
+ ## Getting Started
22
+
23
+ ### Prerequisites
24
+
25
+ - Node.js (v18 or higher recommended)
26
+ - pnpm (v10.19.0 or higher)
27
+
28
+ ### Installation
29
+
30
+ #### Option 1: Automated Installer (Recommended for Non-Developers)
31
+
32
+ 1. Clone the repository:
33
+
34
+ ```bash
35
+ git clone https://github.com/robertjbass/lpgp.git
36
+ cd lpgp
37
+ ```
38
+
39
+ 2. Run the installer:
40
+
41
+ ```bash
42
+ ./install.sh
43
+ ```
44
+
45
+ The installer will:
46
+
47
+ - Detect your operating system and shell
48
+ - Check for Node.js and install it if missing (using nvm)
49
+ - Check for pnpm and install it if missing
50
+ - Install all dependencies and compile native modules
51
+ - Build the project
52
+ - Optionally create an `lpgp` command alias
53
+
54
+ 3. Run the tool and create or import your keys:
55
+
56
+ ```bash
57
+ pnpm dev
58
+ ```
59
+
60
+ Use the Key Management menu to generate new keypairs or import existing ones.
61
+
62
+ #### Option 2: Manual Installation (For Developers)
63
+
64
+ 1. Clone the repository:
65
+
66
+ ```bash
67
+ git clone https://github.com/robertjass/lpgp.git
68
+ cd lpgp
69
+ ```
70
+
71
+ 2. Install dependencies:
72
+
73
+ ```bash
74
+ pnpm install
75
+ ```
76
+
77
+ This will install all Node.js dependencies including `better-sqlite3`, which requires native compilation.
78
+
79
+ 3. Build the project:
80
+
81
+ ```bash
82
+ pnpm build
83
+ ```
84
+
85
+ 4. Database initialization:
86
+
87
+ The SQLite database is automatically created on first run at `~/.lpgp/data.db`. No manual setup required!
88
+
89
+ ### Usage
90
+
91
+ Run the PGP tool:
92
+
93
+ ```bash
94
+ pnpm dev
95
+ ```
96
+
97
+ You'll be greeted with an interactive menu:
98
+
99
+ ```
100
+ ╔════════════════════════════════════════╗
101
+ ║ 🔐 PGP Encryption/Decryption Tool ║
102
+ ╚════════════════════════════════════════╝
103
+
104
+ ? What would you like to do?
105
+ 🔒 Encrypt a message
106
+ 🔓 Decrypt a message
107
+ 👋 Exit
108
+ ```
109
+
110
+ ## How It Works
111
+
112
+ ### Encrypting a Message
113
+
114
+ 1. Select "🔒 Encrypt a message"
115
+ 2. Choose your input method:
116
+ - **📋 Paste from clipboard** - Automatically encrypts text from your clipboard
117
+ - **📝 Use an editor** - Opens your preferred text editor
118
+ - **⌨️ Type inline** - Enter text directly (press Enter, then Ctrl+D to finish)
119
+ 3. The encrypted message is displayed and automatically copied to your clipboard
120
+
121
+ ### Decrypting a Message
122
+
123
+ 1. Select "🔓 Decrypt a message"
124
+ 2. Choose your input method for the encrypted text
125
+ 3. The decrypted message is displayed and automatically copied to your clipboard
126
+
127
+ ## Development
128
+
129
+ ### Available Scripts
130
+
131
+ ```bash
132
+ # Run the PGP tool (development)
133
+ pnpm dev
134
+
135
+ # Format code with Prettier
136
+ pnpm format
137
+
138
+ # Build the TypeScript project
139
+ pnpm build
140
+
141
+ # Run the built project
142
+ pnpm start
143
+ ```
144
+
145
+ ### Project Structure
146
+
147
+ ```
148
+ lpgp/
149
+ ├── src/
150
+ │ ├── pgp-tool.ts # Main CLI entry point
151
+ │ ├── encrypt.ts # Encryption logic
152
+ │ ├── decrypt.ts # Decryption logic
153
+ │ ├── key-manager.ts # Key management UI
154
+ │ ├── key-utils.ts # Key utility functions
155
+ │ ├── db.ts # SQLite database layer
156
+ │ ├── ui.ts # Centralized UI styling
157
+ │ └── schema.sql # Database schema
158
+ ├── dist/ # Built output (not in git)
159
+ ├── package.json
160
+ ├── tsconfig.json
161
+ └── README.md
162
+ ```
163
+
164
+ ## Roadmap
165
+
166
+ See [TODO.md](TODO.md) for the complete project roadmap. Completed and upcoming features:
167
+
168
+ - SQLite database integration
169
+ - System keychain passphrase storage
170
+ - Key generation and management
171
+ - Multi-recipient encryption
172
+ - Contact management
173
+ - File encryption/decryption (planned)
174
+ - GPG keyring import (planned)
175
+
176
+ ## Security Considerations
177
+
178
+ As this is a learning project, please note:
179
+
180
+ - Passphrases are stored in your system keychain (macOS Keychain, Windows Credential Manager, etc.)
181
+ - Keys are stored in SQLite database at `~/.lpgp/data.db`
182
+ - The `.gitignore` excludes database and `.env` files
183
+ - This tool has not undergone professional security audit
184
+ - For production use, consider more secure key storage methods (e.g., hardware tokens)
185
+
186
+ ## Contributing
187
+
188
+ This is primarily a personal learning project, but suggestions and feedback are welcome! Feel free to:
189
+
190
+ - Open issues for bugs or feature requests
191
+ - Submit pull requests with improvements
192
+ - Share your experience using the tool
193
+
194
+ ## License
195
+
196
+ **Source Available Educational License** - NOT Open Source
197
+
198
+ This software is source-available for educational purposes, security auditing, and learning only. Commercial use and use by for-profit enterprises is prohibited without explicit permission. See the [LICENSE](LICENSE) file for full terms.
199
+
200
+ The source code is publicly available to promote transparency, enable security audits, and support learning about encryption and web development - but this does not make it open source software.
201
+
202
+ ## Acknowledgments
203
+
204
+ - Built with [OpenPGP.js](https://openpgpjs.org/) for encryption
205
+ - [Inquirer.js](https://github.com/SBoudrias/Inquirer.js) for beautiful CLI prompts
206
+ - [Chalk](https://github.com/chalk/chalk) for terminal styling
207
+ - [Clipboardy](https://github.com/sindresorhus/clipboardy) for clipboard operations
208
+
209
+ ---
210
+
211
+ **Learning Focus:** This project explores:
212
+
213
+ - PGP encryption and cryptography fundamentals
214
+ - Node.js CLI development with TypeScript
215
+ - Security best practices for handling sensitive data
216
+ - System keychain integration for secure credential storage
217
+
218
+ It's a work in progress and will continue to evolve as I learn more about encryption and secure communication.
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Get the application config directory path.
3
+ * Creates the directory if it doesn't exist.
4
+ *
5
+ * - Unix-like (macOS, Linux): ~/.lpgp
6
+ * - Windows: C:\Users\<username>\.lpgp
7
+ */
8
+ export declare function getConfigDir(): string;
9
+ /**
10
+ * Get the database file path.
11
+ */
12
+ export declare function getDbPath(): string;
13
+ /**
14
+ * Get the path to a file within the config directory.
15
+ */
16
+ export declare function getConfigPath(filename: string): string;
17
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA;;;;;;GAMG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAQrC;AAED;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtD"}
package/dist/config.js ADDED
@@ -0,0 +1,31 @@
1
+ import { existsSync, mkdirSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+ const APP_DIR_NAME = '.lpgp';
5
+ /**
6
+ * Get the application config directory path.
7
+ * Creates the directory if it doesn't exist.
8
+ *
9
+ * - Unix-like (macOS, Linux): ~/.lpgp
10
+ * - Windows: C:\Users\<username>\.lpgp
11
+ */
12
+ export function getConfigDir() {
13
+ const configDir = join(homedir(), APP_DIR_NAME);
14
+ if (!existsSync(configDir)) {
15
+ mkdirSync(configDir, { recursive: true });
16
+ }
17
+ return configDir;
18
+ }
19
+ /**
20
+ * Get the database file path.
21
+ */
22
+ export function getDbPath() {
23
+ return join(getConfigDir(), 'data.db');
24
+ }
25
+ /**
26
+ * Get the path to a file within the config directory.
27
+ */
28
+ export function getConfigPath(filename) {
29
+ return join(getConfigDir(), filename);
30
+ }
31
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAE5B,MAAM,YAAY,GAAG,OAAO,CAAA;AAE5B;;;;;;GAMG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAA;IAE/C,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,SAAS,CAAC,CAAA;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,IAAI,CAAC,YAAY,EAAE,EAAE,QAAQ,CAAC,CAAA;AACvC,CAAC"}
package/dist/db.d.ts ADDED
@@ -0,0 +1,80 @@
1
+ export type Keypair = {
2
+ id: number;
3
+ name: string;
4
+ email: string;
5
+ fingerprint: string;
6
+ public_key: string;
7
+ private_key: string;
8
+ passphrase_protected: boolean;
9
+ algorithm: string;
10
+ key_size: string;
11
+ can_sign: boolean;
12
+ can_encrypt: boolean;
13
+ can_certify: boolean;
14
+ can_authenticate: boolean;
15
+ expires_at: string | null;
16
+ revoked: boolean;
17
+ revocation_reason: string | null;
18
+ created_at: string;
19
+ updated_at: string;
20
+ last_used_at: string | null;
21
+ is_default: boolean;
22
+ };
23
+ export type Contact = {
24
+ id: number;
25
+ name: string;
26
+ email: string;
27
+ fingerprint: string;
28
+ public_key: string;
29
+ algorithm: string;
30
+ key_size: string;
31
+ trusted: boolean;
32
+ last_verified_at: string | null;
33
+ notes: string | null;
34
+ expires_at: string | null;
35
+ revoked: boolean;
36
+ created_at: string;
37
+ updated_at: string;
38
+ };
39
+ export type Settings = {
40
+ id: number;
41
+ default_keypair_id: number | null;
42
+ auto_sign_messages: boolean;
43
+ prefer_inline_pgp: boolean;
44
+ keyserver_url: string;
45
+ };
46
+ type Schema = {
47
+ keypair: Keypair[];
48
+ contact: Contact[];
49
+ settings: Settings;
50
+ };
51
+ export declare class Db {
52
+ private db;
53
+ constructor();
54
+ /**
55
+ * Migrate database from the old project-local location to ~/.lpgp
56
+ */
57
+ private migrateFromLegacyLocation;
58
+ private initializeSchema;
59
+ private migrateFromJson;
60
+ select<T extends keyof Schema>({ table, where, }: {
61
+ table: T;
62
+ where?: {
63
+ key: keyof Schema[T] extends keyof Schema[T] ? T extends 'settings' ? keyof Settings : keyof Keypair | keyof Contact : never;
64
+ compare: 'is' | 'is not' | 'like' | 'not like';
65
+ value: any;
66
+ };
67
+ }): T extends 'settings' ? Settings : Schema[T];
68
+ insert<T extends keyof Schema>(table: T, value: T extends 'settings' ? Partial<Omit<Settings, 'id'>> : T extends 'keypair' ? Omit<Keypair, 'id' | 'created_at' | 'updated_at'> : Omit<Contact, 'id' | 'created_at' | 'updated_at'>): T extends 'settings' ? Settings : T extends 'keypair' ? Keypair : Contact;
69
+ update<T extends keyof Schema>(table: T, where: {
70
+ key: T extends 'settings' ? keyof Settings : keyof Keypair | keyof Contact;
71
+ value: any;
72
+ }, updates: T extends 'settings' ? Partial<Settings> : T extends 'keypair' ? Partial<Keypair> : Partial<Contact>): void;
73
+ delete<T extends keyof Schema>(table: T, where: {
74
+ key: T extends 'settings' ? keyof Settings : keyof Keypair | keyof Contact;
75
+ value: any;
76
+ }): void;
77
+ close(): void;
78
+ }
79
+ export {};
80
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}