I just released a proof-of-concept Ricochet echobot running on Android. While the “final product” code is not much, when I actually outlined the work I put in over the last 10 months to get here, it seemed worth a brief write up.
When I started I had never done Android development, I knew nothing about how Tor hidden services worked, especially programatically setting one up, and I knew nothing of the Ricochet protocol. What I had was a go based implementation of the Ricochet protocol (go-ricochet from Sarah), the knowledge that a Go to Java/Android binder tool of some sort in some state of experimentality existed (go mobile) and the knowledge that Orbot, a Tor client for Android existed and you could browser Tor websites with it. So the idea I had was that it might be possible to cobble these all slightly to extremely experimental tools together to build a Android Ricochet client.
My goal when I set out was always to prove that this was possible, and once there, build on it. To start with I checked out the gomobile tools and started running through their basic examples and running them on go-ricochet. I then setup Android Studio, learned how to use QubesOS’s qvm-usb tool and sys-usb VM to assign phones to VMs so I could build and run apps from Android Studio onto my phone (the VM phone deployment not looking so promising from within a Qubes VM already). Once I had these going I started working on simple gomobile imports into Java, the basic get a string from go code and set it as a label in an Android app. I had to learn all about how Android does it’s GUIs via activities and building them and accessing them.
It was here I ran into my first major hurdle and dereailment: I discovered after a lot of errors and reading, that somewhere between gomobile and Java any go method or package with a ‘-‘ in it is not going to import properly and be accessible. I dug somewhat deep into this, joining the issue with additional comments and debug and tracing info. I helped identify the problem area, and I even took a poke at reading the code and seeing if there was a simple fix I could do. There was not, so after some time I abandoned that path as it wasn’t a critical path to the proof of concept and I just accepted I’d be writing a wrapper go library that used Java style camelCase for everything.
After this I ran into a knot of a few problems. I was now calling the go-ricochet code fairly well, so I started proceeding. Not sure exactly how Tor Hidden services worked or their setup, but following the go-ricochet code first, I saw I needed keys so I worked on calling go code to generate those. This first diverted me into next learning how Android / Java did multi tasking and creating backgroundActivities to manage the “long running” key generation process without crashing the app. Once here I ran into the problem of lack of ahead of time research and reading when I found I had no idea how to setup a Tor HS in Orbot. I found I could create one through Orbot’s in app menus, but then I found as I belatedly started reading the Ricochet protocol, that the HS key and the Ricochet key were supposed to be one in the same.
I had a few paths I thought I could pursue, and I started with trying to get the HS key from Orbot. This was a quick dead end, but it got me to search for more info on the Tor Control port/socket and I found old bugs from Ricochet’s creator requesting programatic HS features and eventually getting them in the form of the ADD_ONION command, so that Ricochet could generate a protocol key and create a HS based on it.
Around this time I discovered that there had also been some recent work in gomobile on reverse bindings for Java, so that one could create an entirely go based native Android app. I spent a good chunk of time researching into this, creating a new test app, but quickly running into many problems as it was incredibly experimental. I did find and fix one bug in the gomobile toolchain while working on this, a simple “parent envs not populating child process envs properly” kind of bug. I submitted a pull request and got it accepted: 46671: cmd/gobind: add GOROOT to cmd.Env from ctx.GOROOT. I eventually got feed back on the golang-nuts mailing list from the author of this feature, Elias, that this feature was far too experimental for what I wanted, so I closed down this line of research and went back to the standard model of Java app calling go packages and functions.
Over the course of this time I also learned about writing to files and storing preferences in Android. I also made a few simple contributions to go-ricochet in the form of loading keys from function arguments, and later extending the calls to bulb to create a Tor HS to take ipv4/socket as an argument. Also not having a formal introduction to Android dev, I had problems once I started opening ports making or receiving any connection and it took me a bit of time to “stumble” onto the fact I needed to be requesting INTERNET permissions in Android.
There were other toolchain hicups, especially during upgrades. gomobile and gradle > 2.2.3 do not mix, and it took a while to trace that down as the source of weird errors and downgrade. Sometimes gradle would just ‘lose’ the ability to push apks to my phone, but Qubes had my back here because I could just reboot my work VM easily.
Finally though after reading the Tor control port documentation I looked into the Orbot configs and found Orbot by default listens on a random port and needs an auth cookie. I found the required config file parameters to make it listen on a fixed port and not need cookie auth. Not finding app/settings for it, I manually put them into the free form config section Orbot thoughtfully provides.
In the early summer the go-ricochet code was rewritten and upgraded to include bulb a go interface to tor control port. I ported my meager wrapper to use this.
With everything in place I went back to my code and got the go-ricochet code to connect to the Orbot control port and successfully register a Hidden Service with a key the go code had generated. It worked but then listening failed because I was doing it in a main activity thread in Java/Android and being a “long running” task it was being killed by a task manager. I again put it into a background activity and finally it was able to listen. I invoked the go-ricochet example Echobot and ran it on my phone and it worked! I was able to connect to it from the desktop client and send messages and get responses!
Now I have a proof of concept that Ricochet can work on Android. Now however the real work begins :)
Future plans include building out a device remote control over Ricochet, a full mobile IM client, and possibly working to create patches to Orbot to make the configurations this needs/will need easier.
goRicochetMobile: The simple go code wrapping of go-ricochet
AndroidOD: A Java app that activates a Tor Hidden Service with Orbot and invokes an echobot. Eventually a full fledged Ricochet using device remote control is planned to be built out from here.