start	end	text
3710	7530	Am I stopping the screen? No.
35730	41890	So we are going to be talking about building a microcontroller Bitcoin address generator.
42550	47570	And what that means is building essentially a homemade hardware wallet,
47570	50970	or at least a homemade hardware wallet with some limited functionality.
54490	57710	So first a little bit about myself.
57710	61990	I'm a full-time software engineer at Microsoft based out of Pittsburgh.
61990	67850	So I am working on backend and system stuff for an Azure storage product.
67850	72410	My day job doesn't have anything to do with Bitcoin or blockchain,
72410	77130	but I run ChainTuts.com and a YouTube channel on the side.
77130	82990	So I like to create content about explaining how cryptocurrency and blockchain systems work,
82990	84810	and what some of the use cases are.
84810	88670	So I put out articles, videos, code projects, and that sort of thing.
88670	95390	And I really focus on teaching the core concepts around blockchain systems and use cases.
95390	101530	I don't really do any investing or money talk, but I do explain why sound money is important.
103490	106250	First, of course, the quick disclaimers.
106250	111450	I am not a cryptography or security expert by profession,
111450	116960	but I am a working software engineer and care a lot about code security and those sorts of things.
116960	122120	Security is a complex and evolving topic, especially in the blockchain space
122120	125980	when it comes to securing our funds and our wallets and those sorts of things.
126080	131520	So this is really a proof of concept project, and I wanted to show that it was possible
131520	138500	and kind of enjoy the process of trying to build an open hardware, open source cryptocurrency tool
138500	141360	that I could use and share with others.
143820	149120	So a little bit of context for the project that I actually built here,
149120	153380	and that is, what's the core of crypto ownership?
153480	159460	So if you've been around in the space, you know that the core of crypto ownership is private keys.
159740	167740	Every Bitcoin wallet or Ethereum wallet or DigiByte wallet starts out with a seed phrase these days,
167740	176900	and that's used to generate private keys, which are 256-bit numbers that are kept totally secret on the client side.
176900	180960	So we never reveal our secret keys with anybody else.
181240	185020	Those private keys are used to generate public keys.
185780	192060	And those public keys are then hashed and encoded and turned into our addresses.
192060	199220	So these are the actual public-facing addresses that we give to somebody else when we want them to send some funds to us.
202570	210090	So private keys are used to prove that we own some amount of Bitcoin funds that we want to spend by using digital signatures.
210450	216830	Anyone with the keys can spend the funds, and so it's absolutely critical when it comes to cryptocurrency
217410	224130	that the keys are both securely generated and securely stored so that nobody else can get at them.
225030	229670	Andreas Antonopoulos likes to say, I've heard him say and I repeat often,
229670	236810	not your keys, not your coins. So that's a really critical concept when it comes to any of these cryptocurrencies.
237790	247930	One of the innovations that has come along in the space because of this security concern is hardware and other forms of offline wallets.
247930	258090	So the commercial solutions like the KeepKey, the Trezor, the Ledger, those are examples of hardware wallets.
258090	265270	And what those are is those are specialized devices that generates cryptocurrency private keys.
265610	273390	They store them and generate them securely offline so they don't have to be done on a network device.
273390	281530	And they will sign transactions presented to them using a very limited protocol for communication between the hardware device
281530	287510	and the PC that you're using to actually broadcast that transaction to the blockchain.
287610	294490	There are also even simpler and earlier solutions like paper, metal, etc. wallets.
294490	302430	So people would generate key pairs using maybe an air-gapped network or air-gapped offline computer
302430	309130	and sent to a non-networked printer to create a paper wallet and store those key pairs
309130	316250	so that they could load up a paper wallet with funds that they wanted to later sweep into an online wallet and spend.
318490	324010	So in general with offline wallets, whether it's a hardware wallet or a paper style wallet,
324010	328630	these keys are generated and stored on a device that's not connected to a network.
328630	335250	So this is fundamentally distinct from the kind of hot wallets like full node wallets, like a Bitcoin Core instance,
335250	339810	or mobile-like clients like you would use on a cell phone.
342090	350310	Now, so the typical solutions for this, building a hardware wallet to keep your keys secure, is a commercial device.
350310	352990	So these are devices that are developed by a company.
352990	356670	For example, I like the KeepKey, which is developed by Shapeshift.
356810	362130	There's the Trezor and the Ledger, and these are devices that are ready-made that you can go out and buy.
362290	366870	Now, almost all of these devices, as far as I'm aware, do have open source firmware
366870	373330	because we often like open source to help mitigate issues of trust and backdoors in the crypto space.
373570	379510	But I kept thinking to myself, why couldn't I build one of these myself on some cheap hardware?
379510	390290	And thus, my project, MicroBitAdder, was born out of lots of tinkering, experimentation, and perhaps getting on my wife's nerves.
392740	402400	So I thought it would be really interesting to generate real offline key pairs for cryptocurrencies using my own code that I developed myself.
402400	412200	I had some basic experience with microcontrollers from another project that I built and presented at the Blockchain Training Conference last year,
412200	420260	actually where I met Ron Stoner, and this was a proof-of-work simulator on a little circuit playground device.
422320	430560	So I'm not an embedded engineer by any means, but I had some experience working with these little devices and just found them to be really fascinating.
430560	439880	And I wanted to see if I could build something like this, a tool for generating key pairs, on readily available, fairly straightforward-to-code products.
441160	445220	There's a couple major challenges with this idea, though.
445560	455560	First, I needed a platform with enough memory and computing power to store and run code to do these cryptographic computations.
455560	465640	The M0 platform, which is that little circuit playground device that I showed in the last slide, was way too insufficient for being able to do SHA and ECDSA
466100	471720	and store all of that code on the flash memory available on that device.
472820	476720	The next major concern was cryptographic primitives.
476720	483980	So to do Bitcoin address computation, I needed SHA-256, REG-MD-160.
483980	488180	In order to support Ethereum, I needed KEKAC SHA-3.
488180	494880	And I needed the appropriate elliptic curve algorithm used for the public key cryptography.
495240	501740	And the final very important requirement is it has to have a cryptographically secure random number generator.
501740	507420	So I have to have some way to get true randomness, not pseudo-randomness, to generate keys.
508780	515900	So how did I work through these particular challenges in picking a simple hardware platform?
515900	521380	For the memory and power needs, I decided on the Adafruit M4 platforms.
521380	527560	So they have several different devices, such as the Itsy Bitsy M4 and the Grand Central M4,
527560	532580	which are the ones that I use to develop and test this particular project.
532580	536320	It runs on an Atmel SAMD-51 processor.
537080	545660	Across the devices, both have at least 256 kilobytes of flash memory and 192 kilobytes or greater of RAM.
545660	552660	So they had plenty of juice to load some cryptographic code and be able to do these computations quickly.
555570	558210	Now, how do I get cryptographic primitives?
558270	563310	I think most of us in this space know kind of the number one rule is don't roll your own crypto.
563310	569810	I'm definitely not a cryptographer and don't have quite the math knowledge to implement my own crypto.
569810	578470	So I needed to get trusted, secure crypto primitives that would run on these little platforms that don't have an operating system.
580230	589050	Standalone Python libraries are fairly hard to find and run on the microcontroller platform due to the space concerns.
589490	599350	On the other hand, what I stumbled on is that the Trezor commercial hardware wallet firmware is open source and very standalone C code.
599350	606550	Most of these individual modules that I needed to run to get this project to work were standalone and didn't tie in other C libraries.
606870	615390	And so what I did was I ended up porting some of Trezor's open source code that was license compatible with what I wanted to release as.
615410	619830	And I'll go into a little more detail on how I did that later on.
623750	630390	Now, the final very important concern was the need for true cryptographically secure random number generation.
630390	633950	And luckily, the platform choice fixed this for me.
633950	642050	The M4 microcontrollers that I used, the entire family of them from Adafruit, come built in with a true random number generator.
642150	651730	If this was a limitation, but the platform was suitable otherwise, there are other options for getting some cryptographically suitable randomness.
651730	659210	I could have done something like use an accelerometer or other device to get the appropriate amount of environmental noise.
659210	663910	But having this built in made life a little bit easier.
667290	673530	So putting it all together, how did I build this standalone address generator project?
673530	679350	The stack starts on the bottom with a custom CircuitPython module written in C.
679350	682750	So I am actually mostly a Python developer.
682750	689690	I do have C and C++ knowledge, but I do a lot of my work at my day job.
689690	696190	And a lot of the stuff I do for chain tutorials in Python because of the ease of development and comfort that I have with it.
696210	703870	It's a very powerful and robust language, even if it's not necessarily powerful in the sense of getting the most speed out of it.
703990	712090	So I wanted to build the application layer for this in CircuitPython, which is designed specifically for these small devices.
712090	721370	And I found that it was possible to extend CircuitPython to build a custom C module where I would do all of the cryptography work.
721450	726590	The device itself is one of these M4 family devices from Adafruit.
726590	734830	So the Grand Central or the Itsy Bitsy with an I2C character LCD screen or a receipt printer hooked up to it.
734830	747590	And ultimately, at the time of doing this presentation, I support Bitcoin, Bitcoin Cash with CashAdder, Ethereum, Litecoin, and Digibyte addresses that you can generate with this.
749190	758470	This was, I think, the most interesting and fun part of this project was building a custom CircuitPython module.
758470	766650	I followed a tutorial called Extending CircuitPython by Dave Astels that's available on the Adafruit Learn website.
766930	774170	And so I went through that tutorial and just learned the basics of creating a custom module for the CircuitPython build.
774270	778700	This is where all the cryptography happens, thanks to the Trezor code.
778700	792820	So I get a true random number generator seed passed in from the Python layer because it's easy to use os.urandom to get your seed from CircuitPython directly.
793820	803540	I then hash that seed into a private key, generate the associated public key, and return an encoded key pair from this layer.
803540	815500	So this is using chain-appropriate address encoding. It's base58 addresses for Bitcoin, Litecoin, and Digibytes, CashAdder for Bitcoin Cash, and of course hexadecimal for Ethereum.
815760	824280	And as well, this custom module function returns the with or hex-encoded private key, depending on the chain as well.
826750	831810	So this, of course, required actually building the custom CircuitPython module.
831810	841210	I had to run the makefile that's provided by the CircuitPython code, make sure all the files were in the appropriate places.
841210	850750	And this ultimately gives you a UF2 firmware that you can drag onto your microcontroller device and it will reboot with that new firmware.
850750	856070	So since I was actually essentially building the platform that the device runs on from scratch,
856070	864150	it required a little bit more work than the basic sort of CircuitPython functionality where you just have to edit a Python file.
864150	870070	This required me getting down into the firmware layer a little bit. It definitely presented some challenges,
870070	876430	but luckily the folks over at Adafruit and the folks that work on CircuitPython are really helpful about getting you up and running
876430	880850	if you talk to them on GitHub or somewhere else and have questions.
881910	888810	I personally found, for whatever it's worth, that I was able to get this build running most easily on Linux.
888850	897510	It is possible to build CircuitPython on Windows and Mac, I do believe, but I just worked on Ubuntu when I was working on the core of this project.
900070	908810	Now within this custom CircuitPython module, since all of the Trezor cryptoprimitive code are pretty standalone,
908810	914290	it also made it possible to do testing for this on a command line interface.
914290	922330	So every time I wanted to go in and work on some of the important cryptography stuff and make sure that I was getting correct addresses and correct encoding,
922330	929590	I didn't have to worry about rebooting the firmware, reloading the firmware, making sure my LCD screen was hooked up correctly,
929590	935890	and all of those little challenges that you run into when you're developing on hardware devices.
936170	945830	So for example, on this slide here is an example of just running a test driver to generate a new Digibyte address right on the command line with a private key.
945830	955210	Since everyone at DEF CON gets to see this key pair, I would say don't take that and send any of your precious Digibyte to it, but I think you all know that.
957590	967330	Now for the CircuitPython layer, all this layer does is it's kind of the application layer that's built on top of the lower level crypto stuff, which is done in C.
967330	978790	This generates the entropy, so I'm using Python's os.urandom function, which is tied right into the CSRNG built into the platform.
978790	993210	I call that custom module code, the function call takes that randomness seed as an argument, and I get a tuple back, so I get the private key and the address back already encoded in the correct format.
993210	1004250	And then this code uses the appropriate libraries to display that final address and private key on an LCD screen.
1004610	1013610	I also tested as well with a receipt printer, which I thought was kind of fun. You know, it's not the most robust way to store your cryptographic key data long-term,
1013610	1021210	but I could press a button to generate a new Bitcoin address and have it printed right out for me, and I just thought that was pretty cool.
1021210	1031510	But I primarily tested with an LCD screen, which simply rotates between displaying the address and the private key about every 30 seconds or so.
1033970	1041150	All you have to do here, and one of the reasons I picked CircuitPython even for an embedded microcontroller project,
1041150	1051350	is with CircuitPython, when you connect the device to your development PC, you'll simply see a drive called CircuitPy mount to that computer,
1051350	1057610	and you simply edit the main code.py file, and this is where all of that application layer code went.
1058010	1063870	And when you restart the device, it will automatically run that code.py file.
1066030	1073730	In this iteration of this project, the usage is really straightforward and simple then, and comes with some pitfalls that I'll talk about next,
1073730	1080470	but each reset of the device will just generate you a new, completely random key pair that you can copy down.
1082350	1087830	So this is what the final project looks like wired up in a couple different ways,
1087830	1094970	generating Bitcoin addresses with a little itsy-bitsy on the screen with the larger Grand Central,
1094970	1100350	and also showing it generating key pairs and printing to a receipt printer.
1105420	1109520	So this was a really interesting project, I had a lot of fun building it,
1109520	1117260	and I was really, really pleased with the results and the fact that I was able to get a real working Bitcoin address generator running.
1117380	1122240	That said, there's a lot of potential pitfalls when you're working with cryptography,
1122240	1126440	and I wanted to talk about some of those issues as part of this talk,
1126440	1132640	because I don't want everybody to think that this is something that you can just take and run with, that it's guaranteed to be secure.
1132640	1140360	And more so, what are some of the things that you can run into if you're choosing to tinker with a project like this on your own?
1140780	1146600	The first and perhaps most obvious pitfalls are cryptography foot guns.
1146600	1152260	Again, I'm not a crypto expert, and there's always hidden dangers with implementations.
1152520	1157260	I tried to mitigate those as much as possible by using trusted primitives,
1157260	1165580	so I used libraries for the Trezor hardware device, which is a very, very popular crypto hardware wallet.
1165700	1169660	The Trezor team works really hard to take in bug reports.
1169820	1173980	I'm sure has people that are cryptography experts working on the code,
1173980	1183000	and I felt fairly confident using these and was able to, I think, go forward assuming that SHA-256 was going to work correctly if I use their code.
1183000	1191300	I also kept things simple. For this at least first round of this project, all it does is generate a key pair.
1191300	1199940	It generates a random private key and then walks through the steps to get a pub key and finally an encoded usable address.
1199940	1209640	I don't have any extended support for many of the features that we've come to enjoy, like HD wallets and those sorts of things, and I'll get to that in a bit as well.
1209640	1216920	And then finally, tested, tested, tested manually against no working implementations of key generators.
1217060	1224820	So I would use some different places where I would use my device to generate completely throwaway private keys.
1224820	1231520	I would plug that into a paper wallet tool, for example, and make sure that I kept getting the correct public address.
1231520	1241540	Because the last thing that I would want to do is send funds to an address and have it turn out that the address was wrong based on the private key and then lose those funds forever.
1244440	1257220	A major pitfall that many of you may have been thinking of while listening to this right now is that single key pairs are simply way out of favor and considered a legacy way of dealing with private key data.
1257220	1267960	You have to make sure that if you're generating a single key pair for fund storage, that you copy it correctly and double, triple check before you send any funds to it.
1268000	1276560	Because Base58, like is used in Bitcoin addresses and in the WIF private key format, is not the most human friendly format.
1276560	1284280	It's a little bit more compact than HEX, but it's also super easy to screw up. Was that a capital or a lowercase w that I wanted?
1284280	1289560	And that was something that I ran into when I was actually testing this stuff with some live funds.
1289660	1294120	The encoding is just not human friendly and it is easily corrupted.
1294180	1302320	Bad handwriting, character distinctions like lowercase, uppercase, potential for water damage if you're on paper.
1302320	1307620	These are all huge problems for long term key storage that are important to consider.
1307620	1312800	And as is, the code that I generated only shows this key pair once.
1312800	1316300	So you had to be really careful to copy down everything.
1316300	1324120	And then if you were going to reset the device, you had no way of verifying the key pair you copied down was correct again.
1325440	1330460	So let's talk about the fun stuff, which is potential future improvements.
1330460	1338640	How can we make a project like this that's a tinkerer's homemade offline wallet better, safer, more secure?
1338880	1354840	I think the first and best thing that I could have done to make this better and would like to consider as I maybe iterate on this project in the future is upgrade to BIP39, BIP44 compatible seed phrases instead of single key pairs.
1354840	1366980	So instead of directly generating a private key from the true random number generator, generate a seed phrase and encode it as a mnemonic using the BIP39 standard.
1367340	1374200	This is much, much, much better for reasons that a lot of us in the crypto space are fairly familiar with.
1374200	1386040	You have a backup that's much more human readable, a backup that is much easier to fix if you do get a little bit of water damage or something like that or dealing with bad handwriting.
1386040	1395640	It's much easier to figure out what an English word might be if a character or two is off than in a string of seemingly random information like a WIF encoded private key.
1395640	1415120	We could then generate new addresses as needed or even if we wanted to keep it simple and just grab the first address from the tree, this is still a much safer and easier backup solution even for a single address usage of this type of device.
1416980	1423880	Now, I will say, of course, again, another thing that's fallen out of favor is address reuse in general for privacy concerns.
1423880	1433500	So, you know, it would be best if we're using a BIP44 standard in an implementation of this in the future that it would allow you to generate new addresses from the given seed.
1433600	1441920	But as well, even if it was just used to generate the first key pair, if you have a mnemonic backup, it's going to be much safer for the users.
1443260	1446440	Several UI UX improvements that could be made.
1446920	1451080	Warnings about some of the things that I talked about, like, hey, don't lose this.
1451080	1455900	Make sure that your seed or make sure that your key is copied down correctly.
1456460	1460720	Maybe, in fact, it should actually store the key pairs for a while.
1460720	1480440	Since it's designed to be a standalone offline, never connected to a network device, it could be feasible that you would want to keep maybe an encrypted copy of the seed phrase on there or a list of the generated key pairs on there in case the user screws up and wants to go back and make sure they copied something correctly.
1482420	1489060	This was built on CircuitPython 4, which has now been superseded by CircuitPython 5.
1489060	1496980	So, it would, of course, be wise to upgrade my custom module, custom firmware to the latest builds for supportability.
1497020	1503180	Downside, the build process was tricky. It was probably the hardest part of getting this up and running.
1503920	1507160	Question, could be a potential improvement.
1507360	1511060	Is this device powerful enough for a pure Python implementation?
1511060	1525960	I originally got the idea of doing the lower-level cryptography in C and then having a CircuitPython application layer because I was dealing with the particularly limited devices I was trying to do this on first before I moved to the M4 platform.
1525960	1537700	I haven't really tested out whether or not the M4 is powerful enough to load pure Python implementations of the cryptography and therefore have a pure Python project.
1537700	1546380	I would like to do that for easier development and less complexity for both myself and potential users of a project like this.
1546380	1555520	The downside is, of course, with anything cryptography, making sure that the crypto primitive libraries that I'm using are up to snuff in terms of their security.
1555640	1565500	And as far as I understand it, there can be some more concerns with doing crypto in a Python environment versus a C environment with side channels and those sorts of things.
1566540	1579660	I would love to consider doing more unit testing. It's always a good idea to catch basic cases and edge cases through a unit test instead of manual testing.
1579660	1587560	So anytime I make some kind of change to the code, I can have test cases that would check and make sure that key pairs are being generated correctly.
1587560	1605980	A lot of the Bitcoin BIPs that are involved with these sort of wallet generation actions do have some test vectors that I could put into a unit test to make sure that I'm not missing strange edge cases.
1606360	1613020	And I'm just open to ideas. I build projects like this outside of work just as something that I enjoy.
1613020	1618000	I like to tinker. I like to learn about Bitcoin and crypto tech and then teach other people about it.
1618000	1626480	So I'm always looking for ideas and perhaps something new will pop into my head tomorrow about how I could work on a project like this and make it better.
1629180	1635140	And that's all I had for the main presentation. I would love to take any questions you all have.
1645820	1658600	If I'm not mistaken, I do believe that the Grand Central M4, which is one of the devices that I worked on, it might have some kind of keystore capability, but I can't say for sure on that.
1661500	1669280	Yeah, that definitely would be nice and that would be something to investigate as well as part of potential future improvements and tinkering with the idea.
1671750	1684810	I think at the very least, if I could get it to generate a seed phrase instead of just a raw, you know, with an address key pair, it would certainly make backup safer, even if it doesn't store them on the device.
1684810	1691270	Because that way, at the very least, you can make sure that you're writing it down correctly and backing it up.
1691270	1699970	And it's obviously not a full hardware wallet implementation. It doesn't sign transactions or offer, you know, modern trees of addresses.
1699970	1713390	It was kind of a proof of concept for the initial idea of can I generate a basic crypto wallet with a little microcontroller, like something that's simpler even than a Raspberry Pi.
1713390	1717130	And I'm glad I tinkered with it and it worked out.
