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.
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/PKG-INFO +2 -1
- ensec_cli-2.0.0/ensec_cli/__init__.py +1 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli/cli.py +79 -15
- ensec_cli-2.0.0/ensec_cli/ecc.py +29 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli.egg-info/PKG-INFO +2 -1
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli.egg-info/SOURCES.txt +1 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli.egg-info/requires.txt +1 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/pyproject.toml +3 -2
- ensec_cli-1.0.10/ensec_cli/__init__.py +0 -1
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/LICENSE +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/README.md +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli/conf_load.py +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli/esdcompress.py +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli/passchk.py +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli/rsa_encryptor.py +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli/rsa_signer.py +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli/utils.py +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli/wavencode.py +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli.egg-info/dependency_links.txt +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli.egg-info/entry_points.txt +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/ensec_cli.egg-info/top_level.txt +0 -0
- {ensec_cli-1.0.10 → ensec_cli-2.0.0}/setup.cfg +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ensec-cli
|
|
3
|
-
Version:
|
|
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
|
|
168
|
-
|
|
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
|
|
182
|
-
f.write(
|
|
183
|
-
|
|
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
|
-
|
|
195
|
-
|
|
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
|
|
231
|
-
f.write(
|
|
232
|
-
|
|
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
|
|
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 {
|
|
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:
|
|
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,14 +4,15 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ensec-cli"
|
|
7
|
-
version = "
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|