Open olalonde opened 10 years ago
I think I found it: https://github.com/etotheipi/BitcoinArmory/blob/99c8cd151eba47f1100307e85337779537cee345/armoryengine/PyBtcAddress.py#L451
Also, brainwallet.org has an implementation here: https://github.com/brainwallet/brainwallet.github.com/blob/master/js/armory.js
Is it up to date?
I can't find any way to get the (public key, chain code) from the UI... How is this done?
The KdfRomix class takes care of it.
Code can be found in EncryptionUtils.cpp, notably:
void KdfRomix::computeKdfParams(double targetComputeSec, uint32_t maxMemReqts) SecureBinaryData KdfRomix::DeriveKey_OneIter(SecureBinaryData const & password)
You can right click on any address in the wallet property window to get its 65 bytes hex public key.
I dont think chaincodes are exposed to the UI anymore since we started deriving it from the rootkey.
Any address entry in the PyBtcWallet addrMap member carries a chaincode value. All chaincodes in a given wallet are the same.
Ok, I got this out of the Backup wallet feature (I won't be using this wallet, no worries)
1PUzLkds8eHGjHPaW7v7h23bzmHjrRMVqz
PublicX : 9df5 23e7 18b9 1f59 a790 2d46 999f 9357 ccf8 7208 24d4 3076 4516 b809 f7ab ce4e
PublicY : 66ba 5d21 4682 0dae 401d 9506 8437 2516 79f9 0c56 4186 cc50 07df c6d0 6989 1ff4
ChainIndex: 0
Not sure what is the chain code though.
@goatpig thanks! So there's no way to get the chain code out of the UI? How could someone back up a watch-only copy of their wallet for example? Or do you always need to backup the root key as well?
There is no option to create paper backups of WO wallets if it's what you are asking for, only digital ones.
Ah ok I see. Is the root code alone sufficient to derive private keys? Let's say I wanted to code a Armory compatible watch only wallet... Is there any way I could do that or the Armory UI won't let me get out the necessary information? I suppose I could parse the digital watch only backup created by Armory but I'd rather find an easier way :)
The root key is used to derive the chaincode and the first address pair. Address pair N+1 is derived from address pair N, through a scalar which is:
sha256(sha256(pubKey N)) XOR chaincode
Both the private and public keys are multiplied by this scalar to yield the next pair.
Exact code can be seen in EncryptionUtils.cpp:
SecureBinaryData CryptoECDSA::ComputeChainedPrivateKey( SecureBinaryData const & binPrivKey, SecureBinaryData const & chainCode, SecureBinaryData binPubKey, SecureBinaryData* multiplierOut)
SecureBinaryData CryptoECDSA::ComputeChainedPublicKey( SecureBinaryData const & binPubKey, SecureBinaryData const & chainCode, SecureBinaryData* multiplierOut)
This gives you 2 options:
With the root key alone, you can rebuild an entire wallet. With the chaincode and the first public key, you can reproduce the entire watching only wallet.
Also, with private key N and the chaincode, you can reproduce all private keys past N, and with pbulic key N and the chaincode, you can reproduce any public keys past N
Ok thanks a lot for your time. It would be really great if it was possible to get this chain code out of wallet in a safe way so that it can be imported in a compatible wallet. Right now it seems the only options are
1) to copy/paste the root key and use a third party tool to generate the chain code which is not ideal because it relies on trusting a third party tool.
2) have the third party support the file Armory's digital watch-only backup format which is a bit a PITA
Cheers.
Are you talking from a user or developer standpoint? It is fairly easy as a dev: Build the binaries, grab your favorite Python debugger, start Armory with a wallet, break a this line:
https://github.com/etotheipi/BitcoinArmory/blob/master/armoryengine/PyBtcWallet.py#L1846
and watch self.addrMap['ROOT'].chaincode.
For users, there is no hook in place currently that I can think of to get the chaincode through the UI.
Yes, I was talking from a user's standpoint. I guess I could release a small self contained script that lets users get the chain code out of their paper backup phrase that they can run locally.
I think ideally you want to look at the code early in PyBtcWalletRecovery.py, in the ProcessWallet function. It is self contained and will run on its own when spawned from Armory's source folder. It only needs to go as far as this line:
https://github.com/etotheipi/BitcoinArmory/blob/master/armoryengine/PyBtcWalletRecovery.py#L449
and can run with just a wallet path. That's enough to read any wallet and extract the first address entry.
Question: what do PublicX
and PublicY
represent in the paper wallet? I tried generating an address using them but the address is not one in my wallet.
X and Y parameters for the secp256k1 curve point.
Looking at the 65 bytes SER public key packaging, it goes 0x04 X Y
Hey, I managed to get the public key derivation code to work :) That being said there is something that really puzzles me. When I start deriving from the public key 04 + PublicX + PublicY
(049df523e718b91f59a7902d46999f9357ccf8720824d430764516b809f7abce4e66ba5d2146820dae401d95068437251679f90c564186cc5007dfc6d069891ff4
), the result looks like this:
1CGrip2uQUwhP2f3ARfbcrmtdwvWzELRmj
1BfBauMP4PX1ZBYrqH4K4R8KWrFfskrs7E
15emDCBVgBJLDP5cKxuwZ4Q77sfqEcwZvC
16tDJhMYBv1szZgRZCohWrzEvzX2bG7vEQ
1c6NUxFe9xo5fsS8ACBsHNFYTvHQP3qzu
However, the expected output is:
1PUzLkds8eHGjHPaW7v7h23bzmHjrRMVqz
1CGrip2uQUwhP2f3ARfbcrmtdwvWzELRmj
1BfBauMP4PX1ZBYrqH4K4R8KWrFfskrs7E
15emDCBVgBJLDP5cKxuwZ4Q77sfqEcwZvC
16tDJhMYBv1szZgRZCohWrzEvzX2bG7vEQ
So basically it looks like 04 + PublicX + PublicY
is the second public key in an Armory wallet?
http://brainwallet.org/#chains gets this right but they compute the public key from the paper wallet. 045a09a3286873a72f164476bde9d1d8e5c2bc044e35aa47eb6e798e325a86417f7c35b61d9905053533e0b4f2a26eca0330aadf21c638969e45aaace50e4c0c87
. Is there any way to compute this key from PublicX
and PublicY
in the paper wallet. Or am I doing something wrong?
Oh, stupid mistake in my code, works fine now.
I just tasked one of our guys with adding these features. It will include a new six-line export and import function, using Armory's easy-type-16 format (so it will have the same alphabet and checksums as regular paper backups). Plan to allow paper or text-file export, and a new import-watchonly-root-key function that would allow you to type the 6 lines or load the six lines from file. We're not sure when we'll have it, but it shouldn't be terribly long, and we can include it the multisig-beta build we're releasing soon.
Wow, awesome!!! (we had started working on a proof of concept here http://maxrann.github.io/armory-mpk/ but if you guys support something like this natively, even better!). If you're curious, we needed this to support Armory on https://www.coldmonitor.com
This is still an issue, isn't it? Can one derive public keys / addresses from some read only data provided to the user of armory in decent way? I would be very excited about a headsup for the new wallet format.
Hi. I will try to implement Armory's key derivation algorithm for Bitcore (Javascript). Is there any existing Javascript implementation? Where is the algorithm located and is there a higher level description available? If I understand correctly, Armory uses a custom scheme but plans to implement BIP32 eventually?