ensec-cli 1.0.10__tar.gz → 2.0.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,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ensec-cli
3
- Version: 1.0.10
3
+ Version: 2.0.0
4
4
  Summary: EncryptSecureDEC Open Source CLI
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
7
7
  License-File: LICENSE
8
8
  Requires-Dist: pycryptodome
9
9
  Requires-Dist: cryptography
10
+ Requires-Dist: reedsolo
10
11
  Dynamic: license-file
11
12
 
12
13
  # ENSEC-CLI
@@ -0,0 +1 @@
1
+ __version__ = "2.0.0"
@@ -17,11 +17,13 @@ from . import rsa_encryptor
17
17
  from pathlib import Path
18
18
  from .conf_load import load_config
19
19
  from . import __version__ as VERSION
20
-
20
+ from .ecc import *
21
21
  # OKならそのまま続行
22
22
 
23
23
  conf=load_config()
24
24
 
25
+ ecc = False
26
+
25
27
  BLOCKCHAIN_HEADER = b'BLOCKCHAIN_DATA_START\n'
26
28
  def _format_bytes(num: int) -> str:
27
29
  units = ["B", "KB", "MB", "GB", "TB", "PB"]
@@ -164,23 +166,43 @@ def cli_encrypt(file_path, password, memo):
164
166
  username = getpass.getuser()
165
167
 
166
168
  try:
167
- with lzma.open(file_path + ".vdec", 'rb') as f:
168
- data = f.read()
169
+ with open(file_path + ".vdec", 'rb') as f:
170
+ raw_data = f.read()
171
+ if ecc==True:
172
+ try:
173
+ data = recover_data(raw_data)
174
+ if data is None:
175
+ data = lzma.decompress(raw_data)
176
+ except(ValueError, lzma.LZMAError):
177
+ data = lzma.decompress(raw_data)
178
+ else:
179
+ data=lzma.decompress(raw_data)
169
180
  split_index = data.index(BLOCKCHAIN_HEADER)
170
181
  chain_json = data[split_index + len(BLOCKCHAIN_HEADER):].decode('utf-8')
171
182
  blockchain = Blockchain.from_json(chain_json)
172
183
  except:
184
+ if os.path.exists(file_path + ".vdec") :
185
+ print("警告:既存のブロックチェーンデータの読み込みに失敗しました。\n新規にブロックチェーンを作成します。")
173
186
  blockchain = Blockchain()
187
+
174
188
  block = Block(file_hash, blockchain.chain[-1].hash if blockchain.chain else "0", "Encrypt", file_hash, username, memo)
175
189
  blockchain.add_block(block)
176
190
 
177
191
  encrypted_data = salt + nonce + ciphertext + tag
178
192
  blockchain_data = BLOCKCHAIN_HEADER + blockchain.to_json().encode('utf-8')
179
193
 
194
+ combined_data = encrypted_data + blockchain_data
195
+ # 先にLZMA圧縮
196
+ compressed_data = lzma.compress(combined_data)
197
+
198
+ if ecc==True:
199
+ ecc_data = add_ecc(compressed_data)
200
+ else:
201
+ ecc_data = compressed_data
180
202
  out_path = file_path + ".vdec"
181
- with lzma.open(out_path, 'wb') as f:
182
- f.write(encrypted_data)
183
- f.write(blockchain_data)
203
+ with open(out_path, 'wb') as f:
204
+ f.write(ecc_data)
205
+
184
206
  if deletemode["mode"] == True:
185
207
  delete_pre_file(file_path)
186
208
  print(f"✅ Encryption completed: {out_path}")
@@ -191,8 +213,27 @@ def cli_decrypt(file_path, password, memo):
191
213
  wav_bytes = f.read()
192
214
  data = wavencode.wav_bytes_to_binary(wav_bytes)
193
215
  else:
194
- with lzma.open(file_path, 'rb') as f:
195
- data = f.read()
216
+ try:
217
+ with open(file_path, 'rb') as f:
218
+ data = f.read()
219
+ if ecc==True:
220
+ # 分割ファイルでない場合はECC復元とLZMA展開を試みる。失敗したら(分割ファイルでない場合)LZMA展開のみ試みる。
221
+ data = recover_data(data) # ECC復元とLZMA展開を試みる(成功すればdataが更新される)
222
+
223
+ if data is None:
224
+ raise ValueError("データの復元に失敗")
225
+ else:
226
+ data = lzma.decompress(data)
227
+ except ValueError as e:
228
+ print("エラー:ファイルの読み込みに失敗しました")
229
+ print("ECCでも復元できないくらいにファイルが破損している可能性があります")
230
+ return
231
+ except EOFError:
232
+ print("エラー:圧縮データが途中で途切れています\n(ファイルが破損している可能性があります)\n分割データの場合必要なパーツが足りません")
233
+ return
234
+ except lzma.LZMAError:
235
+ print("エラー:LZMA展開に失敗しました")
236
+ return
196
237
 
197
238
  split_index = data.index(BLOCKCHAIN_HEADER)
198
239
  crypto_data = data[:split_index]
@@ -225,12 +266,24 @@ def cli_decrypt(file_path, password, memo):
225
266
  file_hash = hashlib.sha256(ciphertext).hexdigest()
226
267
  block = Block(file_hash, blockchain.chain[-1].hash if blockchain.chain else "0", "Decrypt", file_hash, username, memo)
227
268
  blockchain.add_block(block)
269
+
270
+ # 暗号バイト列
271
+ encrypted_data = salt + nonce + ciphertext + tag
272
+ blockchain_data = BLOCKCHAIN_HEADER + blockchain.to_json().encode('utf-8')
273
+
274
+ combined_data = encrypted_data + blockchain_data
275
+
276
+ compressed_data = lzma.compress(combined_data)
277
+
278
+ if ecc==True:
279
+ ecc_data = add_ecc(compressed_data)
280
+ else:
281
+ ecc_data = compressed_data
228
282
 
229
283
  if not file_path.endswith(".wav"):
230
- with lzma.open(file_path, 'wb') as f:
231
- f.write(salt + nonce + ciphertext + tag)
232
- f.write(BLOCKCHAIN_HEADER)
233
- f.write(blockchain.to_json().encode('utf-8'))
284
+ with open(file_path, 'wb') as f:
285
+ f.write(ecc_data)
286
+
234
287
 
235
288
  print(f"✅ Decryption completed: {output_file}")
236
289
 
@@ -239,8 +292,15 @@ def cli_verify_chain(file_path):
239
292
  with open(file_path, 'rb') as f:
240
293
  data = wavencode.wav_bytes_to_binary(f.read())
241
294
  else:
242
- with lzma.open(file_path, 'rb') as f:
295
+ with open(file_path, 'rb') as f:
243
296
  data = f.read()
297
+ if ecc == True:
298
+ data = recover_data(data)
299
+ if data is None:
300
+ print("❌ Error: データの復元に失敗しました")
301
+ return
302
+ else:
303
+ data = lzma.decompress(data)
244
304
  split_index = data.index(BLOCKCHAIN_HEADER)
245
305
  chain_json = data[split_index + len(BLOCKCHAIN_HEADER):].decode('utf-8')
246
306
  blockchain = Blockchain.from_json(chain_json)
@@ -276,6 +336,7 @@ def password_from_keyfile(keyfile_path: str) -> str:
276
336
 
277
337
  return hashlib.sha256(data).hexdigest()
278
338
  def main():
339
+ global ecc
279
340
  parser = argparse.ArgumentParser(description="EncryptSecureDEC CLI")
280
341
  parser.add_argument("mode",choices=["encrypt","decrypt","verify-chain","sign",
281
342
  "verify-sign","key-protect-on","key-protect-off"])
@@ -287,9 +348,12 @@ def main():
287
348
  parser.add_argument("--dir", action="store_true",help="Encrypt Dir mode")
288
349
  parser.add_argument("--pubkey", help="Path to public key file (only required in RSA encrypt mode)")
289
350
  parser.add_argument("--keyfile",help="Use a file as the password source for encryption/decryption")
290
- parser.add_argument("--version",action="version",version=f"ENSEC_CLI {__version__}")
351
+ parser.add_argument("--version",action="version",version=f"ENSEC_CLI {VERSION}")
352
+ parser.add_argument("--ecc", action="store_true",help="Enable ECC protection")
291
353
  args = parser.parse_args()
292
-
354
+
355
+ if args.ecc:
356
+ ecc=True
293
357
  # --- validate RSA/pubkey usage ---
294
358
  # --- validate RSA/pubkey usage ---
295
359
  if args.rsa:
@@ -0,0 +1,29 @@
1
+ from reedsolo import RSCodec, ReedSolomonError
2
+ import lzma
3
+ ECC_BYTES = 32 # 32byteのECC。最大で約16byte分の破損を訂正可能
4
+ rs = RSCodec(ECC_BYTES)
5
+
6
+ def add_ecc(data: bytes) -> bytes:
7
+ """暗号化済みデータにECCを付与"""
8
+ return bytes(rs.encode(data))
9
+
10
+ def recover_ecc(encoded: bytes) -> bytes:
11
+ """ECC付きデータを復元"""
12
+ try:
13
+ decoded = rs.decode(encoded)
14
+ return bytes(decoded[0]) # 元データ
15
+ except ReedSolomonError as e:
16
+ raise ValueError("ECCで復元できないほど破損しています") from e
17
+
18
+ def recover_data(data):
19
+ try:
20
+ compressed_data = recover_ecc(data)
21
+ except ValueError as e:
22
+ return None
23
+
24
+ try:
25
+ data = lzma.decompress(compressed_data)
26
+ except lzma.LZMAError:
27
+ print("エラーLZMA圧縮データの展開に失敗しました")
28
+ return None
29
+ return data
@@ -1,12 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ensec-cli
3
- Version: 1.0.10
3
+ Version: 2.0.0
4
4
  Summary: EncryptSecureDEC Open Source CLI
5
5
  Requires-Python: >=3.9
6
6
  Description-Content-Type: text/markdown
7
7
  License-File: LICENSE
8
8
  Requires-Dist: pycryptodome
9
9
  Requires-Dist: cryptography
10
+ Requires-Dist: reedsolo
10
11
  Dynamic: license-file
11
12
 
12
13
  # ENSEC-CLI
@@ -4,6 +4,7 @@ pyproject.toml
4
4
  ensec_cli/__init__.py
5
5
  ensec_cli/cli.py
6
6
  ensec_cli/conf_load.py
7
+ ensec_cli/ecc.py
7
8
  ensec_cli/esdcompress.py
8
9
  ensec_cli/passchk.py
9
10
  ensec_cli/rsa_encryptor.py
@@ -1,2 +1,3 @@
1
1
  pycryptodome
2
2
  cryptography
3
+ reedsolo
@@ -4,14 +4,15 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ensec-cli"
7
- version = "1.0.10"
7
+ version = "2.0.0"
8
8
  description = "EncryptSecureDEC Open Source CLI"
9
9
  requires-python = ">=3.9"
10
10
  readme = "README.md"
11
11
 
12
12
  dependencies = [
13
13
  "pycryptodome",
14
- "cryptography"
14
+ "cryptography",
15
+ "reedsolo"
15
16
  ]
16
17
  [tool.setuptools]
17
18
  packages = ["ensec_cli"]
@@ -1 +0,0 @@
1
- __version__ = "1.0.10"
File without changes
File without changes
File without changes
File without changes