rtty-soda 0.1.5__py3-none-any.whl → 0.2.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.

Potentially problematic release.


This version of rtty-soda might be problematic. Click here for more details.

rtty_soda/main.py CHANGED
@@ -1,6 +1,3 @@
1
- # ruff: noqa: PLR0913 - not applicable because we don't call Click Commands directly
2
- # ruff: noqa: ANN201 - not applicable because the Click Commands are untyped
3
- # mypy: disable-error-code = "no-untyped-def, misc"
4
1
  from pathlib import Path
5
2
 
6
3
  import click
@@ -11,14 +8,13 @@ from rtty_soda.archivers import ARCHIVERS, UNARCHIVERS
11
8
  from rtty_soda.cli_io import (
12
9
  print_stats,
13
10
  read_bytes,
14
- read_ciphertext_bytes,
15
- read_clean_bytes,
16
- read_plaintext_bytes,
11
+ read_key_bytes,
12
+ read_password_bytes,
17
13
  write_output,
18
14
  )
19
15
  from rtty_soda.cryptography import public, secret
20
16
  from rtty_soda.cryptography.kdf import KDF_PROFILES, kdf
21
- from rtty_soda.encoders import ENCODERS, RawEncoder
17
+ from rtty_soda.encoders import ENCODERS
22
18
 
23
19
  in_path = click.Path(
24
20
  exists=True,
@@ -38,62 +34,129 @@ CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]}
38
34
 
39
35
  @click.group(cls=ClickAliasedGroup, context_settings=CONTEXT_SETTINGS)
40
36
  @click.version_option(package_name="rtty-soda")
41
- def cli():
37
+ def cli() -> None:
42
38
  pass
43
39
 
44
40
 
45
- @cli.command()
41
+ @cli.command() # pyright: ignore[reportAny]
46
42
  @click.option("--encoding", "-e", default="base64", show_default=True)
47
- def genkey_cmd(encoding: str):
43
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
44
+ @click.option("--group-len", default=0, show_default=True)
45
+ @click.option("--line-len", default=0, show_default=True)
46
+ @click.option("--padding", default=0, show_default=True)
47
+ def genkey_cmd(
48
+ encoding: str, output_file: Path | None, group_len: int, line_len: int, padding: int
49
+ ) -> None:
48
50
  """Generate Private Key.
49
51
 
50
- Encoding: base26 | base36 | base64 | base94
52
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
51
53
  """
52
54
  enc = ENCODERS[encoding]
53
- key = PrivateKey.generate()
54
- click.echo(key.encode(enc))
55
+ is_bin = encoding == "binary"
55
56
 
57
+ key = bytes(PrivateKey.generate())
58
+ key = enc.encode(key)
56
59
 
57
- @cli.command()
60
+ write_output(
61
+ target=output_file,
62
+ data=key,
63
+ is_binary=is_bin,
64
+ group_len=group_len,
65
+ line_len=line_len,
66
+ padding=padding,
67
+ )
68
+
69
+
70
+ @cli.command() # pyright: ignore[reportAny]
58
71
  @click.argument("private_key_file", type=in_path)
59
72
  @click.option("--encoding", "-e", default="base64", show_default=True)
60
- def pubkey_cmd(private_key_file: Path, encoding: str):
73
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
74
+ @click.option("--group-len", default=0, show_default=True)
75
+ @click.option("--line-len", default=0, show_default=True)
76
+ @click.option("--padding", default=0, show_default=True)
77
+ def pubkey_cmd(
78
+ private_key_file: Path,
79
+ encoding: str,
80
+ output_file: Path | None,
81
+ group_len: int,
82
+ line_len: int,
83
+ padding: int,
84
+ ) -> None:
61
85
  """Get Public Key.
62
86
 
63
- Encoding: base26 | base36 | base64 | base94
87
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
64
88
  """
65
89
  enc = ENCODERS[encoding]
66
- key = read_clean_bytes(private_key_file)
67
- priv = PrivateKey(key, enc)
68
- click.echo(priv.public_key.encode(enc))
90
+ is_bin = encoding == "binary"
69
91
 
92
+ priv = read_key_bytes(source=private_key_file, is_binary=is_bin, encoder=enc)
93
+ priv = PrivateKey(private_key=priv)
94
+ pub = bytes(priv.public_key)
95
+ pub = enc.encode(pub)
70
96
 
71
- @cli.command()
97
+ write_output(
98
+ target=output_file,
99
+ data=pub,
100
+ is_binary=is_bin,
101
+ group_len=group_len,
102
+ line_len=line_len,
103
+ padding=padding,
104
+ )
105
+
106
+
107
+ @cli.command() # pyright: ignore[reportAny]
72
108
  @click.argument("password_file", type=in_path)
73
109
  @click.option("--encoding", "-e", default="base64", show_default=True)
74
110
  @click.option("--profile", "-p", default="sensitive", show_default=True)
75
- def kdf_cmd(password_file: Path, encoding: str, profile: str):
111
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
112
+ @click.option("--group-len", default=0, show_default=True)
113
+ @click.option("--line-len", default=0, show_default=True)
114
+ @click.option("--padding", default=0, show_default=True)
115
+ def kdf_cmd(
116
+ password_file: Path,
117
+ encoding: str,
118
+ profile: str,
119
+ output_file: Path | None,
120
+ group_len: int,
121
+ line_len: int,
122
+ padding: int,
123
+ ) -> None:
76
124
  """Key Derivation Function.
77
125
 
78
- Encoding: base26 | base36 | base64 | base94
126
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
79
127
 
80
128
  Profile: interactive | moderate | sensitive
81
129
  """
82
130
  enc = ENCODERS[encoding]
83
131
  prof = KDF_PROFILES[profile]
84
- pw = read_bytes(password_file)
85
- key = kdf(pw, prof, enc)
86
- click.echo(key)
132
+ is_bin = encoding == "binary"
133
+
134
+ pw = read_password_bytes(password_file)
135
+ key = kdf(password=pw, profile=prof)
136
+ key = enc.encode(key)
137
+
138
+ write_output(
139
+ target=output_file,
140
+ data=key,
141
+ is_binary=is_bin,
142
+ group_len=group_len,
143
+ line_len=line_len,
144
+ padding=padding,
145
+ )
87
146
 
88
147
 
89
- @cli.command(aliases=["e"])
148
+ @cli.command(aliases=["e"]) # pyright: ignore[reportAny]
90
149
  @click.argument("private_key_file", type=in_path)
91
150
  @click.argument("public_key_file", type=in_path)
92
151
  @click.argument("message_file", type=in_path)
93
152
  @click.option("--key-encoding", default="base64", show_default=True)
94
153
  @click.option("--data-encoding", "-e", default="base64", show_default=True)
95
- @click.option("--compression", "-c", default="zlib", show_default=True)
96
- @click.option("--output-file", "-o", type=out_path, help="(Optional)")
154
+ @click.option("--compression", "-c", default="zstd", show_default=True)
155
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
156
+ @click.option("--group-len", default=0, show_default=True)
157
+ @click.option("--line-len", default=0, show_default=True)
158
+ @click.option("--padding", default=0, show_default=True)
159
+ @click.option("--verbose", "-v", is_flag=True, help="Show verbose output.")
97
160
  def encrypt_public_cmd(
98
161
  private_key_file: Path,
99
162
  public_key_file: Path,
@@ -102,34 +165,57 @@ def encrypt_public_cmd(
102
165
  data_encoding: str,
103
166
  compression: str,
104
167
  output_file: Path | None,
105
- ):
168
+ group_len: int,
169
+ line_len: int,
170
+ padding: int,
171
+ verbose: bool,
172
+ ) -> None:
106
173
  """Encrypt Message (Public).
107
174
 
108
- Encoding: base26 | base36 | base64 | base94 | binary
175
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
109
176
 
110
- Compression: zlib | bz2 | lzma | raw
177
+ Compression: zstd | zlib | bz2 | lzma | raw
111
178
  """
112
179
  key_enc = ENCODERS[key_encoding]
113
180
  data_enc = ENCODERS[data_encoding]
114
181
  archiver = ARCHIVERS[compression]
115
- priv_bytes = read_clean_bytes(private_key_file)
116
- priv = PrivateKey(priv_bytes, key_enc)
117
- pub_bytes = read_clean_bytes(public_key_file)
118
- pub = PublicKey(pub_bytes, key_enc)
119
- data = stats = read_plaintext_bytes(message_file, data_enc)
182
+ is_bin_key = key_encoding == "binary"
183
+ is_bin_data = data_encoding == "binary"
184
+
185
+ priv = read_key_bytes(
186
+ source=private_key_file, is_binary=is_bin_key, encoder=key_enc
187
+ )
188
+ priv = PrivateKey(private_key=priv)
189
+ pub = read_key_bytes(source=public_key_file, is_binary=is_bin_key, encoder=key_enc)
190
+ pub = PublicKey(public_key=pub)
191
+ data = stats = message_file.read_bytes()
120
192
  data = archiver(data)
121
- data = public.encrypt(private=priv, public=pub, data=data, out_enc=data_enc)
122
- write_output(output_file, data, data_enc)
123
- print_stats(stats, data)
124
-
125
-
126
- @cli.command(aliases=["es"])
193
+ data = public.encrypt(private=priv, public=pub, data=data)
194
+ data = data_enc.encode(data)
195
+
196
+ write_output(
197
+ target=output_file,
198
+ data=data,
199
+ is_binary=is_bin_data,
200
+ group_len=group_len,
201
+ line_len=line_len,
202
+ padding=padding,
203
+ )
204
+ if verbose:
205
+ print_stats(plaintext=stats, ciphertext=data)
206
+
207
+
208
+ @cli.command(aliases=["es"]) # pyright: ignore[reportAny]
127
209
  @click.argument("key_file", type=in_path)
128
210
  @click.argument("message_file", type=in_path)
129
211
  @click.option("--key-encoding", default="base64", show_default=True)
130
212
  @click.option("--data-encoding", "-e", default="base64", show_default=True)
131
- @click.option("--compression", "-c", default="zlib", show_default=True)
132
- @click.option("--output-file", "-o", type=out_path, help="(Optional)")
213
+ @click.option("--compression", "-c", default="zstd", show_default=True)
214
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
215
+ @click.option("--group-len", default=0, show_default=True)
216
+ @click.option("--line-len", default=0, show_default=True)
217
+ @click.option("--padding", default=0, show_default=True)
218
+ @click.option("--verbose", "-v", is_flag=True, help="Show verbose output.")
133
219
  def encrypt_secret_cmd(
134
220
  key_file: Path,
135
221
  message_file: Path,
@@ -137,31 +223,52 @@ def encrypt_secret_cmd(
137
223
  data_encoding: str,
138
224
  compression: str,
139
225
  output_file: Path | None,
140
- ):
226
+ group_len: int,
227
+ line_len: int,
228
+ padding: int,
229
+ verbose: bool,
230
+ ) -> None:
141
231
  """Encrypt Message (Secret).
142
232
 
143
- Encoding: base26 | base36 | base64 | base94 | binary
233
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
144
234
 
145
- Compression: zlib | bz2 | lzma | raw
235
+ Compression: zstd | zlib | bz2 | lzma | raw
146
236
  """
147
237
  key_enc = ENCODERS[key_encoding]
148
238
  data_enc = ENCODERS[data_encoding]
149
239
  archiver = ARCHIVERS[compression]
150
- key = read_clean_bytes(key_file)
151
- data = stats = read_plaintext_bytes(message_file, data_enc)
152
- data = archiver(data)
153
- data = secret.encrypt(key=key, data=data, key_enc=key_enc, out_enc=data_enc)
154
- write_output(output_file, data, data_enc)
155
- print_stats(stats, data)
240
+ is_bin_key = key_encoding == "binary"
241
+ is_bin_data = data_encoding == "binary"
156
242
 
157
-
158
- @cli.command(aliases=["ep"])
243
+ key = read_key_bytes(source=key_file, is_binary=is_bin_key, encoder=key_enc)
244
+ data = stats = message_file.read_bytes()
245
+ data = archiver(data)
246
+ data = secret.encrypt(key=key, data=data)
247
+ data = data_enc.encode(data)
248
+
249
+ write_output(
250
+ target=output_file,
251
+ data=data,
252
+ is_binary=is_bin_data,
253
+ group_len=group_len,
254
+ line_len=line_len,
255
+ padding=padding,
256
+ )
257
+ if verbose:
258
+ print_stats(plaintext=stats, ciphertext=data)
259
+
260
+
261
+ @cli.command(aliases=["ep"]) # pyright: ignore[reportAny]
159
262
  @click.argument("password_file", type=in_path)
160
263
  @click.argument("message_file", type=in_path)
161
264
  @click.option("--kdf-profile", "-p", default="sensitive", show_default=True)
162
265
  @click.option("--data-encoding", "-e", default="base64", show_default=True)
163
- @click.option("--compression", "-c", default="zlib", show_default=True)
164
- @click.option("--output-file", "-o", type=out_path, help="(Optional)")
266
+ @click.option("--compression", "-c", default="zstd", show_default=True)
267
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
268
+ @click.option("--group-len", default=0, show_default=True)
269
+ @click.option("--line-len", default=0, show_default=True)
270
+ @click.option("--padding", default=0, show_default=True)
271
+ @click.option("--verbose", "-v", is_flag=True, help="Show verbose output.")
165
272
  def encrypt_password_cmd(
166
273
  password_file: Path,
167
274
  message_file: Path,
@@ -169,35 +276,53 @@ def encrypt_password_cmd(
169
276
  data_encoding: str,
170
277
  compression: str,
171
278
  output_file: Path | None,
172
- ):
279
+ group_len: int,
280
+ line_len: int,
281
+ padding: int,
282
+ verbose: bool,
283
+ ) -> None:
173
284
  """Encrypt Message (Password).
174
285
 
175
286
  KDF profile: interactive | moderate | sensitive
176
287
 
177
- Encoding: base26 | base36 | base64 | base94 | binary
288
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
178
289
 
179
- Compression: zlib | bz2 | lzma | raw
290
+ Compression: zstd | zlib | bz2 | lzma | raw
180
291
  """
181
292
  prof = KDF_PROFILES[kdf_profile]
182
293
  data_enc = ENCODERS[data_encoding]
183
294
  archiver = ARCHIVERS[compression]
184
- pw = read_bytes(password_file)
185
- key = kdf(pw, prof, RawEncoder)
186
- data = stats = read_plaintext_bytes(message_file, data_enc)
187
- data = archiver(data)
188
- data = secret.encrypt(key=key, data=data, key_enc=RawEncoder, out_enc=data_enc)
189
- write_output(output_file, data, data_enc)
190
- print_stats(stats, data)
191
-
295
+ is_bin_data = data_encoding == "binary"
192
296
 
193
- @cli.command(aliases=["d"])
297
+ pw = read_password_bytes(password_file)
298
+ key = kdf(password=pw, profile=prof)
299
+ data = stats = message_file.read_bytes()
300
+ data = archiver(data)
301
+ data = secret.encrypt(key=key, data=data)
302
+ data = data_enc.encode(data)
303
+
304
+ write_output(
305
+ target=output_file,
306
+ data=data,
307
+ is_binary=is_bin_data,
308
+ group_len=group_len,
309
+ line_len=line_len,
310
+ padding=padding,
311
+ )
312
+ if verbose:
313
+ print_stats(plaintext=stats, ciphertext=data)
314
+
315
+
316
+ @cli.command(aliases=["d"]) # pyright: ignore[reportAny]
194
317
  @click.argument("private_key_file", type=in_path)
195
318
  @click.argument("public_key_file", type=in_path)
196
319
  @click.argument("message_file", type=in_path)
197
320
  @click.option("--key-encoding", default="base64", show_default=True)
198
321
  @click.option("--data-encoding", "-e", default="base64", show_default=True)
199
- @click.option("--compression", "-c", default="zlib", show_default=True)
200
- @click.option("--output-file", "-o", type=out_path, help="(Optional)")
322
+ @click.option("--compression", "-c", default="zstd", show_default=True)
323
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
324
+ @click.option("--padding", default=0, show_default=True)
325
+ @click.option("--verbose", "-v", is_flag=True, help="Show verbose output.")
201
326
  def decrypt_public_cmd(
202
327
  private_key_file: Path,
203
328
  public_key_file: Path,
@@ -206,34 +331,53 @@ def decrypt_public_cmd(
206
331
  data_encoding: str,
207
332
  compression: str,
208
333
  output_file: Path | None,
209
- ):
334
+ padding: int,
335
+ verbose: bool,
336
+ ) -> None:
210
337
  """Decrypt Message (Public).
211
338
 
212
- Encoding: base26 | base36 | base64 | base94 | binary
339
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
213
340
 
214
- Compression: zlib | bz2 | lzma | raw
341
+ Compression: zstd | zlib | bz2 | lzma | raw
215
342
  """
216
343
  key_enc = ENCODERS[key_encoding]
217
344
  data_enc = ENCODERS[data_encoding]
218
345
  unarchiver = UNARCHIVERS[compression]
219
- priv_bytes = read_clean_bytes(private_key_file)
220
- priv = PrivateKey(priv_bytes, key_enc)
221
- pub_bytes = read_clean_bytes(public_key_file)
222
- pub = PublicKey(pub_bytes, key_enc)
223
- data = stats = read_ciphertext_bytes(message_file, data_enc)
224
- data = public.decrypt(priv, pub, data, data_enc)
346
+ is_bin_key = key_encoding == "binary"
347
+ is_bin_data = data_encoding == "binary"
348
+
349
+ priv = read_key_bytes(
350
+ source=private_key_file, is_binary=is_bin_key, encoder=key_enc
351
+ )
352
+ priv = PrivateKey(private_key=priv)
353
+ pub = read_key_bytes(source=public_key_file, is_binary=is_bin_key, encoder=key_enc)
354
+ pub = PublicKey(public_key=pub)
355
+ data = stats = read_bytes(source=message_file, is_binary=is_bin_data)
356
+ data = data_enc.decode(data)
357
+ data = public.decrypt(private=priv, public=pub, data=data)
225
358
  data = unarchiver(data)
226
- write_output(output_file, data, data_enc)
227
- print_stats(data, stats)
359
+
360
+ write_output(
361
+ target=output_file,
362
+ data=data,
363
+ is_binary=True,
364
+ group_len=0,
365
+ line_len=0,
366
+ padding=padding,
367
+ )
368
+ if verbose:
369
+ print_stats(plaintext=data, ciphertext=stats)
228
370
 
229
371
 
230
- @cli.command(aliases=["ds"])
372
+ @cli.command(aliases=["ds"]) # pyright: ignore[reportAny]
231
373
  @click.argument("key_file", type=in_path)
232
374
  @click.argument("message_file", type=in_path)
233
375
  @click.option("--key-encoding", default="base64", show_default=True)
234
376
  @click.option("--data-encoding", "-e", default="base64", show_default=True)
235
- @click.option("--compression", "-c", default="zlib", show_default=True)
236
- @click.option("--output-file", "-o", type=out_path, help="(Optional)")
377
+ @click.option("--compression", "-c", default="zstd", show_default=True)
378
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
379
+ @click.option("--padding", default=0, show_default=True)
380
+ @click.option("--verbose", "-v", is_flag=True, help="Show verbose output.")
237
381
  def decrypt_secret_cmd(
238
382
  key_file: Path,
239
383
  message_file: Path,
@@ -241,31 +385,48 @@ def decrypt_secret_cmd(
241
385
  data_encoding: str,
242
386
  compression: str,
243
387
  output_file: Path | None,
244
- ):
388
+ padding: int,
389
+ verbose: bool,
390
+ ) -> None:
245
391
  """Decrypt Message (Secret).
246
392
 
247
- Encoding: base26 | base36 | base64 | base94 | binary
393
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
248
394
 
249
- Compression: zlib | bz2 | lzma | raw
395
+ Compression: zstd | zlib | bz2 | lzma | raw
250
396
  """
251
397
  key_enc = ENCODERS[key_encoding]
252
398
  data_enc = ENCODERS[data_encoding]
253
399
  unarchiver = UNARCHIVERS[compression]
254
- key = read_clean_bytes(key_file)
255
- data = stats = read_ciphertext_bytes(message_file, data_enc)
256
- data = secret.decrypt(key, data, key_enc, data_enc)
400
+ is_bin_key = key_encoding == "binary"
401
+ is_bin_data = data_encoding == "binary"
402
+
403
+ key = read_key_bytes(source=key_file, is_binary=is_bin_key, encoder=key_enc)
404
+ data = stats = read_bytes(source=message_file, is_binary=is_bin_data)
405
+ data = data_enc.decode(data)
406
+ data = secret.decrypt(key=key, data=data)
257
407
  data = unarchiver(data)
258
- write_output(output_file, data, data_enc)
259
- print_stats(data, stats)
260
408
 
409
+ write_output(
410
+ target=output_file,
411
+ data=data,
412
+ is_binary=True,
413
+ group_len=0,
414
+ line_len=0,
415
+ padding=padding,
416
+ )
417
+ if verbose:
418
+ print_stats(plaintext=data, ciphertext=stats)
261
419
 
262
- @cli.command(aliases=["dp"])
420
+
421
+ @cli.command(aliases=["dp"]) # pyright: ignore[reportAny]
263
422
  @click.argument("password_file", type=in_path)
264
423
  @click.argument("message_file", type=in_path)
265
424
  @click.option("--kdf-profile", "-p", default="sensitive", show_default=True)
266
425
  @click.option("--data-encoding", "-e", default="base64", show_default=True)
267
- @click.option("--compression", "-c", default="zlib", show_default=True)
268
- @click.option("--output-file", "-o", type=out_path, help="(Optional)")
426
+ @click.option("--compression", "-c", default="zstd", show_default=True)
427
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
428
+ @click.option("--padding", default=0, show_default=True)
429
+ @click.option("--verbose", "-v", is_flag=True, help="Show verbose output.")
269
430
  def decrypt_password_cmd(
270
431
  password_file: Path,
271
432
  message_file: Path,
@@ -273,45 +434,79 @@ def decrypt_password_cmd(
273
434
  data_encoding: str,
274
435
  compression: str,
275
436
  output_file: Path | None,
276
- ):
437
+ padding: int,
438
+ verbose: bool,
439
+ ) -> None:
277
440
  """Decrypt Message (Password).
278
441
 
279
442
  KDF profile: interactive | moderate | sensitive
280
443
 
281
- Encoding: base26 | base36 | base64 | base94 | binary
444
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
282
445
 
283
- Compression: zlib | bz2 | lzma | raw
446
+ Compression: zstd | zlib | bz2 | lzma | raw
284
447
  """
285
448
  prof = KDF_PROFILES[kdf_profile]
286
449
  data_enc = ENCODERS[data_encoding]
287
450
  unarchiver = UNARCHIVERS[compression]
288
- pw = read_bytes(password_file)
289
- key = kdf(pw, prof, RawEncoder)
290
- data = stats = read_ciphertext_bytes(message_file, data_enc)
291
- data = secret.decrypt(key, data, RawEncoder, data_enc)
451
+ is_bin_data = data_encoding == "binary"
452
+
453
+ pw = read_password_bytes(password_file)
454
+ key = kdf(password=pw, profile=prof)
455
+ data = stats = read_bytes(source=message_file, is_binary=is_bin_data)
456
+ data = data_enc.decode(data)
457
+ data = secret.decrypt(key=key, data=data)
292
458
  data = unarchiver(data)
293
- write_output(output_file, data, data_enc)
294
- print_stats(data, stats)
459
+
460
+ write_output(
461
+ target=output_file,
462
+ data=data,
463
+ is_binary=True,
464
+ group_len=0,
465
+ line_len=0,
466
+ padding=padding,
467
+ )
468
+ if verbose:
469
+ print_stats(plaintext=data, ciphertext=stats)
295
470
 
296
471
 
297
- @cli.command()
472
+ @cli.command() # pyright: ignore[reportAny]
298
473
  @click.argument("in_encoding")
299
474
  @click.argument("out_encoding")
300
475
  @click.argument("file", type=in_path)
301
- @click.option("--output-file", "-o", type=out_path, help="(Optional)")
476
+ @click.option("--output-file", "-o", type=out_path, help="Write output to file.")
477
+ @click.option("--group-len", default=0, show_default=True)
478
+ @click.option("--line-len", default=0, show_default=True)
479
+ @click.option("--padding", default=0, show_default=True)
302
480
  def encode_cmd(
303
- in_encoding: str, out_encoding: str, file: Path, output_file: Path | None
304
- ):
481
+ in_encoding: str,
482
+ out_encoding: str,
483
+ file: Path,
484
+ output_file: Path | None,
485
+ group_len: int,
486
+ line_len: int,
487
+ padding: int,
488
+ ) -> None:
305
489
  """Encode File.
306
490
 
307
- Encoding: base26 | base36 | base64 | base94 | binary
491
+ Encoding: base26 | base31 | base36 | base64 | base94 | binary
308
492
  """
309
493
  in_enc = ENCODERS[in_encoding]
310
494
  out_enc = ENCODERS[out_encoding]
311
- data = read_ciphertext_bytes(file, in_enc)
495
+ in_bin = in_encoding == "binary"
496
+ out_bin = out_encoding == "binary"
497
+
498
+ data = read_bytes(source=file, is_binary=in_bin)
312
499
  data = in_enc.decode(data)
313
500
  data = out_enc.encode(data)
314
- write_output(output_file, data, out_enc)
501
+
502
+ write_output(
503
+ target=output_file,
504
+ data=data,
505
+ is_binary=out_bin,
506
+ group_len=group_len,
507
+ line_len=line_len,
508
+ padding=padding,
509
+ )
315
510
 
316
511
 
317
512
  if __name__ == "__main__":