Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dogechain.info wallet format has recently changed, support is now broken. #317

Open
3rdIteration opened this issue Jan 17, 2022 · 12 comments
Labels
Low Priority Likely to be one of the last issues to be looked at

Comments

@3rdIteration
Copy link
Owner

3rdIteration commented Jan 17, 2022

These wallets are also incorrectly detected as a blockchain.com wallet, either way it's broken.

Sample of updated wallet files is here:
https://github.com/3rdIteration/btcrecover/blob/6ba24508d4a752bc06a1dd29d52c55c23f1f0795/btcrecover/test/test-wallets/dogechain.wallet.aes.json.2022-01

The correct password is the standard test password, "btcr-test-password".

@3rdIteration 3rdIteration added the Low Priority Likely to be one of the last issues to be looked at label Jan 17, 2022
@jimtje
Copy link

jimtje commented Mar 26, 2022

FWIW here is the decryptor code in js:

function getSHA256(t) {
    var md = forge.md.sha256.create();
    md.update(t);
    return md.digest().toHex();
}

function decryptWallet(payload, password, salt, iterations, aes_cipher) {
    // decrypts the wallet
    // payload, salt are in Base64
    // payload contains the IV (first 16 or 12 bytes)
    
    var encryption_key = forge.util.bytesToHex(forge.pkcs5.pbkdf2(forge.util.encode64(forge.util.hexToBytes(getSHA256(password))), forge.util.decode64(salt), iterations, 32, "sha256"));

    var iv_hex = null;
    var payload_hex = null;
    var aes_auth_tag = null;

    var payload_bytes = forge.util.decode64(payload);
    
    if (aes_cipher === "AES-CBC") {
	iv_hex = forge.util.bytesToHex(payload_bytes.slice(0,16));
	payload_hex = forge.util.bytesToHex(payload_bytes.slice(16));
    } else if (aes_cipher === "AES-GCM") {
	iv_hex = forge.util.bytesToHex(payload_bytes.slice(0,12));
	aes_auth_tag = forge.util.bytesToHex(payload_bytes.slice(12, 12+16));
	payload_hex = forge.util.bytesToHex(payload_bytes.slice(12+16));
    } else {
	throw("Unrecognized cipher");
    }
    
    // decrypt the wallet
    var decipher = forge.cipher.createDecipher(aes_cipher, forge.util.hexToBytes(encryption_key));

    if (aes_cipher === "AES-CBC") {
	decipher.start({iv: forge.util.hexToBytes(iv_hex)});
    } else if (aes_cipher === "AES-GCM") {
	decipher.start({iv: forge.util.hexToBytes(iv_hex), tag: forge.util.hexToBytes(aes_auth_tag), additionalData: forge.util.hexToBytes(""), tagLength: 128});
    } else {
	throw("Unrecognized cipher");
    }
    
    decipher.update(forge.util.createBuffer(forge.util.hexToBytes(payload_hex)));

    var output_data = null;

    if (decipher.finish()) {
	// decryption succeeded, but need to check output
	try {
	    output_data = JSON.parse(decipher.output.data);
	} catch (err) {
	    output_data = null;
	}
    }

    return output_data; // the decrypted wallet, or null if failed

}

function encryptWallet(payload, password, iterations, aes_cipher) {
    // encrypts the payload
    // payload is in JSON
    // prepends IV (16 bytes) to payload
    // returns Base64 iv+payload, and salt

    var salt_bytes = forge.random.getBytesSync(16);
    var key_bytes = forge.pkcs5.pbkdf2(forge.util.encode64(forge.util.hexToBytes(getSHA256(password))), salt_bytes, iterations, 32, "sha256");

    var iv_bytes = null;

    if (aes_cipher === "AES-CBC") {
	iv_bytes = forge.random.getBytesSync(16);
    } else if (aes_cipher === "AES-GCM") {
	iv_bytes = forge.random.getBytesSync(12);
    } else {
	throw("Unrecognized cipher");
    }
    
    var cipher = forge.cipher.createCipher(aes_cipher, key_bytes);

    if (aes_cipher === "AES-CBC") {
	cipher.start({iv: iv_bytes});
    } else if (aes_cipher === "AES-GCM") {
	cipher.start({iv: iv_bytes, additionalData: forge.util.hexToBytes(""), tagLength: 128});
    } else {
	throw("Unrecognized cipher");
    }
    
    cipher.update(forge.util.createBuffer(JSON.stringify(payload)));
    cipher.finish();

    var encrypted_payload = null;

    if (aes_cipher === "AES-CBC") {
	encrypted_payload = iv_bytes + cipher.output.data;
    } else if (aes_cipher === "AES-GCM") {
	encrypted_payload = iv_bytes + cipher.mode.tag.data + cipher.output.data;
    } else {
	throw("Unrecognized cipher");
    }
    
    var response = {
	salt: forge.util.encode64(salt_bytes),
	payload: forge.util.encode64(encrypted_payload),
	cipher: aes_cipher
    };

    var decrypted_payload = decryptWallet(response.payload, password, response.salt, iterations, aes_cipher);

    if (decrypted_payload === null || JSON.stringify(decrypted_payload) !== JSON.stringify(payload)) {
	throw("Unable to decrypt encrypted payload.");
    }
    
    return response;
    
}

function testBrowserEncryption(){
    var result = false;
    try {
	encryptWallet({a:1}, forge.util.bytesToHex(forge.random.getBytesSync(12)), 1000, "AES-CBC");
	encryptWallet({a:1}, forge.util.bytesToHex(forge.random.getBytesSync(12)), 1000, "AES-GCM");
	result = true; // if we got here, we're fine
    } catch (err) {
	result = false;
    }

    try {
	var s_special = "`1234567890-=~!@#$%^&*()_+abcdпароль";
	var s_normal = "`1234567890-=~!@#$%^&*()_+abcdefghABCDEFG";
	
	result = (result &&
		  (s_special !== forge.util.encodeUtf8(s_special)) &&
		  (s_normal === forge.util.encodeUtf8(s_normal)) &&
		  (getSHA256(s_special) === "33bc2af5524c1b8512b4d2b06d8f7b5efa30aca50f4f9801a3f0ba01240964e6") &&
		  (getSHA256(forge.util.encodeUtf8(s_special)) === "4b21f9780a8ce6fec928c0754b0e55ddb7298308a72f21a8f0120019819c6644") &&
		  (getSHA256(s_normal) === "5962ca3e3114351e42762683bd861eaa735e8c8ca07378c63330fcaccc504a56") &&
		  (getSHA256(forge.util.encodeUtf8(s_normal)) === "5962ca3e3114351e42762683bd861eaa735e8c8ca07378c63330fcaccc504a56"));
    } catch (err) {
	result = false;
    }
    
    return result;
}

However with mandatory 2FA it seems, offline recovery is probably not an option anymore.

@3rdIteration
Copy link
Owner Author

3rdIteration commented Mar 26, 2022

Once you have the wallet file it would be fine, so if you want to fix it up and bring a PR then please do.

Basically dogechain support has come through two abandoned sponsored features (so the person sponsoring didn't end up paying on delivery of working code) so I'm not inclined to expand any time on this wallet type beyond approving a PR.

@jimtje
Copy link

jimtje commented Mar 26, 2022

I can certainly do that, but I'm not sure how much utility the feature would have. My old dogechain wallet, which did not have 2FA enabled, had it forced upon it at some point in the last few months and since it's linked to my old school email that I no longer have access to, I'm effectively locked out. I have it backed up, but if I remember correctly the most obvious way to back up one's account is the plaintext pdf. Any new account I open have the same problem - 2FA enforced logins. Is this specific feature one that is frequently asked about beyond the two abandoned sponsors? Because it feels particularly niche, all things considered.

I maintain a library for opening legacy format wallets and while a different use case, I'd be happy to integrate/solve problems that actual long time crypto users have ran into, like figuring out what coin is in a particular wallet.dat file as in #80 - and the feature would also do the same for passworded but not encrypted wallet files - and bitcoinj-based wallets and keyfiles as well. If you think that's within the scope of this repo I'd be happy to add that set of features instead, as almost inevitably I find myself referring those who ask questions about my library to this repo.

@BeatTheBullets
Copy link

@jimtje I am currently trying to regain acces to an old wallet of mine from 2017. I had given up hope on this wallet but recently discovering this btcrecover program I would like to give it another try. So it is very unfortunate that the one wallet type I am trying to recover has broken due to this recent update.

I have acces to my 2FA so I have been able to download the wallet file(looks the same as the example above from 3rdItteration), but now I need to decrypt it so the btcrecover program can use it again. I have taken a look at your wallet decryptor javascript code but I am unsure how to run it with the wallet. I would very much appreciate it if you could help with this matter.

@3rdIteration
Copy link
Owner Author

@jimtje I am currently trying to regain acces to an old wallet of mine from 2017. I had given up hope on this wallet but recently discovering this btcrecover program I would like to give it another try. So it is very unfortunate that the one wallet type I am trying to recover has broken due to this recent update.

I have acces to my 2FA so I have been able to download the wallet file(looks the same as the example above from 3rdItteration), but now I need to decrypt it so the btcrecover program can use it again. I have taken a look at your wallet decryptor javascript code but I am unsure how to run it with the wallet. I would very much appreciate it if you could help with this matter.

Support could be fixed if you want to sponsor it.

@BeatTheBullets
Copy link

@3rdIteration What would this sponsorship entail (specifics)?

@3rdIteration
Copy link
Owner Author

It's already half done, so would basically just be $250 USD. Once the sponsorship payment was recieved then the feature would be completed and merged within two weeks.

@BeatTheBullets
Copy link

@3rdIteration It is good to hear that it is almost finished. Unfortunately I do not have that kind of money right now.

@sa976171
Copy link

sa976171 commented Apr 1, 2024

Can you please fix the issue. I have 30k dogecoin in dogechain wallet. I will donate to the creator if i am able to recover it

@3rdIteration
Copy link
Owner Author

I'm happy to look at it as a trusted recovery if you like.

@tdfd2024
Copy link

tdfd2024 commented May 4, 2024

I'm happy to look at it as a trusted recovery if you like.
Hello,
image
dogechain.info will stop functioning on June 1st, could you help us decipher the code? What good will the code be if it is of no use to anyone? I think everyone who can restore access to their dogecoins will thank you financially

@3rdIteration
Copy link
Owner Author

If you want a trusted recovery then you can request one here: https://cryptoguide.tips/recovery-services-consultations/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Low Priority Likely to be one of the last issues to be looked at
Projects
None yet
Development

No branches or pull requests

5 participants