Xor seedsave
Thanks for contributing to COLDCARD source code, please be as descriptive as possible.
- If you haven't yet, please check out our docs https://coldcardwallet.com/docs/
- Have you tested your work yet? You can do it with the simulator https://github.com/Coldcard/firmware/blob/master/unix/simulator.py
By submitting this work you agree to the Individual Contributor License Agreement (CLA)
I hope this is useful and not controversial, I am building on the seed xor work (love it btw).
TODO list: [x] Implement loading from file [x] Implement saving to file [x] Manually test edge cases [x] Make existing tests pass [ ] Create new tests to cover new functionality
This PR will introduce saving and restoring XOR from sd cards.
The idea here, is that similar to passphrases, you can store one seed on the device, and another on an SD card. When you wish to sign, you must log in using your pin, then you must restore the seed xor from file and you may then sign a transaction, bringing a more secure alternative to the passphrase.
Of course, this is not a replacement for backing up the XOR seed words.
When creating an XOR file, you are told to have your seed words ready, this is a hint to have an already valid seed word. As the ColdCard is not creating the words, there is no need for a quiz.
Loading from SD Card is not enabled if you have no existing seed words (eg. first time use). This makes no sense anyway as the file is encrypted using an existing xpriv, so if you don't have an existing xpriv, we can't decrypt the file anyway.
When you are restoring seed XOR words, you will be asked whether you wish to "enter manually" or load from sd card.
The code is defensive, and if reading, decrypting or parsing the file fails, then the user will see a message, no action was taken, and they will be able to continue where they left off.
One thing that is novel here, is that once the XOR has been applied, you cannot decrypt the file anymore as we will always use the currently in use private key to decrypt and parse any xor files.
A user can store multiple xor files on multiple sd cards and restore them, or they can put them all on one sd card.
You are NOT offered to save your XOR to file after creating one, that feels complicated. Instead, you are able to create XOR files at any time through a separate menu.
I have no idea why there are these other commits in this PR, I have run git fetch --all, the branch should be rebased on master. Any ideas?
- we just recently merged all the mk4 code onto master, maybe that's an issue?
nvm, I wasn't looking properly, my commits were off another branch, not master. That has been resolved now.
Let me know if this is valuable, I plan to write something along the lines of these tests:
#def test_import_xor_file()
# TODO:
# - test when sdcard is missing
# - test when no files found
# - test when 1 file found
# - test when 2 files found
# - test choosing a bad file
#def test_export_xor_file()
# TODO:
# - test when sdcard is missing
# - test when no files exist
# - test when conflicting file exists
# - test when using tmp_secret
#def test_import_xor_file_and_manual()
Not sure if all of the use cases will be testable though, for example, I don't know if I can make a test assuming that there is no SD card since the tests don't control the emulator's startup.
It is useful. We were planning to do something similar, except with just XOR of 1.. so you might call it "ephemeral seeds"
I deleted and re-init the repo now that I've rebased, I'm trying to get the thing to build.
I am getting the following errors when I run pip install -r requirements.txt
error: subprocess-exited-with-error
× python setup.py bdist_wheel did not run successfully.
│ exit code: 1
╰─> [8 lines of output]
running bdist_wheel
running build
running build_py
running build_ext
building 'smartcard.scard._scard' extension
swigging smartcard/scard/scard.i to smartcard/scard/scard_wrap.c
swig -python -outdir smartcard/scard -DPCSCLITE -o smartcard/scard/scard_wrap.c smartcard/scard/scard.i
error: command 'swig' failed: No such file or directory
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for pyscard
Running setup.py clean for pyscard
Failed to build pyscard
Installing collected packages: pyscard, pydes, pycoin, pyaes, pbkdf2, ndeflib, namedlist, libusb1, iniconfig, toml, six, pyusb, pyparsing, py, pluggy, Pillow, numpy, nfcpy, mnemonic, hidapi, click, attrs, zbar-py, packaging, onetimepass, ndef, ecdsa, pytest, ckcc-protocol
Running setup.py install for pyscard ... error
error: subprocess-exited-with-error
× Running setup.py install for pyscard did not run successfully.
│ exit code: 1
╰─> [10 lines of output]
running install
/home/dipunm/Projects/coldcard/firmware/ENV/lib/python3.10/site-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
warnings.warn(
running build
running build_py
running build_ext
building 'smartcard.scard._scard' extension
swigging smartcard/scard/scard.i to smartcard/scard/scard_wrap.c
swig -python -outdir smartcard/scard -DPCSCLITE -o smartcard/scard/scard_wrap.c smartcard/scard/scard.i
error: command 'swig' failed: No such file or directory
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure
× Encountered error while trying to install package.
╰─> pyscard
note: This is an issue with the package mentioned above, not pip.
hint: See above for output from the failure.
Any idea why/what I need to install to get this to build now?
Thanks @doc-hex
I am running Arch Linux by the way, but if there is a specific piece of debian software that I need, I can usually find it's equivalent in the Arch package repository.
NVM, new dependency required from linux repository: swig
I'm struggling to get tests passing. I've tried the following commands:
pytest --sim
pytest --sim -m "not bitcoind and not qrcode and not unfinalized"
pytest --sim -m qrcode
I had to make a change to conftest.py around line 534:
try:
m = cap_menu()
except RuntimeError:
continue
This was because after running the tests in test_addr.py, the tests in test_address_explorer.py expect that after pressing x, you should be presented with a menu, but you are presented with a QR code instead so the tests fail when running after one another. This change allows the tests to press x repeatedly until a menu is presented without exceeding the 10 iteration limit. (for i in range(10):)
Now I am struggling with tests that assume NFC is enabled.
I can of course run tests by file, however, I\d like to understand how should I be ensuring that my tests are well written and will not break other tests?
Also, is there a way to write a test that can force the simulator to think it has no SD card without requiring manual intervention?
Thanks.
with regards to SD card - what you're looking for is --eject passed to simulator. Also check unix/README.md for more simulator options.
Recently we've also added testing/run_sim_tests.py (git pull --rebase upstream/master)which is basically a retry test runner. Check it out, maybe you're just experiencing intermittent failures - that can be resolved with running concrete test against fresh simulator.