Getting back a password from Polkawallet JSON File
#8
hey madbury,

the answer to what the differences are between version 2 and version 3 Polkawallet algorithms can be seen within the source code of for instance the github repo linked above (polkadot-js or probably others too).

The main differences are these: NO SCRYPT !!! which should give you a HUGE performance advantage because scrypt is very slow (intentionally slow of course ! this is to make it difficult to brute-force or mask attack etc)

The main differences are here and these are probably also the 2 parts that you didn't find that easily (without my help, hehe):
1. no scrypt: https://github.com/polkadot-js/common/bl...ts#L27-L33
2. password to key conversion (just NUL-byte padding, hehe): https://github.com/polkadot-js/common/bl...ts#L20-L32

here is the python3 version, you could easily also convert the perl version etc... now that you have all the algorithm details:
polkawallet2.py:
Code:
#!/usr/bin/env python3

# Author: philsmd
# Date: April 2022
# License: public domain, credits go to philsmd and hashcat

# Note: NaCl uses XSalsa20 and Poly1305 for decrypting the data.
# there is *NO* key derivation for version 2 wallets ! i.e. the password is used AS-IS,
# but NULL-byte (\x00) padded to 32 bytes

# only tested with version 2 of a PolkaWallet test wallet

import binascii
import sys
from nacl.secret import SecretBox # install PyNaCl


#
# Examples
#

# const PAIR = '{"address":"5CczAE5AmGrZ93MeVhha3Ywam7j9dKB7cArnH7gtrXcMFJvu","encoded":"0xee8f236e2ac3217ce689692a4afc612220dc77fddaed0482f8f95136a7c3e034cccfbc495410a6e9b2439904974ed1d207abeca536ff6985ceb78edeeb3dc343e561c184c488101af8811d1331430b4ccf0e96ef507132e5132964e8564232e7100d973c5bee7b231dd0c8ad5273f3501515a422c8d7ed9d20a73c0ed17c98ee4588e54844bb73052dcad81f7a1094613d63c162fec7446c88b1fae70e","encoding":{"content":["pkcs8","sr25519"],"type":"xsalsa20-poly1305","version":"2"},"meta":{"genesisHash":"0xe143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423e","name":"json v2","tags":[],"whenCreated":1595243159596}}';
# PASS2 = "versionTwo";

ENCODED = "0xee8f236e2ac3217ce689692a4afc612220dc77fddaed0482f8f95136a7c3e034cccfbc495410a6e9b2439904974ed1d207abeca536ff6985ceb78edeeb3dc343e561c184c488101af8811d1331430b4ccf0e96ef507132e5132964e8564232e7100d973c5bee7b231dd0c8ad5273f3501515a422c8d7ed9d20a73c0ed17c98ee4588e54844bb73052dcad81f7a1094613d63c162fec7446c88b1fae70e"


#
# Start
#

if len (sys.argv) < 2:
  print ("ERROR: Please specify the dict file within the command line", file=sys.stderr)

  sys.exit (1)

fp = None

try:
  fp = open (sys.argv[1])
except:
  print ("ERROR: Could not open dictionary file '%s'" % sys.argv[1], file=sys.stderr)

  sys.exit (1)

if ENCODED[0:2] != "0x":
  print ("ERROR: not a valid ENCODED string for version 2 wallets", file=sys.stderr)

  sys.exit (1)

if len (ENCODED) < (2 + 24 + 32):
  print ("ERROR: too short ENCODED string for version 2 wallets", file=sys.stderr)

  sys.exit (1)

raw_data = binascii.unhexlify (ENCODED[2:])

nonce     = raw_data[ 0:24]
encrypted = raw_data[24:  ]

cracked = False

password = fp.readline ()

while password:
  password = password.strip ()

  key = (password + ("\x00" * 32)) [0:32] # pad with 32 \x00 bytes, take the first 32 bytes as key
  key = key.encode () # python 3 shenanigans

  box = SecretBox (key)

  try:
    box.decrypt (encrypted, nonce)

    print ("Password found: '%s'" % password)

    cracked = True

    break
  except:
    password = fp.readline ()


# Cleanup:

fp.close ()


# Exit codes:

if cracked:
  sys.exit (0)
else:
  sys.exit (1)

of course you would need to adapt the "ENCODED" string (the most important data from the JSON file that is needed to verify a password). one could also think about adapting the script and taking 2 command line arguments, first could be the json wallet, second one could be the password... for convenience

hope this helps, thx
Reply


Messages In This Thread
RE: Getting back a password from Polkawallet JSON File - by philsmd - 04-06-2022, 05:23 PM