mirror of
https://github.com/logos-messaging/logos-messaging-nim-compose.git
synced 2026-01-08 00:43:07 +00:00
feat: keystore decrypt tool (#153)
This commit is contained in:
parent
c8dcc85736
commit
bb9189ab89
7
decrypt_keystore/README.md
Normal file
7
decrypt_keystore/README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
## Usage
|
||||||
|
To validate/decrypt your keystore credential,
|
||||||
|
- update `keystore.json` with your own credentials/keystore
|
||||||
|
- run:
|
||||||
|
```sh
|
||||||
|
python3 ./decrypt.py --password YOUR_PASSWORD_HERE --file keystore.json
|
||||||
|
```
|
||||||
75
decrypt_keystore/decrypt.py
Normal file
75
decrypt_keystore/decrypt.py
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
from binascii import unhexlify
|
||||||
|
from Crypto.Cipher import AES
|
||||||
|
from Crypto.Protocol.KDF import PBKDF2
|
||||||
|
from Crypto.Hash import SHA256, keccak
|
||||||
|
from Crypto.Util import Counter
|
||||||
|
from hashlib import sha256
|
||||||
|
|
||||||
|
def diagnose_keystore(file_path: str, password: str):
|
||||||
|
with open(file_path, "r") as f:
|
||||||
|
keystore = json.load(f)
|
||||||
|
|
||||||
|
print(f"🔍 Diagnosing keystore: {file_path}")
|
||||||
|
|
||||||
|
for address, data in keystore.get("credentials", {}).items():
|
||||||
|
print(f"\n🔐 Address: {address}")
|
||||||
|
try:
|
||||||
|
crypto = data["crypto"]
|
||||||
|
salt = unhexlify(crypto["kdfparams"]["salt"])
|
||||||
|
iterations = crypto["kdfparams"]["c"]
|
||||||
|
ciphertext = unhexlify(crypto["ciphertext"])
|
||||||
|
iv = unhexlify(crypto["cipherparams"]["iv"])
|
||||||
|
mac_expected = unhexlify(crypto["mac"])
|
||||||
|
|
||||||
|
# Derive key
|
||||||
|
derived_key = PBKDF2(password, salt, dkLen=32, count=iterations, hmac_hash_module=SHA256)
|
||||||
|
|
||||||
|
# Ethereum-style MAC
|
||||||
|
keccak_hash = keccak.new(digest_bits=256)
|
||||||
|
keccak_hash.update(derived_key[16:32] + ciphertext)
|
||||||
|
mac_computed = keccak_hash.digest()
|
||||||
|
|
||||||
|
if mac_computed == mac_expected:
|
||||||
|
print("✅ MAC matched using keccak256.")
|
||||||
|
else:
|
||||||
|
print("❌ MAC failed with keccak256. Trying SHA256 fallback...")
|
||||||
|
fallback_mac = sha256(derived_key[:16] + ciphertext).digest()
|
||||||
|
if fallback_mac == mac_expected:
|
||||||
|
print("✅ MAC matched using SHA256 fallback.")
|
||||||
|
else:
|
||||||
|
print("❌ MAC failed with both keccak256 and SHA256.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Decrypt
|
||||||
|
ctr = Counter.new(128, initial_value=int.from_bytes(iv, byteorder="big"))
|
||||||
|
cipher = AES.new(derived_key[:16], AES.MODE_CTR, counter=ctr)
|
||||||
|
decrypted = cipher.decrypt(ciphertext)
|
||||||
|
|
||||||
|
print(f"\n🧪 Raw Decrypted (hex): {decrypted.hex()}")
|
||||||
|
try:
|
||||||
|
utf8 = decrypted.decode("utf-8")
|
||||||
|
print("\n📜 Decrypted as UTF-8 string:")
|
||||||
|
print(utf8)
|
||||||
|
|
||||||
|
try:
|
||||||
|
parsed = json.loads(utf8)
|
||||||
|
print("\n🧾 Decrypted as JSON:")
|
||||||
|
print(json.dumps(parsed, indent=2))
|
||||||
|
except Exception as e:
|
||||||
|
print("⚠️ Could not parse UTF-8 string as JSON:", e)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("⚠️ Could not decode decrypted data as UTF-8:", e)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"💥 Error: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="Diagnose Waku-style keystore files.")
|
||||||
|
parser.add_argument("--file", required=True, help="Path to keystore JSON file")
|
||||||
|
parser.add_argument("--password", required=True, help="Password to decrypt")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
diagnose_keystore(args.file, args.password)
|
||||||
0
decrypt_keystore/keystore.json
Normal file
0
decrypt_keystore/keystore.json
Normal file
Loading…
x
Reference in New Issue
Block a user