Open mjg-foundation opened 1 year ago
I'm offering an additional 2 XMR to the bounty
Do Foundation devices support alloc? I do see they're no_std.
Do Foundation devices support alloc? I do see they're no_std.
Alloc functionality is available in C micropython interfaces using m_new
and m_del
, see extmod/foundation/modfoundation-ur.h
for example
Yeah, I'm asking regarding Rust.
It looks like https://github.com/rust-embedded/embedded-alloc could be introduced to offer Rust alloc. Would that be unacceptable?
To clarify, I'm fine with Rust yet I've never worked on embedded devices with it. I have no idea the larger implications of defining an allocator on Rust's side. I don't see why it'd be an issue, but it may significantly increase code size to unacceptable degrees or may break C expectations or...
Yeah, I'm asking regarding Rust.
I haven't worked much with our rust libs, so I would err on the side of safety. This isn't intended to be an oxidation project, unless it so happens that way and it works better.
https://docs.rs/monero-serai/0.1.4-alpha/monero_serai/
There is the question of if Rust should be used here. I'd say yes, if it works. monero-serai offers all the necessary functionality discussed on the passport side, without known security issues (its TX creation code is currently non-standard, but the passport would solely sign TXs).
I'm also willing to work on integrating monero-serai. I'd, personally, refuse to touch the Monero codebase for this. While libringct alone (the TX signing code) would be fine, moving over multisig would require moving over wallet2 which is a monolith without praise. Solely acknowledgement it does what it needs to.
Then if we look for what other projects did, Trezor rewrote vast swaths of Monero in Python:
https://github.com/trezor/trezor-firmware/blob/master/core/src/apps/monero/xmr/bulletproof.py
monero-serai would offer constant time versions with secure memory handling (though I'm unsure how much of a concern that is given its a HW wallet).
TL;DR I legitimately believe monero-serai would be a solid candidate for the Foundation, if usable. I'd be willing to work on this. If you'd rather Python work be applied, or the Monero C/C++ code, I will respect that. I just am not personally interested in picking up such work, and will leave this open to other developers.
Sorry if these messages were a bit too aggressive/forward :sweat_smile: They were just meant to be to the point. I'd love to see Monero on Foundation and wouldn't mind doing what I can :)
https://docs.rs/monero-serai/0.1.4-alpha/monero_serai/
There is the question of if Rust should be used here. I'd say yes, if it works. monero-serai offers all the necessary functionality discussed on the passport side, without known security issues (its TX creation code is currently non-standard, but the passport would solely sign TXs).
I'm also willing to work on integrating monero-serai. I'd, personally, refuse to touch the Monero codebase for this. While libringct alone (the TX signing code) would be fine, moving over multisig would require moving over wallet2 which is a monolith without praise. Solely acknowledgement it does what it needs to.
Then if we look for what other projects did, Trezor rewrote vast swaths of Monero in Python:
https://github.com/trezor/trezor-firmware/blob/master/core/src/apps/monero/xmr/bulletproof.py
monero-serai would offer constant time versions with secure memory handling (though I'm unsure how much of a concern that is given its a HW wallet).
TL;DR I legitimately believe monero-serai would be a solid candidate for the Foundation, if usable. I'd be willing to work on this. If you'd rather Python work be applied, or the Monero C/C++ code, I will respect that. I just am not personally interested in picking up such work, and will leave this open to other developers.
Whatever works for you! I'm not gonna gatekeep the codebase, and if you produce a PR that signs monero transactions correctly and robustly (with relatively clean coding style and structure), I'll approve it.
I'm still new to rust, and have not used it at all professionaly, but I'm interested in the stability and productivity gains it can bring here. I just advise against oxidating too much at a time to the point where it becomes prohibitive to review
Totally understand. I'm still reviewing if monero-serai is even feasible in a no_std environment (which is of independent interest to me). The last thing I want to do is submit monero-serai for seeds, then hear the rest of it is unusable and it can't do signing.
@mjg-foundation I managed to build monero-serai, a Rust library offering:
for the Passport (no_std, its cortex-m chip). Since it's no_std, I did have to remove the net code (and with it the scanning/TX creation code). Nothing removed should be relevant to on-passport usage though.
https://github.com/kayabaNerve/passport2-monero demos it being bound and is able to successfully generate seeds (re: binding, not any updated UI).
Regarding the choice of library, it's just meant to be a well-designed, modern Monero library. I could get all the Python code from Trezor, which has been used in this env (HW wallets) before, yet am biased towards monero-serai due to being the author. I also know I can trust monero-serai yet haven't personally reviewed Trezor's work. On a practical note, I'd note how I assume the Rust to be more performant/featured (primarily re: multisig).
If you're concerned about security (as monero-serai is relatively new), there are known issues. Luckily enough, the know issues line up with the code removed to fit in no-std. This does mean monero-serai isn't an immediate candidate for pairing up on the laptop/desktop/phone side though. I have a developer working on those, and then we're planning to have monero-serai audited as well (hopefully over the next few months).
I'll follow up when the UI binding is done. I have to grab a device with a camera... Then, you're more than welcome to accept my PR, or decline it as sure, it's notably (and unexpectedly) increasing the carcinization. I would not be offended and have no plans to beg/complain for payment if you don't believe it's the right fit.
Wow, that was fast! Make sure to go through DEVELOPMENT, and ensure that just build color
and just build mono
work, just clean
ing in between. Use the simulator to test out UI binding, and let me know when it's ready to test!
By test, I mean run on hardware and make sure it isn't totally broken.
It sounds like seraphis relies on a future version of monero, so this issue would be in limbo until seraphis is made official, as far as proper testing. I'll look into seraphis, and start a "discussion" in github about the options of seraphis vs ringct. This could turn into a huge debate, but it's important we do things right.
@kayabaNerve I think I misinterpreted your comments. So we've got seraphis support on deck but this bounty will continue for RingCT?
I'm missreading seria as seraphis 😅, carry on
After re-reading with an eye adjustment, that all sounds very good. If you have devs working on mobile, consider taking bounty #3 , or assisting with it. Barring any objections, I'm fine with moving forward with your approach.
@Monero-HackerIndustrial mentioned that we have an opportunity here to establish standards for broad compatibility among monero wallets for seed creation, unsigned transaction formatting, and signing, similar to the BIPs
The seed here is the never-formally specified Monero seed algorithm. The only alternative is Polyseed, which is formally defined, yet also only implemented into Polyseed (with a PR for monero-serai). While it's a much better format, it's hard to recommend it for use here since Monero proper doesn't support it (though it is possible to convert a Polyseed to a seed).
As for the rest of those items, I'd point discussion to #6.
Working on stash.py, almost all of this is fundamentally incompatible with Monero. The amount of code for fingerprints/xpubs/accounts has to be completely slashed.
Also, the Monero seed won't fit into storage. It's at minimum 100 bytes. Only the master key will.
While I've updated stash.py, it's completely breaking to most other components. At this time, I don't want to slash and burn the entire codebase to correct for that.
Should be ready for my testing in a simulator. If the needed UX steps, detailed in the original post work, I'll submit this for testing on a real device (not there yet).
As mentioned on twitter, I would be very happy if the data stored in the SE can be used by both the original firmware and this firmware, so users wouldn't need to erase when switching or buy a second device. Up to you to decide feasibility.
Also do feel free to slash and burn by commenting sutff out, I understand that most of the functionality will need to be rewritten. The UI can be left with nothing but the setup process, main page, hardware management stuff (brightness, auto shutdown, FCC info, etc), backups, and advanced -> view seed words
@kayabaNerve someone pointed out to me that trezor has a working, python-based, GPL3 monero cold signing library. This could be a more efficient way to work with what we've already got. Thoughts?
I add 1XMR to the bounty
@mjg-foundation
https://github.com/mjg-foundation/passport2-monero/issues/4#issuecomment-1518426008
Then if we look for what other projects did, Trezor rewrote vast swaths of Monero in Python:
https://github.com/trezor/trezor-firmware/blob/master/core/src/apps/monero/xmr/bulletproof.py
monero-serai would offer constant time versions with secure memory handling (though I'm unsure how much of a concern that is given its a HW wallet).
TL;DR I legitimately believe monero-serai would be a solid candidate for the Foundation, if usable. I'd be willing to work on this. If you'd rather Python work be applied, or the Monero C/C++ code, I will respect that. I just am not personally interested in picking up such work, and will leave this open to other developers.
I discussed this a while ago. My reasons for monero-serai, besides personal bias, are features/presumed performance.
I'd also note: 1) monero-serai will be audited. I don't believe Trezor's work has. 2) I personally am not a fan of Trezor's flow.
https://github.com/trezor/trezor-firmware/tree/master/core/src/apps/monero/signing
They use a builder pattern, which is fine, yet I question the quality of a 10-step process. This is likely simply since I'm unused to their library and haven't fully seen it/its flow.
3) Their messages aren't minimal.
https://github.com/trezor/trezor-firmware/blob/master/core/src/trezor/messages.py#L3852-L3872
This mirrors a struct in wallet2, and has an address, yet also decoded data about the address. This introduces an inconsistency possibility which needs to be checked when decoding. Ideally, these fields aren't decoded at all, and simply set if needed (since their communication isn't valuable when they must be independently derived anyways to be verified).
The library overall, at first glance, does seem comprehensive and well written though. I wouldn't directly object to its usage.
@kayabaNerve Any progress on this? I'm excited to get it compiling on my machine, and curious what the binary size is
I didn't notice this issue so commenting now. This one should be pretty straightforward for me to help with.
Monero seed word generation using diceware (built with monero python library).
https://github.com/Monero-HackerIndustrial/MoneroDice-WalletGen I am going to change the KDF to match the one that polyseed uses.
capture_xpub: derive whatever key or data is needed to generate new subaddresses
There is an address and subaddress index. It is already built into the monero python library.
predictive_utils.py: use monero word dictionary, will need to replace modfoundation-bip39.h with a monero equivalent I started this process from monerosigner. https://github.com/Monero-HackerIndustrial/PortableMoneroQR/tree/main/wordlist
Most of the functions that you are asking for are already built in to the monero python library. If you don't mind having the monero python library be a dependency I can help add those changes pretty simply.
To follow up on the trezor library singing question. I believe that there were some hardware constraints with how signing needed to happen on a trezor that dictated some of the design decisions.
Transaction signing was not a big constraint on monerosigner since I could use a monerod node in offline to sign with it. It would be very nice to have a well documented python example of raw tx signing. I will take a look at the trezor code to see if I can use it to make an example python signing.
@Monero-HackerIndustrial Sounds good, if you can get monero-python into the firmware. It may be most efficient to not directly add it as a dependency, but bring over specific necessary files
I haven't had the time to further work on this, so I'm fine stepping to the side.
I'm setting aside some time to take a look at this Friday. I can bring over the needed specific files. For passport, do you support other language seed phrases other than English?
I planned on bringing over the other language wordlist regardless.
I'm setting aside some time to take a look at this Friday. I can bring over the needed specific files. For passport, do you support other language seed phrases other than English?
I planned on bringing over the other language wordlist regardless.
We don't, but feel free to!
For the route of cutting out the non needed portions of the monero python library. How do I tag those files for licenses?
Do I just add: SPDX-License-Identifier: {$SPDX_license_name} And a reference to the original file at the top of the document?
I started working on creating a portable version of the seed library called pureSeed.py
I'll eventually add some tools for converting different seed types (Trezor, Ledger, Mymonero & Polyseed). Making it a separate repo then will move over the completed version into a pr.
Couple of questions on the existing passport codebase.
In passport2-monero/simulator/sim_modules/passport/__init__.py
I see :
SPDX-FileCopyrightText: © 2020 Foundation Devices, Inc. <hello@foundationdevices.com>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# __init__.py - Simulated replacements for some Foundation code
#
import sys
from urandom import randint, seed
from utime import ticks_ms
IS_SIMULATOR = True
IS_COLOR = sys.argv[6] == 'color'
IS_DEV = True
HAS_FUEL_GAUGE = False
class Noise:
AVALANCHE = 1
MCU = 2
SE = 4
ALS = 8
ALL = AVALANCHE | MCU | SE | ALS
def __init__(self):
v = ticks_ms()
# print('Initialize RNG with seed = {}'.format(v))
seed(v)
def random_bytes(self, buf, _source):
for i in range(len(buf)):
buf[i] = randint(0, 255)
common.py contains this variable:
# Avalanche noise source
noise = None
I see a noise c file and matching header file. I see the function inside there
bool noise_get_random_bytes(uint8_t sources, void* buf, size_t buf_len);
I am guessing that the simulated functions are to make debugging easier on a simulator. How does the device generate that entropy? How is common.noise.random_bytes(seed, common.noise.ALL)
actually called from the python code on a device? Is there a cytpe loader or is that already exposed in the device environment?
Also a couple of notes on current seed generation:
# Hash to mitigate any potential bias in RNG sources
seed = trezorcrypto.sha256(seed).digest()
I would advocate for having some KDF to generate the key from the random source. In the bitcoin space there is a standard under bip39 for raw entropy to seed. There is no equivalent standard for monero. Here is a thread on creating a standard for monero KDF seeds: I can take care of standardizing it for you.
Is there any constraints for using sha512 instead of sha256 for the KDF on the monero version? I was thinking of using this pattern for the seed:
#the new way uses the key derivation of
#https://github.com/diybitcoinhardware/embit/blob/2bf81739eb5f01f8ad59d23c492fd9d9564eed48/src/embit/bip39.py#L86
PBKDF2_ROUNDS = 2048
#password used for the salt (a sha256sum )
password = hashlib.sha256(dice_rolls.encode()).digest()
entropy_bytes = hashlib.pbkdf2_hmac(
"sha512",
dice_rolls.encode("utf-8"),
password,
PBKDF2_ROUNDS,
32,
)
hex = entropy_bytes
hex = hex.hex()
s = Seed(hex)
phrase = s.phrase
public_address = s.public_address()
This is basically the same as bip39 I use the same #of iterations but changed PBKDF2-HMAC-SHA256 to PBKDF2-HMAC-SHA512?
Excuse my ignorance on how the foundation device creates entropy. I am just getting started looking at the code and could be wrong. I just didn't see a KDF for randomness to seed. Is there a reason for this ? (Is the source of randomness trusted enough should you still run a KDF?)
Thank you in advance! (FYI None of these questions are blockers for me, I am working on porting over the wordlists but would like to understand the device better).
Someone deleted their bounty of 2 XMR, bringing this down to 3 XMR total.
Someone deleted their bounty of 2 XMR, bringing this down to 3 XMR total.
I'm assuming this is referring to the bounty I offered. I don't know why but my comment dissapeared. When I logged into github the reply magically reappeared. Not sure how that's possible.
To be clear, I'm still offering the bounties I originally pledged for this and the other open issues.
Should prs be opened directly to main branch?
Should prs be opened directly to main branch?
Yep!
I started working on creating a portable version of the seed library called pureSeed.py
I'll eventually add some tools for converting different seed types (Trezor, Ledger, Mymonero & Polyseed). Making it a separate repo then will move over the completed version into a pr.
Couple of questions on the existing passport codebase.
In
passport2-monero/simulator/sim_modules/passport/__init__.py
I see :SPDX-FileCopyrightText: © 2020 Foundation Devices, Inc. <hello@foundationdevices.com> # SPDX-License-Identifier: GPL-3.0-or-later # # __init__.py - Simulated replacements for some Foundation code # import sys from urandom import randint, seed from utime import ticks_ms IS_SIMULATOR = True IS_COLOR = sys.argv[6] == 'color' IS_DEV = True HAS_FUEL_GAUGE = False class Noise: AVALANCHE = 1 MCU = 2 SE = 4 ALS = 8 ALL = AVALANCHE | MCU | SE | ALS def __init__(self): v = ticks_ms() # print('Initialize RNG with seed = {}'.format(v)) seed(v) def random_bytes(self, buf, _source): for i in range(len(buf)): buf[i] = randint(0, 255)
common.py contains this variable:
# Avalanche noise source noise = None
I see a noise c file and matching header file. I see the function inside there
bool noise_get_random_bytes(uint8_t sources, void* buf, size_t buf_len);
I am guessing that the simulated functions are to make debugging easier on a simulator. How does the device generate that entropy? How is
common.noise.random_bytes(seed, common.noise.ALL)
actually called from the python code on a device? Is there a cytpe loader or is that already exposed in the device environment?Also a couple of notes on current seed generation:
# Hash to mitigate any potential bias in RNG sources seed = trezorcrypto.sha256(seed).digest()
I would advocate for having some KDF to generate the key from the random source. In the bitcoin space there is a standard under bip39 for raw entropy to seed. There is no equivalent standard for monero. Here is a thread on creating a standard for monero KDF seeds: I can take care of standardizing it for you.
Is there any constraints for using sha512 instead of sha256 for the KDF on the monero version? I was thinking of using this pattern for the seed:
#the new way uses the key derivation of #https://github.com/diybitcoinhardware/embit/blob/2bf81739eb5f01f8ad59d23c492fd9d9564eed48/src/embit/bip39.py#L86 PBKDF2_ROUNDS = 2048 #password used for the salt (a sha256sum ) password = hashlib.sha256(dice_rolls.encode()).digest() entropy_bytes = hashlib.pbkdf2_hmac( "sha512", dice_rolls.encode("utf-8"), password, PBKDF2_ROUNDS, 32, ) hex = entropy_bytes hex = hex.hex() s = Seed(hex) phrase = s.phrase public_address = s.public_address()
This is basically the same as bip39 I use the same #of iterations but changed PBKDF2-HMAC-SHA256 to PBKDF2-HMAC-SHA512?
Excuse my ignorance on how the foundation device creates entropy. I am just getting started looking at the code and could be wrong. I just didn't see a KDF for randomness to seed. Is there a reason for this ? (Is the source of randomness trusted enough should you still run a KDF?)
Thank you in advance! (FYI None of these questions are blockers for me, I am working on porting over the wordlists but would like to understand the device better).
Sorry I forgot to come around to this. The simulator C files mock out the device functionality, so yeah on the device the avalanche rng is used. I'm not a hardware guy and I joined foundation pretty late in passport's development, so I'm not too familiar with the design decisions and some of the more permanent code like seed generation. The only limitation on the seed is what entropy can be stored in the secure element. IIRC we store entropy and parse it into a seed on demand, but I can double check that tomorrow (I'm shitposting from the gym rn)
Edit: If you look at the call to SecretStash.encode(seed_bits), and the encode function in stash.py, you can see what's being saved and how it's encoded.
The first step in replacing bitcoin with monero in this project will be creating monero seeds. Users should be able to:
Here are the places to start work:
Much of the functionality needed is probably available in extmod/trezor/crypto/monero/. I'll start the bounty off at 2 XMR, and hope more can flow in from the community.
bounty: 2 XMR