ghostbit-cli 1.3.0__tar.gz → 1.4.0__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ghostbit-cli
3
- Version: 1.3.0
3
+ Version: 1.4.0
4
4
  Summary: Ghostbit CLI — create end-to-end encrypted pastes from the terminal
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/stackopshq/ghostbit
@@ -27,6 +27,7 @@ from ._completion import cmd_completion as _cmd_completion_raw
27
27
  from ._config import DEFAULT_SERVER, cmd_config, load_config
28
28
  from ._crypto import (
29
29
  decrypt,
30
+ decrypt_bytes,
30
31
  derive_key,
31
32
  encrypt,
32
33
  gen_key,
@@ -114,7 +115,13 @@ def cmd_paste(args) -> None:
114
115
  key = gen_key()
115
116
  kdf_salt = None
116
117
 
117
- ciphertext, nonce = encrypt(content, key)
118
+ if args.compress:
119
+ import gzip
120
+
121
+ payload_input: str | bytes = gzip.compress(content.encode())
122
+ else:
123
+ payload_input = content
124
+ ciphertext, nonce = encrypt(payload_input, key)
118
125
 
119
126
  payload = {
120
127
  "content": ciphertext,
@@ -124,6 +131,7 @@ def cmd_paste(args) -> None:
124
131
  "expires_in": args.expires,
125
132
  "burn": args.burn,
126
133
  "max_views": args.max_views,
134
+ "compressed": args.compress,
127
135
  }
128
136
 
129
137
  result = api_create(server, payload)
@@ -269,7 +277,12 @@ def cmd_view(args) -> None:
269
277
  key = base64.urlsafe_b64decode(padded)
270
278
 
271
279
  try:
272
- plaintext = decrypt(data["content"], data["nonce"], key)
280
+ if data.get("compressed"):
281
+ import gzip
282
+
283
+ plaintext = gzip.decompress(decrypt_bytes(data["content"], data["nonce"], key)).decode()
284
+ else:
285
+ plaintext = decrypt(data["content"], data["nonce"], key)
273
286
  except Exception: # noqa: BLE001
274
287
  print("Error: decryption failed — wrong key or corrupted paste.", file=sys.stderr)
275
288
  sys.exit(1)
@@ -501,6 +514,10 @@ current server: {current_server}
501
514
  "--burn", "-b", action="store_true",
502
515
  help="Delete after the first view.",
503
516
  ) # fmt: skip
517
+ parser.add_argument(
518
+ "--compress", "-z", action="store_true",
519
+ help="Gzip the plaintext locally BEFORE encryption (60–80%% smaller for text).",
520
+ ) # fmt: skip
504
521
  parser.add_argument(
505
522
  "--max-views", "-m", type=int, default=None, metavar="N",
506
523
  help="Delete after N views.",
@@ -42,17 +42,23 @@ def gen_salt() -> str:
42
42
  return base64.b64encode(os.urandom(16)).decode()
43
43
 
44
44
 
45
- def encrypt(plaintext: str, key: bytes) -> tuple[str, str]:
45
+ def encrypt(plaintext: str | bytes, key: bytes) -> tuple[str, str]:
46
+ """Encrypt a string or raw bytes with AES-256-GCM. Returns (ct_b64, nonce_b64)."""
46
47
  nonce = os.urandom(12)
47
- ct = AESGCM(key).encrypt(nonce, plaintext.encode(), None)
48
+ data = plaintext.encode() if isinstance(plaintext, str) else plaintext
49
+ ct = AESGCM(key).encrypt(nonce, data, None)
48
50
  return base64.b64encode(ct).decode(), base64.b64encode(nonce).decode()
49
51
 
50
52
 
51
- def decrypt(ciphertext_b64: str, nonce_b64: str, key: bytes) -> str:
53
+ def decrypt_bytes(ciphertext_b64: str, nonce_b64: str, key: bytes) -> bytes:
54
+ """Decrypt returning raw bytes — used by the compressed-paste path."""
52
55
  ct = base64.b64decode(ciphertext_b64)
53
56
  nonce = base64.b64decode(nonce_b64)
54
- pt = AESGCM(key).decrypt(nonce, ct, None)
55
- return pt.decode()
57
+ return AESGCM(key).decrypt(nonce, ct, None)
58
+
59
+
60
+ def decrypt(ciphertext_b64: str, nonce_b64: str, key: bytes) -> str:
61
+ return decrypt_bytes(ciphertext_b64, nonce_b64, key).decode()
56
62
 
57
63
 
58
64
  def derive_key(password: str, salt_b64: str) -> bytes:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ghostbit-cli
3
- Version: 1.3.0
3
+ Version: 1.4.0
4
4
  Summary: Ghostbit CLI — create end-to-end encrypted pastes from the terminal
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/stackopshq/ghostbit
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ghostbit-cli"
7
- version = "1.3.0"
7
+ version = "1.4.0"
8
8
  description = "Ghostbit CLI — create end-to-end encrypted pastes from the terminal"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes