Ethereum Pre-Sale extract SAFE hash (non-revealing private keys)
#1
Hello everyone.  I was re-organizing my home when I came across an hdd containing my old eth presale .json file  (Not life changing amount but still great to take…). Got few hints of the password but the wordlist is going be huge ... I took a look at jhontheripper hash extracter but I have seen that the hash is revealing (meaning that the hash contain the whole seed pharse of the wallet ... I have a correct level in python and perl and I really like learning and I have a lot of spare-time for the next months coming ... 

On the security side a revealing hash is  bad. I know many guys who have some cheap server I would like to be able to run some of the wordlist/rules on their server. I spend hours looking at the few ressources that are online. And thanks to philsmd great work that I saw here https://github.com/hashcat/hashcat/issues/1279  .I think I understand the decrypt process. I also find the issue on git about making safe hash extraction for eth https://github.com/openwall/john/issues/3130. From the hashcat issue I see that the -m 16300 is pretty similar to the -m 15600 and from the openwall issue I can see that there could be a way using padding (which I don't really get) to make safe hash extraction of this -m 15600 hash. 
Although at the end the solardiz is saying that this could potentially not work for eth presale type ... 


To summarize and to get all the info I can confirm that the .json file of the eth presale is looking like this : 
Code:
{ "bkp": 64 chars, "btcaddr": 34 chars,  "email":email@gmail.com,  "encseed": 1248 chars,  "ethaddr": 40 chars } 
‎‎‎
And thanks to philsmd post I can say that the actual decryption algorithm should be something like this : 
The algorithm is very easy. sha3 (aes_256_cbc_decrypt (pbkdf2 ($pass, $pass, 2000), $iv, $encseed) . "\x02") 
So basically we just extract the first 16 bytes (0-15) from the "encseed" field which we use as the initialization vector (iv) for the AES-256-CBC decryption, the remaining bytes (starting from byte 16) we use as the encrypted seed. The key for the AES-256-CBC decrytion is generated by using the user password as salt AND pass and use 2000 iterations of pbkdf2-hmac-sha256. The final hash is just a sha3/keccak hash of the seed (the decrypted encseed from the AES decrytion mentioned above). 
Also from the code I see that we can only use the first half of the bkp to verify the matching of the seed hash to the bkp
Code:
my $bkp = pack ("H*", "74fdb879ece341dd590a769f2cd39d67");
(only 32 characters long vs 64 characters long in the .json). 
‎‎
So basically after all of this I am thinking of 4 ways to make this "SAFE" hash extractor and the hashcat code associated : 
  • Using only a part of the of the encseed to generate a part of the bkp but i'm not sure it could work due to the way aes is working.
  • Using the padding stuff (would really appreciate any links to learn more ) mentionned here by solardiz
  • Try to build something https://github.com/philsmd/7z2hashcat but for the presale wallet
  • Encrypt every part of the json with a really strong 64 char (or more) random password but a low computation time algorithms to not slow too much the process. But I'm unusure if encrypting it another time will allow the decryption to find the password of the first encryption... 
If you have any idea that can help me or any opinion on the ways describe above (I'm still a big newbie in encryption so I can say some stupid stupid stuff). Also if you have some recommandation for me after reading my post don't hesitate to send me some links. 
BIG thanks to all the admin and contributor of hashcat and Jtr. 
 
Reply
#2
I don't think you can make a safe AND collision resistant variant of the Ethereum presale hash format. We need the entire data field to decrypt and perform the SHA3() checksum wrap and verify at the end. Without that, you would indeed be reduced to padding checks at best I suspect. Perhaps an entropy check or something could work, but you'd still be decrypting more of encseed than I think you might want to expose. Unfortunately, the process for verifying a password is to decrypt the wallet data, which means you must ship at least some of that wallet data to any system doing the cracking, and all of it if you want any reasonable certainty of finding the "right" password and not just a random string that can decrypt the data into "well formed" gibberish.
Reply
#3
(06-09-2023, 05:04 PM)Chick3nman Wrote: I don't think you can make a safe AND collision resistant variant of the Ethereum presale hash format. We need the entire data field to decrypt and perform the SHA3() checksum wrap and verify at the end. Without that, you would indeed be reduced to padding checks at best I suspect. Perhaps an entropy check or something could work, but you'd still be decrypting more of encseed than I think you might want to expose. Unfortunately, the process for verifying a password is to decrypt the wallet data, which means you must ship at least some of that wallet data to any system doing the cracking, and all of it if you want any reasonable certainty of finding the "right" password and not just a random string that can decrypt the data into "well formed" gibberish.

First of all thank you for your quick response Smile . Tell me if i'm wrong but I just realised I  can expose 97% of the encseed which arounds 1200/1248 is SAFE. The time it will take thousands year if someone want to brute force the las 48 characters  and having a few false positive is not a big issue. Even having a lot of them could be handled,  if I automate a bit and make something that will return me everytime the positive password found. 

Could you give some links or a quick description of I can implement padding checks and entropy checks or others tricks to try ?  As I told you I'm really happy to learn about this Smile .
Reply
#4
I'm not so sure about your assumption that 1200/1248 is safe. It sounds safe intuitively but I would need to take a closer look at the format again to be sure. iirc, the enc seed contains the raw seed bytes, which you can hash with sha3 to receive your private key, but I don't remember how those are aligned or if there was other information in encseed.

As for padding checks or entropy checks, I don't have any links outside of linking you to modes in hashcat that implement those things. I think the ethereum presale mode may actually have a padding/alignment check as an early throwaway. As for entropy, the Truecrypt/Veracrypt modes all implement an entropy check on load to verify that you are loading an encrypted filer/container/etc.
Reply
#5
Gonna check for the encseed content on some example wallet and will update you. But assuming to take the bytes of the seed - 50 characters it should be safe ? 
Also I took a quick look at this assuming it's the https://hashcat.net/wiki/doku.php?id=hashcat_utils for the padding checks and I didn't really get the entropy stuff (would spend more time on it). 

The only issue is that I don't exactly see how I can implement it in what steps basically ?  Smile

My idea be something like this I guess :
1) Substract the last x char of the encseed 
2) Apply the SHA3 (I'm not sure)
3) Check the padding (Not sure too)

Thanks again for you great response
Reply
#6
So I spends the last fews days searching and coding and assuming.

I have finally find the padding at the end of the encseed (using an encseed created by me ) a72643507070707070707. The issue is that it's at the end of the encseed which is an issue because the seed is encrypted with aes cbc if I want to decrypt the last block I need the data of the n-1 block and to get this one I need n-2 and so on. 

Are the padding always at the full end of the decrypted text or there could "partial padding" ? 

I didn't find any way to decrypt the hash from left to right too ... 

I'm still wondering if there is a way to crypt both encseed and bkp(private key encoded) using a special algorithm. And even in case someone find the password it will still be encrypted by the new password I put. If you have any idea I take it Smile . 

Also I have took a good look at the 16300.c mode on hashcat and there is no padding check from what I saw and no entropy check too.

Was also looking to partially decode the bkp(private key encoded) to use half of it to create the pub key and then generate the public address and check for a match. But due to the SHA3 it should not work normally. 

One thing sad is that all this could have been avoided by a simple "encseed": at the beginning of the encrypted seed. I could have easily add early throwaway for all the decrypted seed who don't have this... but due to the fact a seed is purely random and I don't know any part of my seed it i can't verify the seed validity ... 

One of the only thing that could work is end is the "entropy" check but i'm not sure the real seed will be the one with the most entropy ? I spend a bit of time checking the entropy of some string and it seems to not work like this ... 

If anyone have any others ideas don't hesitate to reply Smile
Reply
#7
(06-11-2023, 03:34 PM)hkbb345 Wrote: Are the padding always at the full end of the decrypted text or there could "partial padding" ?

This is definitely an issue and I'm not sure how to avoid it honestly.

(06-11-2023, 03:34 PM)hkbb345 Wrote: I'm still wondering if there is a way to crypt both encseed and bkp(private key encoded) using a special algorithm. And even in case someone find the password it will still be encrypted by the new password I put. If you have any idea I take it Smile . 

What you are looking for is the holy grail of computing, and is so far unachievable. It's called FHE, https://en.wikipedia.org/wiki/Homomorphic_encryption
Reply
#8
Thanks for all the quick response I learned a lot during the process. Will definitly spend some time around in the forum to help other (or at least try to Smile ) . Gonna spend a few days still looking for idea to make the SAFE hash but after that if I still get nothing I will probably  move on and try to get more hashing power ...
Reply