cipher-crypter 3.0.0__py3-none-any.whl

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.
@@ -0,0 +1 @@
1
+ __version__ = "3.0.0"
cipher_crypter/cli.py ADDED
@@ -0,0 +1,991 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ ╔═══════════════════════════════════════════════╗
4
+ ║ Cipher Crypter v3.0 — by JosephX ║
5
+ ║ Gelişmiş Terminal Şifreleme Aracı ║
6
+ ╚═══════════════════════════════════════════════╝
7
+ """
8
+
9
+ import time, os, sys, json, random, datetime, hashlib, struct, zlib, hmac
10
+ from dataclasses import dataclass, asdict
11
+
12
+ # ── Renk kodları ─────────────────────────────────────────────────────────────
13
+ class C:
14
+ GREEN = "\033[92m"
15
+ GREEN_DIM = "\033[32m"
16
+ AMBER = "\033[33m"
17
+ RED = "\033[91m"
18
+ CYAN = "\033[96m"
19
+ MAGENTA = "\033[95m"
20
+ WHITE = "\033[97m"
21
+ GRAY = "\033[90m"
22
+ BOLD = "\033[1m"
23
+ RESET = "\033[0m"
24
+ BLINK = "\033[5m"
25
+
26
+ def supports_color():
27
+ return hasattr(sys.stdout, "isatty") and sys.stdout.isatty()
28
+
29
+ if not supports_color():
30
+ for attr in vars(C):
31
+ if not attr.startswith("_"):
32
+ setattr(C, attr, "")
33
+
34
+ # ── Şifreleme seviyeleri ──────────────────────────────────────────────────────
35
+ LEVELS = {
36
+ 1: ("EASY", C.GREEN, "░", "Temel sembol kodlama"),
37
+ 2: ("MEDIUM", C.CYAN, "▒", "Sembol + XOR katmanı"),
38
+ 3: ("HARD", C.AMBER, "▓", "Sembol + XOR + Byte karıştırma"),
39
+ 4: ("DEVIL", C.RED, "▲", "HARD + Vigenere + Tuz"),
40
+ 5: ("IMPOSSIBLE", C.MAGENTA, "☠", "DEVIL × 3 tur + Padding + Zlib"),
41
+ }
42
+
43
+ LEVEL_COLORS = {1: C.GREEN, 2: C.CYAN, 3: C.AMBER, 4: C.RED, 5: C.MAGENTA}
44
+
45
+ # ── Temel sembol seti (base-13) ───────────────────────────────────────────────
46
+ CHARS = "░▒▓╨╬╥╫╤╞╪╩╧╙"
47
+ BASE = len(CHARS) # 13
48
+
49
+ # ── Desteklenen binary uzantılar ──────────────────────────────────────────────
50
+ BINARY_EXTS = {
51
+ # Video
52
+ ".mp4", ".mkv", ".avi", ".mov", ".wmv", ".flv", ".webm", ".m4v",
53
+ # Ses
54
+ ".mp3", ".wav", ".flac", ".ogg", ".aac", ".m4a", ".wma",
55
+ # Resim
56
+ ".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tiff", ".ico", ".svg",
57
+ # Ofis / Doküman
58
+ ".pdf", ".docx", ".xlsx", ".pptx", ".odt", ".ods",
59
+ # Arşiv
60
+ ".zip", ".rar", ".7z", ".tar", ".gz", ".bz2", ".xz", ".iso",
61
+ # Veri / DB
62
+ ".csv", ".json", ".xml", ".db", ".sqlite", ".sql",
63
+ # Uygulama / Sistem
64
+ ".exe", ".dll", ".apk", ".bin", ".so", ".dylib",
65
+ # Font / Diğer
66
+ ".ttf", ".otf", ".woff", ".woff2",
67
+ }
68
+
69
+ TEXT_EXTS = {".txt", ".md", ".log", ".py", ".js", ".ts", ".html", ".css",
70
+ ".sh", ".bat", ".cfg", ".ini", ".yaml", ".yml", ".toml"}
71
+
72
+ def dosya_tipi(path: str) -> str:
73
+ """'binary', 'text', veya 'unknown' döndür."""
74
+ ext = os.path.splitext(path)[1].lower()
75
+ if ext in BINARY_EXTS: return "binary"
76
+ if ext in TEXT_EXTS: return "text"
77
+ return "unknown" # bilinmeyen → binary olarak işle
78
+
79
+ # ─────────────────────────────────────────────────────────────────────────────
80
+ # ŞİFRELEME ALGORİTMALARI (bytes → bytes)
81
+ # ─────────────────────────────────────────────────────────────────────────────
82
+
83
+ def _b13_enc(data: bytes) -> bytes:
84
+ """Her byte'ı 3 CHARS sembolüyle kodla (hızlı lookup table)."""
85
+ # Lookup table: 256 byte → 3 sembol (UTF-8, her sembol 3 byte = 9 byte/giriş)
86
+ tbl = []
87
+ for b in range(256):
88
+ tbl.append((CHARS[b // (BASE * BASE) % BASE] +
89
+ CHARS[(b // BASE) % BASE] +
90
+ CHARS[b % BASE]).encode("utf-8"))
91
+ out = bytearray()
92
+ for b in data:
93
+ out += tbl[b]
94
+ return bytes(out)
95
+
96
+ def _b13_dec(data: bytes) -> bytes:
97
+ s = data.decode("utf-8")
98
+ if len(s) % 3 != 0:
99
+ raise ValueError("Bozuk veri: uzunluk 3'ün katı değil.")
100
+ # Ters lookup: sembol → değer
101
+ rev = {c: i for i, c in enumerate(CHARS)}
102
+ out = bytearray(len(s) // 3)
103
+ for i in range(0, len(s), 3):
104
+ out[i // 3] = rev[s[i]] * BASE * BASE + rev[s[i+1]] * BASE + rev[s[i+2]]
105
+ return bytes(out)
106
+
107
+ def _xor(data: bytes, key: bytes) -> bytes:
108
+ """Hızlı XOR: key'i veri uzunluğuna tileleyip bytearray XOR."""
109
+ kl = len(key)
110
+ n = len(data)
111
+ # key'i tam kat + kırıntı olarak tile et
112
+ reps, rem = divmod(n, kl)
113
+ full_key = bytearray(key * reps + key[:rem])
114
+ out = bytearray(n)
115
+ for i in range(n):
116
+ out[i] = data[i] ^ full_key[i]
117
+ return bytes(out)
118
+
119
+ def _make_perm(n: int, seed: int):
120
+ """Fisher-Yates ile deterministik permütasyon döndür (list[int])."""
121
+ rng = random.Random(seed)
122
+ perm = list(range(n))
123
+ for i in range(n - 1, 0, -1):
124
+ j = rng.randint(0, i)
125
+ perm[i], perm[j] = perm[j], perm[i]
126
+ return perm
127
+
128
+ def _shuffle(data: bytes, seed: int) -> bytes:
129
+ """Deterministik byte karıştırma.
130
+ perm[i] = j anlamı: orijinal i. byte → çıktıda j. konuma gider.
131
+ out[perm[i]] = data[i]
132
+ """
133
+ n = len(data)
134
+ perm = _make_perm(n, seed)
135
+ out = bytearray(n)
136
+ for i, p in enumerate(perm):
137
+ out[p] = data[i]
138
+ return bytes(out)
139
+
140
+ def _unshuffle(data: bytes, seed: int) -> bytes:
141
+ """_shuffle'ın tersi.
142
+ out[i] = data[perm[i]] ← çünkü out[perm[i]]=data[i] idi
143
+ """
144
+ n = len(data)
145
+ perm = _make_perm(n, seed)
146
+ out = bytearray(n)
147
+ for i, p in enumerate(perm):
148
+ out[i] = data[p]
149
+ return bytes(out)
150
+
151
+ def _vigenere_enc(data: bytes, key: bytes) -> bytes:
152
+ kl = len(key)
153
+ out = bytearray(len(data))
154
+ for i, b in enumerate(data):
155
+ out[i] = (b + key[i % kl]) & 0xFF
156
+ return bytes(out)
157
+
158
+ def _vigenere_dec(data: bytes, key: bytes) -> bytes:
159
+ kl = len(key)
160
+ out = bytearray(len(data))
161
+ for i, b in enumerate(data):
162
+ out[i] = (b - key[i % kl]) & 0xFF
163
+ return bytes(out)
164
+
165
+ def _derive_keys(password: str) -> dict:
166
+ """Şifreden deterministik anahtarlar türet."""
167
+ h = hashlib.sha256(password.encode("utf-8")).digest()
168
+ return {
169
+ "xor": h[:16],
170
+ "shuffle": struct.unpack("<Q", h[16:24])[0],
171
+ "vigenere": h[8:24],
172
+ "salt": h[4:12],
173
+ "mac": h,
174
+ }
175
+
176
+ # MAC_SIZE: şifreli veriye eklenen imza uzunluğu (byte)
177
+ MAC_SIZE = 16
178
+
179
+ def _mac_sign(data: bytes, key: bytes) -> bytes:
180
+ """Verinin HMAC-SHA256 imzasının ilk MAC_SIZE byte'ını döndür."""
181
+ return hmac.new(key, data, hashlib.sha256).digest()[:MAC_SIZE]
182
+
183
+ def _mac_verify(data: bytes, key: bytes, tag: bytes) -> bool:
184
+ """İmzayı doğrula; timing-safe karşılaştırma kullan."""
185
+ expected = _mac_sign(data, key)
186
+ return hmac.compare_digest(expected, tag)
187
+
188
+ # ── Seviyeye göre şifreleme / çözme ──────────────────────────────────────────
189
+
190
+ def _real_progress(label_text: str, fn, *args, color=C.GREEN):
191
+ """fn(*args) çalıştırır, aynı anda sahte ama gerçekçi progress gösterir."""
192
+ import threading
193
+ result_box = [None]
194
+ err_box = [None]
195
+ done = threading.Event()
196
+
197
+ def worker():
198
+ try:
199
+ result_box[0] = fn(*args)
200
+ except Exception as e:
201
+ err_box[0] = e
202
+ finally:
203
+ done.set()
204
+
205
+ t = threading.Thread(target=worker, daemon=True)
206
+ t.start()
207
+
208
+ width = 44
209
+ filled = 0
210
+ step = 0
211
+ while not done.is_set():
212
+ # Hızlı başla, yavaşla
213
+ inc = max(1, (width - filled) // 8) if filled < width * 0.9 else 0
214
+ filled = min(filled + inc, int(width * 0.97))
215
+ bar = "█" * filled + "░" * (width - filled)
216
+ col = color if filled / width < 0.8 else C.AMBER
217
+ print(f"\r {C.GREEN_DIM}{label_text}{C.RESET} "
218
+ f"[{col}{bar}{C.RESET}] "
219
+ f"{C.WHITE}{int(filled/width*100):3d}%{C.RESET}",
220
+ end="", flush=True)
221
+ done.wait(timeout=0.15)
222
+ step += 1
223
+
224
+ # 100% göster
225
+ bar = "█" * width
226
+ print(f"\r {C.GREEN_DIM}{label_text}{C.RESET} "
227
+ f"[{color}{bar}{C.RESET}] "
228
+ f"{C.WHITE}100%{C.RESET}")
229
+
230
+ if err_box[0]:
231
+ raise err_box[0]
232
+ return result_box[0]
233
+
234
+
235
+ def enc_level(data: bytes, level: int, password: str,
236
+ show_progress: bool = False) -> bytes:
237
+ k = _derive_keys(password)
238
+ col = LEVEL_COLORS.get(level, C.GREEN)
239
+
240
+ def _run(label, fn, *args):
241
+ if show_progress:
242
+ return _real_progress(label, fn, *args, color=col)
243
+ return fn(*args)
244
+
245
+ if level == 1:
246
+ result = _run(f"[EASY] Kodlanıyor", _b13_enc, data)
247
+
248
+ elif level == 2:
249
+ d = _run(f"[MEDIUM] XOR", _xor, data, k["xor"])
250
+ result = _run(f"[MEDIUM] Kodlanıyor", _b13_enc, d)
251
+
252
+ elif level == 3:
253
+ d = _run(f"[HARD] XOR", _xor, data, k["xor"])
254
+ d = _run(f"[HARD] Karıştırılıyor", _shuffle, d, k["shuffle"])
255
+ result = _run(f"[HARD] Kodlanıyor", _b13_enc, d)
256
+
257
+ elif level == 4:
258
+ d = _run(f"[DEVIL] Vigenere", _vigenere_enc, data, k["vigenere"])
259
+ d = _run(f"[DEVIL] XOR", _xor, d, k["xor"])
260
+ d = _run(f"[DEVIL] Karıştırılıyor", _shuffle, d, k["shuffle"])
261
+ d = k["salt"] + d
262
+ result = _run(f"[DEVIL] Kodlanıyor", _b13_enc, d)
263
+
264
+ elif level == 5:
265
+ d = data
266
+ for turn in range(3):
267
+ tk = _derive_keys(password + str(turn))
268
+ d = _run(f"[IMPOSSIBLE] Tur {turn+1}/3 — Vigenere",
269
+ _vigenere_enc, d, tk["vigenere"])
270
+ d = _run(f"[IMPOSSIBLE] Tur {turn+1}/3 — XOR",
271
+ _xor, d, tk["xor"])
272
+ d = _run(f"[IMPOSSIBLE] Tur {turn+1}/3 — Karıştırma",
273
+ _shuffle, d, tk["shuffle"])
274
+ d = tk["salt"] + d
275
+ pad_len = random.randint(16, 64)
276
+ pad = bytes(random.randint(0, 255) for _ in range(pad_len))
277
+ pad_header = struct.pack("<H", pad_len)
278
+ d = pad_header + pad + d
279
+ if show_progress:
280
+ d = _real_progress("[IMPOSSIBLE] Sıkıştırılıyor",
281
+ zlib.compress, d, 1, color=col)
282
+ else:
283
+ d = zlib.compress(d, level=1)
284
+ result = _run(f"[IMPOSSIBLE] Son kodlama", _b13_enc, d)
285
+
286
+ else:
287
+ raise ValueError(f"Geçersiz seviye: {level}")
288
+
289
+ return _enc_with_mac(result, level, password)
290
+
291
+
292
+ def _enc_with_mac(enc_fn_result: bytes, level: int, password: str) -> bytes:
293
+ """EASY hariç tüm seviyelerde sonuca MAC imzası ekle."""
294
+ if level == 1:
295
+ return enc_fn_result # şifresiz, imza anlamsız
296
+ k = _derive_keys(password)
297
+ tag = _mac_sign(enc_fn_result, k["mac"])
298
+ return tag + enc_fn_result
299
+
300
+
301
+ def _dec_verify_mac(data: bytes, level: int, password: str):
302
+ """MAC'i doğrula ve imzasız veriyi döndür. Hatalı şifrede ValueError fırlatır."""
303
+ if level == 1:
304
+ return data
305
+ if len(data) < MAC_SIZE:
306
+ raise ValueError("Bozuk veri: çok kısa.")
307
+ tag = data[:MAC_SIZE]
308
+ body = data[MAC_SIZE:]
309
+ k = _derive_keys(password)
310
+ if not _mac_verify(body, k["mac"], tag):
311
+ raise ValueError("Hatalı şifre veya bozuk dosya.")
312
+ return body
313
+
314
+
315
+ def dec_level(data: bytes, level: int, password: str,
316
+ show_progress: bool = False, has_mac: bool = True) -> bytes:
317
+ # MAC doğrula — yalnızca yeni format (CIPHERX4) dosyalarda
318
+ if has_mac:
319
+ data = _dec_verify_mac(data, level, password)
320
+
321
+ k = _derive_keys(password)
322
+ col = LEVEL_COLORS.get(level, C.GREEN)
323
+
324
+ def _run(label, fn, *args):
325
+ if show_progress:
326
+ return _real_progress(label, fn, *args, color=col)
327
+ return fn(*args)
328
+
329
+ d = _run(f"[{LEVELS[level][0]}] Çözümleniyor", _b13_dec, data)
330
+
331
+ if level == 1:
332
+ return d
333
+
334
+ elif level == 2:
335
+ return _run(f"[MEDIUM] XOR tersle", _xor, d, k["xor"])
336
+
337
+ elif level == 3:
338
+ d = _run(f"[HARD] Sıra geri al", _unshuffle, d, k["shuffle"])
339
+ return _run(f"[HARD] XOR tersle", _xor, d, k["xor"])
340
+
341
+ elif level == 4:
342
+ d = d[len(k["salt"]):]
343
+ d = _run(f"[DEVIL] Sıra geri al", _unshuffle, d, k["shuffle"])
344
+ d = _run(f"[DEVIL] XOR tersle", _xor, d, k["xor"])
345
+ return _run(f"[DEVIL] Vigenere tersle", _vigenere_dec, d, k["vigenere"])
346
+
347
+ elif level == 5:
348
+ if show_progress:
349
+ d = _real_progress("[IMPOSSIBLE] Açılıyor", zlib.decompress, d,
350
+ color=col)
351
+ else:
352
+ d = zlib.decompress(d)
353
+ pad_len = struct.unpack("<H", d[:2])[0]
354
+ d = d[2 + pad_len:]
355
+ for turn in range(2, -1, -1):
356
+ tk = _derive_keys(password + str(turn))
357
+ d = d[len(tk["salt"]):]
358
+ d = _run(f"[IMPOSSIBLE] Tur {turn+1}/3 — Sıra geri al",
359
+ _unshuffle, d, tk["shuffle"])
360
+ d = _run(f"[IMPOSSIBLE] Tur {turn+1}/3 — XOR tersle",
361
+ _xor, d, tk["xor"])
362
+ d = _run(f"[IMPOSSIBLE] Tur {turn+1}/3 — Vigenere tersle",
363
+ _vigenere_dec, d, tk["vigenere"])
364
+ return d
365
+
366
+ raise ValueError(f"Geçersiz seviye: {level}")
367
+
368
+ # ─────────────────────────────────────────────────────────────────────────────
369
+ # GÖRSEL & YARDIMCI
370
+ # ─────────────────────────────────────────────────────────────────────────────
371
+
372
+ ASCII_LOGO = f"""\
373
+ {C.GREEN}{C.BOLD}
374
+ ██████╗██╗██████╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗
375
+ ██╔════╝██║██╔══██╗██║ ██║██╔════╝██╔══██╗ ╚██╗██╔╝
376
+ ██║ ██║██████╔╝███████║█████╗ ██████╔╝ ████╗╚███╔╝
377
+ ██║ ██║██╔═══╝ ██╔══██║██╔══╝ ██╔══██╗ ╚═══╝██╔██╗
378
+ ╚██████╗██║██║ ██║ ██║███████╗██║ ██║ ██╔╝ ██╗
379
+ ╚═════╝╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝
380
+ {C.RESET}{C.GREEN_DIM} Gelişmiş Terminal Şifreleme Aracı v3.0{C.RESET}"""
381
+
382
+ DIVIDER = f"{C.GREEN_DIM}{'═' * 60}{C.RESET}"
383
+ THIN_DIV = f"{C.GREEN_DIM}{'─' * 60}{C.RESET}"
384
+
385
+ def clear():
386
+ os.system("cls" if os.name == "nt" else "clear")
387
+
388
+ def prompt(text="", color=C.GREEN_DIM):
389
+ return input(f"{color}{text}root@cipher:~$ {C.RESET}")
390
+
391
+ def info(msg): print(f" {C.GREEN_DIM}► {msg}{C.RESET}")
392
+ def success(msg): print(f" {C.GREEN}✓ {msg}{C.RESET}")
393
+ def warn(msg): print(f" {C.AMBER}⚠ {msg}{C.RESET}")
394
+ def error(msg): print(f" {C.RED}✗ {msg}{C.RESET}")
395
+ def label(msg): print(f"\n {C.CYAN}{msg}{C.RESET}")
396
+
397
+ def progress_bar(label_text: str, duration: float = 0.6, width: int = 44, color=C.GREEN):
398
+ steps = 35
399
+ for i in range(steps + 1):
400
+ pct = i / steps
401
+ filled = int(width * pct)
402
+ bar = "█" * filled + "░" * (width - filled)
403
+ bar_c = color if pct < 0.8 else C.AMBER
404
+ print(f"\r {C.GREEN_DIM}{label_text}{C.RESET} "
405
+ f"[{bar_c}{bar}{C.RESET}] "
406
+ f"{C.WHITE}{int(pct*100):3d}%{C.RESET}", end="", flush=True)
407
+ time.sleep(duration / steps)
408
+ print()
409
+
410
+ def matrix_rain(rows=3, cols=56, duration=0.6):
411
+ chars = list(CHARS) + list("01░▒▓")
412
+ end_t = time.time() + duration
413
+ while time.time() < end_t:
414
+ for _ in range(rows):
415
+ line = "".join(random.choice(chars) for _ in range(cols))
416
+ print(f" {C.GREEN_DIM}{line}{C.RESET}")
417
+ time.sleep(0.07)
418
+ print(f"\033[{rows}A", end="")
419
+ print(f"\033[{rows}B", end="")
420
+
421
+ def hacker_animasyon(cozulmus: str, sifreli: str):
422
+ print()
423
+ info("Şifre çözme protokolü başlatıldı...")
424
+ time.sleep(0.3)
425
+ print()
426
+ matrix_rain(rows=2, duration=0.5)
427
+ print()
428
+ progress_bar("Analiz ediliyor", duration=0.7)
429
+ print()
430
+ print(f" {C.GREEN_DIM}», ", end="", flush=True)
431
+ for i in range(len(cozulmus) + 1):
432
+ gorunen = cozulmus[:i]
433
+ kalan = sifreli[i*3 : i*3 + min(24, len(sifreli) - i*3)]
434
+ print(f"\r {C.GREEN}» {gorunen}{C.GREEN_DIM}{kalan}{' ' * 6}",
435
+ end="", flush=True)
436
+ time.sleep(0.06)
437
+ print(f"\r {C.GREEN}» {cozulmus}{' ' * 30}{C.RESET}")
438
+ print()
439
+
440
+ def devil_animasyon(level: int):
441
+ """Seviyeye özel başlangıç animasyonu."""
442
+ name, col, sym, _ = LEVELS[level]
443
+ if level <= 2:
444
+ progress_bar(f"[{name}] Şifreleniyor", duration=0.5, color=col)
445
+ elif level == 3:
446
+ print()
447
+ matrix_rain(rows=2, duration=0.4)
448
+ progress_bar(f"[{name}] Karıştırılıyor", duration=0.7, color=col)
449
+ elif level == 4:
450
+ print()
451
+ matrix_rain(rows=3, duration=0.6)
452
+ progress_bar(f"[{name}] Katmanlar uygulanıyor", duration=1.0, color=col)
453
+ elif level == 5:
454
+ print()
455
+ for _ in range(3):
456
+ matrix_rain(rows=2, duration=0.4)
457
+ time.sleep(0.1)
458
+ progress_bar(f"[{name}] Tur 1/3", duration=0.8, color=col)
459
+ progress_bar(f"[{name}] Tur 2/3", duration=0.8, color=col)
460
+ progress_bar(f"[{name}] Tur 3/3", duration=0.8, color=col)
461
+ progress_bar(f"[{name}] Finalize", duration=0.5, color=col)
462
+
463
+ # ─────────────────────────────────────────────────────────────────────────────
464
+ # DOSYA OKUMA / YAZMA
465
+ # ─────────────────────────────────────────────────────────────────────────────
466
+
467
+ def oku_dosya(path: str) -> bytes:
468
+ """Her türlü dosyayı bytes olarak oku."""
469
+ with open(path, "rb") as f:
470
+ return f.read()
471
+
472
+ def yaz_dosya(path: str, data: bytes):
473
+ with open(path, "wb") as f:
474
+ f.write(data)
475
+
476
+ def temizle_yol(p: str) -> str:
477
+ return p.strip().strip('"').strip("'")
478
+
479
+ # ─────────────────────────────────────────────────────────────────────────────
480
+ # .CIPHERX DOSYA FORMATI
481
+ # CIPHERX3 (eski): CIPHERX3:<seviye>:<ext>:<tip>\n + şifreli veri (MAC yok)
482
+ # CIPHERX4 (yeni): CIPHERX4:<seviye>:<ext>:<tip>\n + şifreli veri (MAC tag dahil)
483
+ # ─────────────────────────────────────────────────────────────────────────────
484
+
485
+ MAGIC_V3 = "CIPHERX3" # geriye uyumluluk (MAC yok)
486
+ MAGIC_V4 = "CIPHERX4" # yeni format (MAC tag gömülü)
487
+ MAGIC = MAGIC_V4 # yeni dosyalar için
488
+
489
+ def build_header(level: int, ext: str, tip: str) -> bytes:
490
+ return f"{MAGIC}:{level}:{ext}:{tip}\n".encode("utf-8")
491
+
492
+ def parse_header(raw: bytes) -> tuple:
493
+ """(level, ext, tip, rest_data, has_mac) döndür."""
494
+ try:
495
+ nl = raw.index(b"\n")
496
+ header = raw[:nl].decode("utf-8")
497
+ rest = raw[nl+1:]
498
+ parts = header.split(":")
499
+ if len(parts) < 4:
500
+ raise ValueError()
501
+ magic = parts[0]
502
+ if magic == MAGIC_V4:
503
+ has_mac = True
504
+ elif magic == MAGIC_V3:
505
+ has_mac = False
506
+ else:
507
+ raise ValueError()
508
+ return int(parts[1]), parts[2], parts[3], rest, has_mac
509
+ except Exception:
510
+ raise ValueError("Geçersiz veya eski format CIPHERX dosyası.")
511
+
512
+ # ─────────────────────────────────────────────────────────────────────────────
513
+ # ŞİFRE SEÇİM MENÜSÜ
514
+ # ─────────────────────────────────────────────────────────────────────────────
515
+
516
+ def sifre_sec_ekran() -> tuple[int, str]:
517
+ """(level, password) döndür. İptal için (0, '') """
518
+ print()
519
+ print(f" {THIN_DIV}")
520
+ print(f" {C.BOLD}{C.WHITE} Şifreleme Seviyesi Seç:{C.RESET}")
521
+ print(f" {THIN_DIV}")
522
+ for lvl, (name, col, sym, desc) in LEVELS.items():
523
+ print(f" {col}[{lvl}] {sym} {name:<12}{C.RESET} {C.GRAY}{desc}{C.RESET}")
524
+ print(f" {C.GRAY}[0] İptal{C.RESET}")
525
+ print(f" {THIN_DIV}")
526
+ print()
527
+
528
+ while True:
529
+ secim = prompt("Seviye (1-5): ").strip()
530
+ if secim == "0": return 0, ""
531
+ if secim.isdigit() and 1 <= int(secim) <= 5:
532
+ level = int(secim)
533
+ break
534
+ warn("Geçersiz seviye.")
535
+
536
+ name, col, sym, _ = LEVELS[level]
537
+ print()
538
+
539
+ if level == 1:
540
+ info(f"{col}{name}{C.RESET} — şifre gerektirmez, Enter'a bas.")
541
+ password = ""
542
+ else:
543
+ import getpass
544
+ print(f" {col}{sym} {name} seviyesi için şifre belirle:{C.RESET}")
545
+ while True:
546
+ try:
547
+ pw1 = getpass.getpass(f" {C.GREEN_DIM}Şifre: {C.RESET}")
548
+ pw2 = getpass.getpass(f" {C.GREEN_DIM}Tekrar: {C.RESET}")
549
+ except Exception:
550
+ # getpass desteklenmiyorsa
551
+ pw1 = prompt("Şifre: ")
552
+ pw2 = pw1
553
+ if pw1 == pw2 and pw1:
554
+ password = pw1
555
+ break
556
+ warn("Şifreler eşleşmedi veya boş, tekrar dene.")
557
+
558
+ print()
559
+ return level, password
560
+
561
+ def sifre_gir_ekran(level: int) -> str:
562
+ """Çözme için şifre gir."""
563
+ name, col, sym, _ = LEVELS[level]
564
+ if level == 1:
565
+ return ""
566
+ import getpass
567
+ print(f" {col}{sym} {name} — Şifreyi gir:{C.RESET}")
568
+ try:
569
+ return getpass.getpass(f" {C.GREEN_DIM}Şifre: {C.RESET}")
570
+ except Exception:
571
+ return prompt("Şifre: ")
572
+
573
+ # ─────────────────────────────────────────────────────────────────────────────
574
+ # İSTATİSTİK & GEÇMİŞ
575
+ # ─────────────────────────────────────────────────────────────────────────────
576
+
577
+ @dataclass
578
+ class GirdiCikti:
579
+ tip: str
580
+ girdi: str
581
+ cikti: str
582
+ zaman: str
583
+ seviye: str = "?"
584
+
585
+ HISTORY_FILE = os.path.join(os.path.expanduser("~"), ".cipher_crypter_history.json")
586
+ stats = {"enc": 0, "dec": 0, "bytes": 0}
587
+ history: list[GirdiCikti] = []
588
+
589
+ def load_history():
590
+ global history
591
+ if os.path.exists(HISTORY_FILE):
592
+ try:
593
+ with open(HISTORY_FILE, "r", encoding="utf-8") as f:
594
+ raw = json.load(f)
595
+ history = []
596
+ for item in raw:
597
+ if isinstance(item, dict):
598
+ item.setdefault("seviye", "?")
599
+ history.append(GirdiCikti(**item))
600
+ except Exception:
601
+ history = []
602
+
603
+ def save_history():
604
+ try:
605
+ with open(HISTORY_FILE, "w", encoding="utf-8") as f:
606
+ json.dump([asdict(h) for h in history[-100:]], f,
607
+ ensure_ascii=False, indent=2)
608
+ except Exception:
609
+ pass
610
+
611
+ def add_to_history(tip, girdi, cikti, seviye="?"):
612
+ history.append(GirdiCikti(
613
+ tip=tip, girdi=girdi, cikti=cikti,
614
+ zaman=datetime.datetime.now().strftime("%d.%m.%Y %H:%M:%S"),
615
+ seviye=seviye,
616
+ ))
617
+ save_history()
618
+
619
+ def show_stats():
620
+ print(f"\n {THIN_DIV}")
621
+ print(f" {C.GREEN_DIM} ŞİFRELENEN {C.GREEN}{stats['enc']:>5}{C.RESET}"
622
+ f" {C.GREEN_DIM}ÇÖZÜLEN {C.GREEN}{stats['dec']:>5}{C.RESET}"
623
+ f" {C.GREEN_DIM}TOPLAM {C.GREEN}{stats['bytes']/1024:>8.1f} KB{C.RESET}")
624
+ print(f" {THIN_DIV}\n")
625
+
626
+ # ─────────────────────────────────────────────────────────────────────────────
627
+ # MENÜ & HEADER
628
+ # ─────────────────────────────────────────────────────────────────────────────
629
+
630
+ def draw_header():
631
+ clear()
632
+ print(ASCII_LOGO)
633
+ print(DIVIDER)
634
+ show_stats()
635
+
636
+ def show_menu():
637
+ print(f" {C.GREEN}[1]{C.RESET} {C.WHITE}Şifrele{C.RESET} "
638
+ f"{C.GRAY}(metin · txt · mp4 · mp3 · zip · docx · bilinmeyen...){C.RESET}")
639
+ print(f" {C.GREEN}[2]{C.RESET} {C.WHITE}Şifre Çöz{C.RESET} "
640
+ f"{C.GRAY}(.cipherx dosyası veya şifreli metin){C.RESET}")
641
+ print(f" {C.GREEN}[3]{C.RESET} {C.WHITE}Hızlı Test{C.RESET} "
642
+ f"{C.GRAY}(Şifrele → Çöz → Doğrula){C.RESET}")
643
+ print(f" {C.GREEN}[4]{C.RESET} {C.WHITE}Geçmiş{C.RESET}")
644
+ print(f" {C.GREEN}[5]{C.RESET} {C.WHITE}Hakkında{C.RESET}")
645
+ print(f" {C.RED}[0]{C.RESET} {C.GRAY}Çıkış{C.RESET}")
646
+ print()
647
+
648
+ # ─────────────────────────────────────────────────────────────────────────────
649
+ # EKRANLAR
650
+ # ─────────────────────────────────────────────────────────────────────────────
651
+
652
+ def ekran_sifrele():
653
+ draw_header()
654
+ label("ŞİFRELEME MODU")
655
+ print(THIN_DIV)
656
+ girdi = prompt("Dosya yolu veya şifrelenecek metin: ")
657
+ if not girdi:
658
+ warn("Boş girdi."); time.sleep(1); return
659
+
660
+ girdi = temizle_yol(girdi)
661
+
662
+ # Dosya mı, metin mi?
663
+ if os.path.exists(girdi):
664
+ tip = dosya_tipi(girdi)
665
+ try:
666
+ data = oku_dosya(girdi)
667
+ except Exception as exc:
668
+ error(f"Dosya okunamadı: {exc}"); time.sleep(2); return
669
+ orijinal_ext = os.path.splitext(girdi)[1].lower() or ".bin"
670
+ kaynak_etiket = f"{girdi} ({len(data)/1024:.1f} KB, {tip})"
671
+ is_file = True
672
+ else:
673
+ # Metin girişi
674
+ data = girdi.encode("utf-8")
675
+ orijinal_ext = ".txt"
676
+ tip = "text"
677
+ kaynak_etiket = f"metin ({len(data)} byte)"
678
+ is_file = False
679
+
680
+ info(f"Kaynak: {kaynak_etiket}")
681
+ print()
682
+
683
+ # Seviye & şifre seç
684
+ level, password = sifre_sec_ekran()
685
+ if level == 0: return
686
+
687
+ name, col, sym, _ = LEVELS[level]
688
+ print()
689
+ # devil_animasyon artık enc_level içinde gerçek progress olarak gösteriliyor
690
+
691
+ try:
692
+ sifreli_data = enc_level(data, level, password, show_progress=True)
693
+ except Exception as exc:
694
+ error(f"Şifreleme hatası: {exc}"); time.sleep(2); return
695
+
696
+ header = build_header(level, orijinal_ext, tip)
697
+ son_veri = header + sifreli_data
698
+
699
+ # Çıktı yolu
700
+ if is_file:
701
+ default_out = os.path.splitext(girdi)[0] + ".cipherx"
702
+ else:
703
+ default_out = os.path.join(os.getcwd(), "output.cipherx")
704
+
705
+ out_yol = prompt(f"Çıktı dosyası [Enter = {default_out}]: ").strip().strip('"').strip("'")
706
+ if not out_yol: out_yol = default_out
707
+ if not out_yol.lower().endswith(".cipherx"):
708
+ out_yol += ".cipherx"
709
+
710
+ try:
711
+ yaz_dosya(out_yol, son_veri)
712
+ except Exception as exc:
713
+ error(f"Kaydedilemedi: {exc}"); time.sleep(2); return
714
+
715
+ print()
716
+ success(f"Şifreleme tamamlandı!")
717
+ info(f"Seviye : {col}{sym} {name}{C.RESET}")
718
+ info(f"Çıktı : {out_yol}")
719
+ info(f"Boyut : {len(data)/1024:.1f} KB → {len(son_veri)/1024:.1f} KB")
720
+ print()
721
+ stats["enc"] += 1
722
+ stats["bytes"] += len(data)
723
+ add_to_history("ENC", girdi[:60], out_yol, name)
724
+ input(f" {C.GRAY}[ Devam için Enter ]{C.RESET} ")
725
+
726
+
727
+ def ekran_coz():
728
+ draw_header()
729
+ label("ŞİFRE ÇÖZME MODU")
730
+ print(THIN_DIV)
731
+ girdi = prompt("Şifreli metin veya .cipherx dosya yolu: ")
732
+ if not girdi:
733
+ warn("Boş girdi."); time.sleep(1); return
734
+
735
+ girdi = temizle_yol(girdi)
736
+
737
+ # .cipherx dosyası mı?
738
+ if girdi.lower().endswith(".cipherx") or (os.path.exists(girdi) and _is_cipherx(girdi)):
739
+ if not os.path.exists(girdi):
740
+ error(f"Dosya bulunamadı: {girdi}"); time.sleep(2); return
741
+ _coz_dosya(girdi)
742
+ return
743
+
744
+ # Eski format metin mi? (EASY seviyesi, şifresiz)
745
+ _coz_metin(girdi)
746
+
747
+
748
+ def _is_cipherx(path: str) -> bool:
749
+ try:
750
+ with open(path, "rb") as f:
751
+ start = f.read(len(MAGIC))
752
+ return start == MAGIC.encode("utf-8")
753
+ except Exception:
754
+ return False
755
+
756
+
757
+ def _coz_dosya(dosya_yolu: str):
758
+ try:
759
+ raw = oku_dosya(dosya_yolu)
760
+ except Exception as exc:
761
+ error(f"Dosya okunamadı: {exc}"); time.sleep(2); return
762
+
763
+ try:
764
+ level, orijinal_ext, tip, sifreli_data, has_mac = parse_header(raw)
765
+ except ValueError as exc:
766
+ error(str(exc)); time.sleep(2); return
767
+
768
+ name, col, sym, _ = LEVELS.get(level, (str(level), C.WHITE, "?", ""))
769
+ info(f"Seviye algılandı: {col}{sym} {name}{C.RESET}")
770
+ info(f"Orijinal uzantı : {orijinal_ext} | Tip: {tip}")
771
+ print()
772
+
773
+ password = sifre_gir_ekran(level)
774
+ print()
775
+
776
+ try:
777
+ orijinal_data = dec_level(sifreli_data, level, password, show_progress=True, has_mac=has_mac)
778
+ except ValueError as exc:
779
+ msg = str(exc)
780
+ if "Hatalı şifre" in msg:
781
+ print()
782
+ error("╔══════════════════════════════════════════╗")
783
+ error("║ ✗ HATALI ŞİFRE — Çözme iptal edildi ║")
784
+ error("╚══════════════════════════════════════════╝")
785
+ else:
786
+ error(f"Çözme hatası: {exc}")
787
+ time.sleep(2); return
788
+ except Exception as exc:
789
+ error(f"Çözme hatası: {exc}"); time.sleep(2); return
790
+
791
+ base = os.path.splitext(dosya_yolu)[0]
792
+ default_out = base + ".recovered" + orijinal_ext
793
+ out_yol = prompt(f"Çıktı dosyası [Enter = {default_out}]: ").strip().strip('"').strip("'")
794
+ if not out_yol: out_yol = default_out
795
+
796
+ try:
797
+ yaz_dosya(out_yol, orijinal_data)
798
+ except Exception as exc:
799
+ error(f"Kaydedilemedi: {exc}"); time.sleep(2); return
800
+
801
+ print()
802
+ success(f"Çözme tamamlandı!")
803
+ info(f"Seviye : {col}{sym} {name}{C.RESET}")
804
+ info(f"Çıktı : {out_yol}")
805
+ info(f"Boyut : {len(orijinal_data)/1024:.1f} KB kurtarıldı")
806
+
807
+ # Metin ise ekrana da göster
808
+ if tip == "text" and len(orijinal_data) < 2000:
809
+ try:
810
+ metin_str = orijinal_data.decode("utf-8")
811
+ print()
812
+ hacker_animasyon(metin_str, sifreli_data.decode("utf-8", errors="replace"))
813
+ except Exception:
814
+ pass
815
+ print()
816
+ stats["dec"] += 1
817
+ stats["bytes"] += len(orijinal_data)
818
+ add_to_history("DEC", dosya_yolu, out_yol, name)
819
+ input(f" {C.GRAY}[ Devam için Enter ]{C.RESET} ")
820
+
821
+
822
+ def _coz_metin(sifreli_str: str):
823
+ """Eski tarz düz metin şifresi çöz (seviye 1 varsayılan)."""
824
+ info("Düz metin modu (EASY seviyesi varsayılıyor)...")
825
+ print()
826
+ progress_bar("Analiz ediliyor", duration=0.5)
827
+ try:
828
+ # Önce EASY dene
829
+ data = sifreli_str.encode("utf-8")
830
+ orijinal = dec_level(data, 1, "")
831
+ metin = orijinal.decode("utf-8")
832
+ except Exception:
833
+ error("Geçersiz şifreli veri! Semboller tanınamadı veya format hatalı.")
834
+ info("Not: Şifre korumalı dosyalar için .cipherx formatını kullanın.")
835
+ time.sleep(2); return
836
+
837
+ hacker_animasyon(metin, sifreli_str)
838
+ print()
839
+ out_yol = prompt("Çıktı dosyası [boş = ekrana yaz]: ").strip().strip('"').strip("'")
840
+ if out_yol:
841
+ try:
842
+ yaz_dosya(out_yol, metin.encode("utf-8"))
843
+ success(f"Kaydedildi: {out_yol}")
844
+ except Exception as exc:
845
+ error(f"Kaydedilemedi: {exc}")
846
+ else:
847
+ success(f"Çözülen metin ({len(metin)} karakter):")
848
+ print(f" {C.WHITE}{metin}{C.RESET}")
849
+ print()
850
+ stats["dec"] += 1
851
+ stats["bytes"] += len(metin)
852
+ add_to_history("DEC", sifreli_str[:40], metin[:40], "EASY")
853
+ input(f" {C.GRAY}[ Devam için Enter ]{C.RESET} ")
854
+
855
+
856
+ def ekran_hizli_test():
857
+ draw_header()
858
+ label("HIZLI TEST MODU")
859
+ print(THIN_DIV)
860
+
861
+ metin = prompt("Test Metni: ")
862
+ if not metin:
863
+ warn("Boş metin."); time.sleep(1); return
864
+
865
+ level, password = sifre_sec_ekran()
866
+ if level == 0: return
867
+
868
+ name, col, sym, _ = LEVELS[level]
869
+ data = metin.encode("utf-8")
870
+ print()
871
+
872
+ info(f"Adım 1/3 — {col}{sym} {name}{C.RESET} şifreleniyor...")
873
+ progress_bar("", duration=0.5, color=col)
874
+ try:
875
+ enc = enc_level(data, level, password)
876
+ except Exception as exc:
877
+ error(f"Şifreleme hatası: {exc}"); time.sleep(2); return
878
+ preview = enc[:60].decode("utf-8", errors="replace")
879
+ success(f"Şifreli: {preview}{'…' if len(enc) > 60 else ''}")
880
+ print()
881
+
882
+ info("Adım 2/3 — Çözülüyor...")
883
+ progress_bar("", duration=0.5, color=col)
884
+ try:
885
+ dec_data = dec_level(enc, level, password)
886
+ dec = dec_data.decode("utf-8")
887
+ except Exception as exc:
888
+ error(f"Çözme hatası: {exc}"); time.sleep(2); return
889
+ success(f"Çözülen: {dec[:60]}{'…' if len(dec) > 60 else ''}")
890
+ print()
891
+
892
+ info("Adım 3/3 — Doğrulanıyor...")
893
+ progress_bar("", duration=0.3)
894
+ ok = dec == metin
895
+ print()
896
+ if ok:
897
+ success(f"TEST BAŞARILI ✓ — {col}{sym} {name}{C.RESET} tutarlı!")
898
+ else:
899
+ error("TEST BAŞARISIZ ✗ — Tutarsızlık tespit edildi!")
900
+ print()
901
+ info(f"Orijinal boyut : {len(data)} byte")
902
+ info(f"Şifreli boyut : {len(enc)} byte ({len(enc)/len(data):.1f}x)")
903
+ print()
904
+ input(f" {C.GRAY}[ Devam için Enter ]{C.RESET} ")
905
+
906
+
907
+ def ekran_gecmis():
908
+ draw_header()
909
+ label("GEÇMİŞ")
910
+ print(THIN_DIV)
911
+ if not history:
912
+ info("Geçmiş boş.")
913
+ input(f"\n {C.GRAY}[ Devam için Enter ]{C.RESET} ")
914
+ return
915
+ gorunen = history[-15:][::-1]
916
+ for i, h in enumerate(gorunen, 1):
917
+ tip_str = f"{C.GREEN}ŞİF{C.RESET}" if "ENC" in h.tip else f"{C.AMBER}ÇÖZ{C.RESET}"
918
+ sev_col = next((LEVEL_COLORS[k] for k,v in LEVELS.items() if v[0]==h.seviye), C.GRAY)
919
+ plain_k = h.girdi[:30] + ("…" if len(h.girdi) > 30 else "")
920
+ print(f" {C.GRAY}{i:>2}.{C.RESET} [{tip_str}] "
921
+ f"{sev_col}[{h.seviye:<10}]{C.RESET} "
922
+ f"{C.WHITE}{plain_k:<33}{C.RESET} "
923
+ f"{C.GRAY}{h.zaman}{C.RESET}")
924
+ print()
925
+ input(f" {C.GRAY}[ Devam için Enter ]{C.RESET} ")
926
+
927
+
928
+ def ekran_hakkinda():
929
+ draw_header()
930
+ label("HAKKINDA")
931
+ print(THIN_DIV)
932
+ lines = [
933
+ ("Cipher Crypter v3.0", C.WHITE),
934
+ ("Gelişmiş Terminal Şifreleme Aracı", C.GREEN_DIM),
935
+ ("", ""),
936
+ ("SEVİYELER:", C.CYAN),
937
+ (f" {C.GREEN}[1] ░ EASY {C.GRAY}Temel sembol kodlama (şifresiz)", ""),
938
+ (f" {C.CYAN}[2] ▒ MEDIUM {C.GRAY}Sembol + XOR katmanı", ""),
939
+ (f" {C.AMBER}[3] ▓ HARD {C.GRAY}Sembol + XOR + Byte karıştırma", ""),
940
+ (f" {C.RED}[4] ▲ DEVIL {C.GRAY}HARD + Vigenere + Tuz", ""),
941
+ (f" {C.MAGENTA}[5] ☠ IMPOSSIBLE{C.GRAY} DEVIL × 3 tur + Padding + Zlib", ""),
942
+ ("", ""),
943
+ ("DOSYA DESTEĞİ:", C.CYAN),
944
+ (" mp4 · mp3 · wav · flac · ogg (ses/video)", C.GRAY),
945
+ (" png · jpg · gif · webp · svg (resim)", C.GRAY),
946
+ (" zip · rar · 7z · tar · gz · iso (arşiv)", C.GRAY),
947
+ (" pdf · docx · xlsx · pptx (ofis)", C.GRAY),
948
+ (" csv · json · xml · db · sqlite (veri)", C.GRAY),
949
+ (" exe · apk · bin · dll (uygulama)", C.GRAY),
950
+ (" + bilinmeyen uzantılar otomatik binary olarak şifrelenir", C.GREEN_DIM),
951
+ ("", ""),
952
+ ("FORMAT:", C.CYAN),
953
+ (" .cipherx — Tüm metadata header'da saklanır.", C.GRAY),
954
+ (" Çözerken seviye & uzantı otomatik algılanır.", C.GRAY),
955
+ ("", ""),
956
+ ("Geliştirici:", C.GREEN_DIM),
957
+ ("JosephX", C.GREEN),
958
+ ]
959
+ for text, color in lines:
960
+ if text == "":
961
+ print()
962
+ else:
963
+ print(f" {color}{text}{C.RESET}")
964
+ print()
965
+ input(f" {C.GRAY}[ Devam için Enter ]{C.RESET} ")
966
+
967
+
968
+ # ─────────────────────────────────────────────────────────────────────────────
969
+ # ANA DÖNGÜ
970
+ # ─────────────────────────────────────────────────────────────────────────────
971
+
972
+ def main():
973
+ load_history()
974
+ while True:
975
+ draw_header()
976
+ show_menu()
977
+ secim = prompt().strip()
978
+ if secim == "1": ekran_sifrele()
979
+ elif secim == "2": ekran_coz()
980
+ elif secim == "3": ekran_hizli_test()
981
+ elif secim == "4": ekran_gecmis()
982
+ elif secim == "5": ekran_hakkinda()
983
+ elif secim == "0":
984
+ clear()
985
+ print(f"\n {C.GREEN}İyi günler!{C.RESET}\n")
986
+ sys.exit(0)
987
+ else:
988
+ warn("Geçersiz seçim."); time.sleep(0.8)
989
+
990
+ if __name__ == "__main__":
991
+ main()
@@ -0,0 +1,7 @@
1
+ Metadata-Version: 2.1
2
+ Name: cipher-crypter
3
+ Version: 3.0.0
4
+ Summary: Gelişmiş Terminal Şifreleme Aracı
5
+ Author: JosephX
6
+ Requires-Python: >=3.6
7
+
@@ -0,0 +1,7 @@
1
+ cipher_crypter/__init__.py,sha256=pKtrXU-VRct109vbaZQ0DAvZOVVUyX9Ty63Xl1nsAy4,23
2
+ cipher_crypter/cli.py,sha256=a8wXqeQccJC-h-MzC72AnXGZF6x4BhNzHOsl8sEt9WE,39988
3
+ cipher_crypter-3.0.0.dist-info/METADATA,sha256=BapyotD77tFHaOvHG_1x0GfZrjcbPJOhsWlL6DzPz5I,152
4
+ cipher_crypter-3.0.0.dist-info/WHEEL,sha256=51RkbunBAw4BWsgaQWTpPhg4Diwp3c9P5iaLk67Hdtg,92
5
+ cipher_crypter-3.0.0.dist-info/entry_points.txt,sha256=h5hpTQcTnbPjGiFRybQYVBj09OXYCASbrxQOH_dZxFA,59
6
+ cipher_crypter-3.0.0.dist-info/top_level.txt,sha256=pQNLRrMcL7J1mSOU6UV_RpVzqS7TgeMZySAKK3xTKeY,15
7
+ cipher_crypter-3.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.47.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cipher-crypter = cipher_crypter.cli:main
@@ -0,0 +1 @@
1
+ cipher_crypter