Building a unified Ethereum experience for Hardware Signers

EthCC[9] · 2 Apr 2026 · 20:26

Btchip examines clear signing for Ethereum hardware devices. The presentation considers how a consistent signing experience can help users understand transactions while accommodating the limited resources of dedicated signers.

Speakers

Topics

From EthCC[9], hosted by Ethereum France.

Transcript

Hi everybody. Thanks for coming this morning. So, I'm Nicola. I'm co-founder of Ledger, CEO of ZKNUX, and today I'm going to tell you why we need to build a new experience for hardware wallet to sign Ethereum transactions. So, I have a lot of slides, so as the famous hedgehog would say, I'm going to go fast, but here we are. >> [snorts] >> Let's start with the threats that you have and why hardware wallets are important. We can think of the delivery of the threats. So, you can have phishing, your hosting can be hacked when you adapt.

DNS can be hijacked. I mean, so a lot of stuff you can't prevent. And the worst today are supply chain attacks, which are very very popular. I mean, there was a big one on Axius, I think, yesterday. And in the end, you would end up as a user communicating with a drainer, or something that can steal your crypto. If you read the transaction, you can avoid it, but still you need to read it very carefully. It can you can end up with something that will redirect you to a malicious contract. So, if you just read the ABI in that case, you would lose money. But, well oops sorry.

And your computer could be completely compromised, which is what we are trying to look at today. And usually, if you have a supply chain attack, the result in the attacker is very skilled, is that your computer be compromised. So, we want to prevent we want to protect ourselves against this. What can we do? We can use a hardware wallet. So, everybody should use a hardware wallet. And if you manage funds, even if I hate EDR, so endpoint detection and response, you should have an EDR installed just for the sake of the funds of your users.

So, that's super important. But, now that we said that you should use a hardware wallet, yeah, what are we going to do with a hardware wallet? So, we are going to clear sign. There are a lot of definitions for clear signing. Mine is going to say you want to display as much information as possible about the transaction, and you want to use the minimum number of third parties to do that. So, ideally, you would just have the transaction, and you would work with it. So, what does clear signing looks like in a hardware wallet, and why is that a problem? First thing, you could just say the hardware wallet could just tell you there is data, so you can't do anything with it. It could display part of the data. In that case, it's worse, because it's useless. I mean, you have something you can't do anything with it. It could

display you the call data, then it's hard to understand if you don't have a secondary host or display. It could display it could pass the transaction, display you the different fields, read the read you can read the function descriptors, and it's hard to interpret, but it's a little bit better. And ideally, what you want to do, even if you are a nerd, you want to see a clear name for the descriptor, you want to see a clear name for the parameter, and you want to see the content of the parameters. Problem is, to do that, you need knowledge of the ABI. The ABI is not linked to the contract, and you need to provide the ABI to the device. So, this is an issue with censorship resistance in that case, crops. And when there are issues with crops, I'm going to put a little salad emoji here.

So, next thing, if you're a user, then you have even more problem with crops, because in the end, this is what you want to to show what this is what you want to see on your hardware device. You want to see that you are supplying 10 bolt to Ave. By the way, Ave doesn't support bolt, so just an example. If you are using Safe, you don't want to see the signers, you want to see again that you are providing 10 bolt to Ave. So, you should be able to see the outcome of the transaction, not all the nitty-gritty details. If you are using a wallet which does account abstraction, so using 4337, again, you don't want to see the different steps. You just want to see that you supply 10 bolt to Ave. And in the end, something a little bit different with transaction simulation,

you could see in your account that you are giving 10 bolts, and you are getting 10 Ave bolts, which is another way of saying the same thing, but we will see why this is very different from clear signing. So, the transaction simulation has multiple issues. So, you are simulating the transaction. So, it depends on the current state of the network and of your contract. I just came up with the time time of signing to time of broadcast, so tost up. Please don't use it, because I just came up with it. You can have red pill attacks on the simulation, so someone can corrupt the simulation and make you end up with a result which is not what you will have on the network. And you have privacy issues, because you are sharing all your transaction details to a third party.

So, in my opinion, the proper way to use transaction simulation is to use it as an additional layer, maybe even hidden from the user, and flash a warning if you end up with a big difference in outcome. For example, if the transaction simulation tells you that you are going to supply 10 bolt to Ave, but the clear signing tell you, "Okay, I don't know what this transaction is." You have a problem, and your wallet should abort. So, clear signing we have seen clear signing for transaction. What does that mean for messages? If you have an EIP-191 message, it's just okay signing to something, you want to display the text. If you have a typed message like 712, then you want to read all the parameter, you want to see all the parameters. It's very similar to what you have in a transaction call

data, but here the good thing is that it's described in the message, so you it's self-described, so it's good, because you don't need to provide an ABI. But, if we get into messages which contain themselves transaction like Safe messages, a message that you are going to use when you use Safe, then you should know that it's a transaction, and then you are back to a problem, because you need to have this extra information that is not included in the message itself. So, basically, the problem that we have to clear sign on hardware devices is that we are missing context. So, we are either missing the ABI, with the ABI, we are missing context.

With the EIP-712, we are missing context. For example, if you see that the parameter is an asset, but this parameter should be considered as a token in a contract, having the ABI is not enough. And same thing for message for a transaction hidden in a 712 message. So, the different crops problems that we have everything, I mean, the most the problem I will focus on are censorship resistance, because to do all that, you need to have created list registries signatures, and this is, of course, not censorship resistant, because you need to either you can choose your own list, but if you want to add an item to the list, it leads to more question.

So, there have been on-chain solutions to this problem of clear signing that have been tried. I will talk a little bit more later about them. The problem is that they are complex to backport. So, if you want to clear sign an existing contract, you could have a proxy, you could redeploy. It's not convenient, and verifying something on chain is hard for hardware signer as well. So, there has been a good overview done by a team doing a hardware wallet on Polkadot and Ethereum. The team is Kalapaya, I think. Not sure about the how you are supposed to say it. The QR code leads to that study.

So, Yes. So, why is this complex for hardware signer in the end? Why do we have a problem? We have a problem because hardware signers are not very powerful, and the biggest problem is that they don't have a lot of RAM. So, top is 110 to 120 kilobytes. If we are considering smart card, usually it's more around 50. They have a limited screen size. So, here, what happens is that if you don't if you don't have an experience which is very clear to the user, you are pretty sure that the user will click yes. I think we have experience with that when dealing with PKI certificates on browser when nobody verifies anything.

And then we have different communication expectation, because the signers are going to be either using USB, BLE, QR, and so on. And I think QR codes are interesting, and air-gapped wallets are interesting, because it's a very good design target. It's a design target where everything is should be embedded in the message, and so this guarantees that you are not going to use third parties, because you have a strong pressure to do it just because you can't do it. So, that's the best way to make sure that you are avoiding something. >> [sighs] >> So, it's not exactly a recent problem.

QR code to a presentation I did in 2017 to talk about hardware wallets and smart contracts. It was at Eth Camp, so even before ETC had a name. And there have been different solutions to try to deal with that in the past. So, we had vendor specific list of ABIs, which is the current situation today. Net spec including this information in the contract, which was not very successful because it gives more work to the developers. Developers are lazy, so they don't do it. We know that. There have been some on-chain descriptors in several EIPs.

All of them are have been pretty much abandoned for the same reason, I think. You could have some application specific passing of the call data in the signer itself, then you need a sandbox. It's complicated, it's proprietary, and so on. You could do call data decoding without the ABI. It's not really easy to read, but it's possible. The QR links to this. And so, how are we going to avoid the famous XKCD 927? So, I have 15 standards. Here is a new standard. It's going to be abandoned like all the other ones. How can we avoid this? So, the architectures that we have today with dealing with hardware signers, it's pretty simple. You have if you consider

that the wallet is designed by the team that did the signer, everything is connected. At some point, you are going to fetch the metadata that you add to the ABI to describe what is the token, what is the transaction, and so on. And you are passing this data to the signer. So, you are connecting to the vendor backend. Everything is in the same domain, so there are not really any issue here. It's proprietary, but as it is proprietary, people can do what they want. I mean, they We live in a free world. Um it gets a little bit more complex if we try to connect the signer to an external wallet because here what happens is that we are going to add We have exactly the same process, so we are going to contaminate somehow um the wallet code with all this

complexity, and in the end, what should be only a signer connects to the backend of the vendor of the signer, which is not really what we wanted in the first place. So, problem we have with this architecture is the signer needs to access remote data to get the metadata to properly sign the transaction. This leads to a security issue, so we had one um MetaMask is well protected against that because it protects uh it locks dependencies very powerfully with something called Lava Mode. Uh Ruby is not doing this. Uh and it leads to a privacy issue because um then you pass the full transaction to your signer signer architecture, and you might only want it to pass it to the wallet.

So, and then of course you have a problem if the signer does not have a remote architecture, if it's an air-gapped project, if it's an air-gapped signer, if it's a DIY project, and so on. And the descriptor format is not standardized. So, those are the problems we are trying to solve. So ideally uh again, still an issue with crops, but we would have a list of people holding the repository of metadata. Ideally, the EF has a neutral party with a lot of industry vendors contributing to this. There would be a standard metadata description for what you want to add to the ABI, to the EIP-712, and this would be transformed for all signers, and all signers could be happy to work with it.

>> [snorts] >> So, this led to uh ERC-7730. Um all the problems that we described are going to be solved in this specification because they have been well identified, and they have been implemented in a way which is easy to support for all signers. So, we don't want code execution, we just want to add simple description of the problem, and well, everything that's really necessary to fix it. Uh the link points to the specification. It's a specification that's in progress, but I suggest you read it.

Um and there are calls to actions. So, for this specification, the first one is that of course you need more descriptors for the widely used contracts. Uh you need to We need to define a a wire format for that, so communication format for all signers so that everything is standardized, and it's easy to integrate in different wallets. I'm working on this. Um we need some feedbacks for how the on-chain registry would be supported, so to avoid crops issue again, and a mechanism to handle the most complex cases because even if we want to avoid programming, sometimes we can't really avoid it. If we have a complex batching logic, for example, with safe multi-send, or if we are dealing with a contract where the call data does some kind of switch based on instruction on

the beginning like the Uniswap router, then it's difficult to solve that without running code in the signer, and this is typically what we want to avoid. One solution to avoid this that we have been prototyping at the Ken Ox is to build a zero-knowledge proof of actually what you want to display. So, the idea is that you will have a circuit that will take the transaction, that will output um that will output the text that should be displayed by the signer, and in the end, you move all the complex logic from the signer to the outside world, and the signer is just verifying a proof in the end. This is called Z Clarity. Um the the proof of concept that we did, and um QR links to it on GitHub.

So, what do we want as features in the universal signer application? We want portability. So, we want to be able to run on any kind of hardware, existing hardware and new hardware. And for that, I think considering air-gapped is a good target because we know that we limit the number of data that should be passed to the um to the wallet, and we will put everything in the same place. We want clear signing, of course. We want to support the emergent privacy needs. So, we want to be able to support the privacy protocols, and we want to do clear signing for the privacy protocols, which is not a feature that signers support today. And basically, we want to design it from scratch with crops in mind.

So, the architecture of the universal signer application is the following. We will have an optional virtual machine, then the core logic that does all the transaction parsing and everything that is necessary to understand the transaction before signing. Uh the display will be specific to the vendor, and we have a hardware abstraction layer for everything that's super specific to the security of the hardware itself. So, key management, cryptography, IOs, uh everything is specific, but basically all the core logic can be reused for all the wallets, so we save a lot of time when porting the application from one wallet to another.

Uh why are you we using a virtual machine? So, it's completely optional. First First thing, uh the main use case for using a virtual machine is if you lack RAM in the host uh in the signer, sorry. So, in that case, the RAM will be shared with the host. Not really um it's not really necessary in my opinion. It's only if you want to be compatible with um with um um low uh lower devices. And lack of application management. Today, there are only two signers doing application management, Ledger and Passport Prime, uh which has been released this week. Congrats.

Uh so, yeah. So, basically, if you want this, and if you don't want to reflash your firmware every time there is a new version of the signer, the virtual machine is useful, otherwise it's not very useful. It's It is inspired from the work done by the Ledger team with Vanadium uh with uh additional hardening against glitch attacks. So, here the QR links to the original version of Vanadium. Uh I will be sending um a a link to the to the hardened one, I mean, on Twitter. Um then we need to standardize a wire a wire format. So, why should we Where should we start? Uh we have CBOR already used today, so CBOR is good. I mean, it's a bit like protocol buffers, it's

CBOR, so it's a good example of a format we can use. It can be suitable for other transports because it's just a binary transport, so we can just add it. And then, how are we going to code the We get to the interesting thing. So, I'm going to use an very extensive use of automatic programming, so specification with a higher-end frontier model, then choosing the implementation uh language later because in the end, when you have a good spec, you don't really care about the language. I mean, models are good to code, so C and Rust. You want a very adversarial testing plan, so you want to have all the security tested here.

Uh mostly, you want to see what happens when people are trying to corrupt the signer, and you want to make sure that the signer is answering correctly. Then you do the code review with different model, and you repeat until you have the right uh until you have a configuration that you like. My personal setup, so we call it boomer setup because it's pretty simple. I'm using Opus 4.6 as a frontier model. I want to use other frontier models to test, and I'm using local models. Uh so, basically, after to generate the code and for the development, I'm using Qwen 3.5 in two version, uh 27 for the dense version to do the specification and test review, and 122 for the development.

Mostly using Claude code, so nothing fancy other than that. And well, an example of what can happen when you use AI to design your application, but it doesn't You forget to add Make no mistake. Uh so, that's why you should always read I mean, what happens when you create something with AI. Um very simple example with 712. So, if you're not familiar with 712, we define structures, and then to know how to encode the structure, we need to take uh different parameters of the transaction and concatenate them together.

So, as a first version, uh Claude gave me this. I hope it's readable. Uh but basically, it was defining the type uh of what is going to be signed in a specific message, and then sending the field. So, here, well, I should have I should have let you some time to guess the problem, but since I don't have time, I will just give you the solution immediately. Uh you have a time of check to time of use problem because in if you define different fields in your structure uh in a different order, then an attacker could corrupt the message.

So, what do you do in that case? You say nicely to Claude, "Okay, there is a talk to vulnerability. Can you please fix it?" And the fix that came out from Claude is to add an additional check when you transfer the fields of the structure and saying, "Okay, you are going to verify that this field has been provided properly before using FNV-1A 32, which is a non-cryptographic hash function apparently popular in Rust." What? So, I I I have no idea I mean, why Claude suggested that, but let's say it's not a very good solution. First, because it's non-cryptographic. Second, because uh it's easy to revert and it's easy to crack. And third, because if you send the message in a different order, then you don't need actually to to do this.

So, then what do you do? You ask to Claude nicely again, "Okay, I like this function, but it's not really what I wanted. So, how could you do it differently?" And since Claude is smart, he will come up with a new uh scheme where you define the field before, then you refer to them, and so you don't need uh to have this kind of weird trick where you verify that you pass them. So, this is the clear This is the correct solution, but I just to say, don't expect the first solution to be the correct one. You still need to read stuff, and you still need to have a human at the wheel.

Even if it's very powerful to design an embedded application. So, thank you. That was a bit short. I don't have my last slide. Uh but I will give more details on the progress of this on Twitter. Uh you can follow me on BTChip. Twitter BT and that's it, I guess. Thank you. >> [applause]