Peter Cai

A random guy on the interwebs. Graduate student. Free software enthusiast. Posts may be in English (US), Chinese (Simplified) or Japanese.

pass-gocrypt: Yet Another Metadata Encryption Extension for Pass

I have switched to pass, the password manager that conforms to the Unix philosophy, since a few months ago. It stores passwords as a bunch of .gpg files laid out in a file system directory, optionally being a git repository, and provides a bunch of shorthand commands for password generation and management. Compared to other fancy password managers with intricate UI / UX, pass feels very refreshing due to its simplicity and portability. You can use it basically anywhere where you have coreutil commands and gpg -- and even on platforms without standard UNIX tools, it is pretty straightforward to create a platform-specific UI for it, such as the Password Store app on Android.

There is one big issue with pass, however, and that is metadata leakage. Because of its use of simple Unix directories and files, even though your passwords themselves are encrypted, metadata such as sites and apps you use is leaked in plaintext as the file and directory names. Depending on the specific directory structure you adopt, it could also leak the account IDs that you use on each service. This may or may not be a problem -- for most services, your online presence there is probably already public knowledge. This applies to email, social networks, Git hosting, forums, and pretty much everything with user-generated content. But there is a substantial subset of services, at least for me, where my presence is not and shall not be public knowledge. For example, the exact hostnames of my personal servers, the services I host on them and my credentials for those services should preferably be kept private.

Another issue with pass is the use of asymmetric cryptography only -- it is convenient when the asymmetric key can be stored on a hardware token like YubiKey, and to be frank, it may be more secure than a symmetric passphrase (when the private key is stored on a hardware token only). However, no asymmetric cryptography in use today is quantum-resistant, and depending on your exact threat model, this could be an issue. It is certainly not an issue for me at this point, but I would not mind if the password store can be protected by another layer of symmetric cryptography, just in case generic quantum computing becomes a reality way faster than anybody thinks it would -- although it does not seem to be likely anytime soon.

Existing Solutions

Now, of course, since pass has existed for more than just a few days, and the fact that pass, being just a shell script, is very extensible, there have been a lot of solutions to these issues:

  • pass-tomb, which stores the entire .password-store directory inside a Tomb, a wrapper script built upon LUKS. This, however, requires root permissions, since the use of device mapper is limited to the superuser. The use of DM also limits its potential usage to Linux only, with little to no hope for cross-platform compatibility (unless someone digs into the undocumented internals of DM and re-implements everything bug-for-bug on another platform).
  • pass-grave, storing the entire password store inside a .tar.gz file encrypted with GPG. This does not require root privileges like Tomb does, and tar is a portable format, unlike LUKS. However, this does mean that every time we need to decrypt the password store, all files must be extracted from the tar and physically written to the underlying filesystem, and vice-versa when closing the password store. Not only is this not very elegant, it also creates a potential leakage if the underlying filesystem does not truly erase deleted data (which is the case for most filesystems).
  • pass-coffin, another extension very similar to pass-grave. It also puts the entire password store inside a tarball wrapped within a layer of GPG encryption. As far as I can tell, pass-coffin is essentially the same as pass-grave, with the only difference being the exposed command line interface. It also aims for better code quality than other extensions, but this is beyond the scope here.

As you may see, all of these have at least one deal-breaker for me, be it the dependence on root privileges and LUKS, or the fact that every open / close operation generates a huge bunch of actual filesystem I/O that may even leak the metadata we are trying to protect in the first place. That is not even considering at least three common issues of these solutions:

  • They break pass git functionalities. Although all three of the solutions mentioned above do still technically allow the usage of pass git, it only works with the decrypted form of the password store. Even though some of the authors (such as the author of pass-coffin) urge users to back up their password stores using git, the repository that is pushed to a remote is decrypted, in its original form, defeating what I see as one of the main goals of adding another layer of metadata encryption. I am personally more worried about a remote git repository leaking metadata of my password store than an unencrypted directory on my disk would do.
  • They still fully rely on the security of GPG only. As mentioned earlier, this may or may not be an issue for you, but I would not mind if there was an option to add a standalone symmetric passphrase to the encrypted password store, such that accessing it requires both the gpg private key and the symmetric passphrase.
  • They operate under a "all-or-nothing" model. Because none of the solutions work on mobile platforms like Android as of now (also partly due to the reliance on LUKS in the pass-tomb case), it means that metadata encryption and mobile support is mutually exclusive. Ideally, the user should be able to choose which entries to encrypt under the metadata encryption scheme, while leaving the rest as-is -- as mentioned before, you probably do not need all of the entries to be hidden behind metadata encryption. These entries without metadata encryption would be accessible on all platforms and devices. This, combined with the extra symmetric passphrase, also allows one to set up an effective "trust hierarchy" within one single password store, where devices holding the repository would not necessarily be able to read the metadata of the full password store -- at least without the extra passphrase.

Design Goals

I love the simplicity of pass, but I also love to not have to worry about metadata leakage. Since none of the existing solutions really meet my needs, I set out to design and implement one myself, just like how most OSS projects are created. Specifically, I want something that:

  • Provides a reasonable level of metadata encryption within a single password store, such that it would play nicely with scripts and browser plugins based on pass
  • Must play nicely with pass git, i.e. content after encryption must be possible to synchronize using Git just like without metadata encryption
  • Must be able to encrypt only a user-selected subset of entries
  • Must not generate an excess of filesystem I/O during normal operation
  • Must support adding a symmetric passphrase for extra protection

But, as I am far from a cryptographer or security engineer, I would not trust myself to roll a encryption scheme like this. That would be essentially equivalent to (or even harder than) inventing a full password manager all over again. Instead, just like what the author of pass-tomb did, I started searching around for something that I can build upon to implement these features.


Enter gocryptfs. Unlike LUKS, used by Tomb, gocryptfs is a userspace implementation of file-based encryption. It operates on a directory tree with a bunch of sub-directories and files, instead of on fixed-size block devices like LUKS does. Being implemented on top of FUSE, it also eliminates the need for root privileges, at least when unprivileged FUSE is allowed.

The nice thing about gocryptfs is that you can use it to set up an encrypted subtree anywhere on the filesystem, and of course this includes inside a pass password store. With the passphrase, an unprivileged FUSE mount would immediately provide a decrypted view into the encrypted subtree, without any actual I/O (other than gocryptfs metadata reads) being done. This is immediately way better than Tomb, and a LOT better than the very, very excessive I/O that pass-coffin and pass-grave do to the password store.

Because gocryptfs operates on files, not blocks on a block device, it would play very nicely with git by simply setting up the encrypted subtree somewhere inside the original pass repository. Of course, git will not be able to track changes inside encrypted files as diffs, but it could not do so to begin with inside a pass tree, so this is not really a disadvantage. gocryptfs itself works on Linux and macOS using libfuse, while a port to Windows also exists as cppcryptfs thanks to the simple and documented encryption scheme designed by the authors of gocryptfs. Even an Android port for gocryptfs exists as DroidFS, although it is not clear at this point how one could integrate this with the Password Store app.

gocryptfs relies on proven symmetric cryptography only. For our purposes, we could easily store the symmetric key inside a GPG-encrypted file for seamless operation with the rest of pass, or we can also add another passphrase to use along with the GPG encrypted one for extra protection. To put it simply, gocryptfs seems like the perfect choice to implement metadata encryption for pass.

Integration with Pass

I then set out to write an extension for pass, pass-gocrypt, that integrates gocryptfs with pass with a convenient command-line interface.

As both pass itself and its extensions are just shell scripts, pass-gocrypt is also pretty simple to implement. What I needed to do is basically a command to initialize the subtree encrypted by gocryptfs, a command to mount (open) it and another command to close it and return to an encrypted state. A few more shorthand commands would be nice, but these three are more than enough.

The gocryptfs subtree will always be located inside the .gocrypt subdirectory in the password store, and the decrypted version will be mounted at gocrypt (without the leading dot), also directly inside the directory of the password store. To initialize the .gocrypt directory, the extension simply invokes the existing pass generate command (albeit internally) to produce a random password, with a length of 32, named gocrypt-passwd inside the store. This password, optionally concatenated with another user-provided static passphrase, will be passed along to gocryptfs as the symmetric password for encryption.

Originally, I was to use some sort of key derivation to combine the user-provided passphrase with the randomly generated password protected by GPG. However, it was a pain to use any sort of proper KDF in bash, and I was reluctant to depend on Perl or Python for that. In addition, I realized that gocryptfs already uses scrypt (a type of KDF) internally before using the passphrase as any sort of encryption key, so a simple concatenation outside of gocryptfs should already be enough. As there is no real limit on the input length of scrypt, the concatenated password should already have all the properties we need.

After creating the gocrypt subtree with pass gocrypt init, you can then simply mount the encrypted subtree with pass gocrypt open, and after a while, unmount it with pass gocrypt close. This style of command line interface closely mimics those provided by pass-tomb and pass-coffin, and should be pretty straightforward to most users. When an extra symmetric passphrase is needed, the user will be prompted when running pass gocrypt open.

When the encrypted subtree is opened, all entries will appear under the gocrypt/ subdirectory inside the password store. This makes it compatible to all tools expecting the standard pass store format, albeit with a gocrypt/ prefix. All pass commands will work transparently inside the gocrypt/ prefix. However, for convenience, and for git compatibility (as will be mentioned later), you can (and should) operate inside the subtree using pass gocrypt <pass-command>. For example, instead of pass edit gocrypt/My/Password, you can use pass gocrypt edit My/Password. Notice how the second command does not include the gocrypt/ prefix, but has to be invoked under the gocrypt subcommand. All known pass commands have an equivalent one under the gocrypt subcommand, which will operate inside the subtree encrypted by gocrypt only.

git compatibility is a little bit tricky still, unfortunately. Don't get me wrong, git itself works perfectly fine with the encrypted subtree. The problem is that when you use the pass commands to generate or edit passwords, a corresponding git commit will be generated with the name of the file in its description (and, the generated commit may not have the correct files staged inside the encrypted directory). This defeats the purpose of implementing metadata encryption. As there is no way for pass extensions to hook into the generation of commits, the only way to work around this is to require the use of the wrapper commands (as mentioned earlier, the pass gocrypt <pass-command> family). These commands suppress the generation of the default commits, and instead creates git commits on their own with a generic commit message.

As an added bonus, these wrapper commands also enable nested repositories for us -- the encrypted subtree itself can be its own standalone git repository! By simply running pass gocrypt git init, you can create an entirely separate git repository just for the encrypted subtree. This repository would not need to be pushed / synchronized on its own, because all of its state (.git) will be automatically included in the outer repository in the encrypted form. Doing so allows the history of the subtree to be tracked separately inside the encrypted directory, without leaking it to the history of the outer repository. After a nested repository is created, all pass gocrypt <pass-command> commands will generate two git commits: one inner commit that includes the detailed file names and changes, stored in the encrypted subdirectory; and another one generic outer commit that includes all the changes inside the encrypted subtree, along with its corresponding (encrypted) .git history changes.

By this point, all of the features I needed (as laid out earlier) have been implemented. The rest is just a few quality-of-life improvements, such as the ability to close itself after a given timeout using systemd-run, and a shorthand to move passwords between the encrypted / unencrypted subtrees. Please refer to the git repository for the latest list of features.

Using pass-gocrypt

To install pass-gocrypt, you simply need to copy gocrypt.bash to the correct path. This can be the .extensions subdirectory in your password store, or one of the supported system-wide extension paths. Please refer to the documentation of pass for details.

Here is a sequence of commands that demonstrate the usage of pass-gocrypt. What is laid out below is basically an excerpt from the project README.

To initialize:

pass gocrypt init
# With extra passphrase:
# pass gocrypt init -p

To generate a password inside the encrypted subdirectory:

pass gocrypt generate "My/Password"

To view a password from inside the encrypted subdirectory:

pass gocrypt show "My/Password"
# or simply: pass show "gocrypt/My/Password"
# or from any other pass-compatible GUI, when the subdirectory is opened

To move a password from outside of the encrypted subdirectory to inside:

pass gocrypt crypt "My/Insecure Password"

To close (unmount) the encrypted subdirectory:

pass gocrypt close

To re-open (mount) the encrypted subdirectory:

pass gocrypt open

To make the encrypted subtree a git repository of its own:

pass gocrypt git init


pass-gocrypt is a simple yet powerful tool to improve the security of pass, the standard password store for Unix. Although it is currently only tested on Linux, it should work with minimal changes on macOS and Windows (patches welcome). As gocryptfs is available on Android, it should be possible to extend Android Password Store with pass-gocrypt support, too, although this has not yet been done. Nevertheless, since we only rely on proven and documented cryptography, I expect it to be pretty straightforward to port and extend on any platform -- just like the original pass tool.

Being towards Death

When I was a kid, there was a phase where I was extremely afraid of, I kid you not, sleeping. I am not sure how common this is among children, but for me it is a somewhat embarrassing piece of memory. The reasons for my fear of sleeping are a little bit complicated, but one of the major causes is the fear of "not waking up", or sometimes, "not waking up as the same person". To me, it seemed like participating in a Russian roulette game every time I fell asleep: how would I even know whether I, this exact "me", am going to wake up again a few hours later? The loss of consciousness when sleeping seemed to be exactly the same as dying, save for dreams, and the fact that we generally do actually wake up the next morning. For one thing, one could simply just die in a sleep and not even knowing anything. That, for some reason, probably of little rationality, sounded very feasible to the past me, especially after learning about my great-grandma's passing in this exact manner. But beyond that, how would I even know that the person waking up in my body the next morning is the same person as when I fell asleep the night before? It could very well be the case that this consciousness experience that I call "me" is actually different every single day. In that sense, I am only a being who lives for as long as the day lasts, and when I go to bed, that is the end of this current incarnation of "me".

For quite a long time, actually, I had a bit of insomnia for this exact reason. I would lie on my bed, pondering about all of this, and eventually pondering about very generic philosophical topics like life and death, only falling asleep when I cannot keep myself awake anymore. A kid worrying about all of this might seem cute and funny to adults, but I genuinely had a lot of deep thoughts during these sleepless nights. Well, at least they were deep to a kid that I was -- and I am sure they would be somewhat laughable if I said it out loud today. As time went on, the fear of sleeping slowly faded away, but that was not due to some sort of revelation as a result of my pondering. Rather, it was because of me learning how to suppress my inner fear of death -- something I think we all do as we grow up. After all, not sleeping well every single night sounds like a quicker way to die early, in a rational sense. Or shall I say, the practical and rational side of me eventually won against the somewhat emotional, fearful and irrational side of me.

But were those fears so irrational after all? The same thoughts still come back to me sporadically even after my adulthood, despite the fact that I try to suppress them as hard as I could. Of course, I eventually concluded that talking about whether the consciousness that wakes up every day is the same person is meaningless, because there seems to be no physical way to define one specific consciousness without relying solely on memories and experiences. However, this does not really rule out the fear that I, in the sense of a mental experience, would not be the same the next time I wake up. It could very well be the case that there is simply no consistent way of tracking one single stream of conscious experience through time, that my experience in every single unit of Plank time is different from that in the previous one. The illusion of a consistent "me" only exists as a result of the continuous transition from one Plank time slice to the next. The act of sleeping, or anything that involves the loss of consciousness, means the breaking of such an illusion, and thus the breaking of oneself as a mental existence. On the other hand, as we grow older, the chance of actually dying does also increase in a very real way. I could suppress my own fear as hard as I can, yet all of these thoughts still dread me from the deepest part of my mind.

Stepping back for a moment, why do we fear death, or "not waking up as the same person", which is basically the same thing, anyway? It once occurred to me that I did not actually know the reason for me. What does it change for me, if, say, there is not actually a consistent existence of myself? Would I do anything different? If not, what is the point of having this fear to the point that it prevents me from having a good night's sleep? Even if I knew I am going to die in my sleep tonight, what would I be able to do? And what is the difference between dying tomorrow and, say, 50 years later? It seems that to a person, once they cease existing in this world, then nothing would ever matter again, and whatever one did or did not do makes absolutely no difference. Disappearing without pain in one's sleep seems to be the best way of passing under this interpretation. The dread is very real, except that I could not explain where it came from, let alone finding myself a way out.

About one year ago, someone who I had a fair amount of connection with online passed away in her sleep due to something as simple as hypotension. May this year marked the first anniversary of being on the internet without her. For this reason, I and a few friends of her (who are also friends of mine) became a bit emotional around that time this year. A lot of us were talking about how great a person she was, and how much she meant to all of us. I also posted a somewhat emotional article on my second blog remembering her, and my thoughts at that time on the meaning of life. The general idea of what I wrote is that, because we never know whether and when the same sort of things would happen to ourselves, trying to assign a meaning to our lives is ultimately futile. If we define the meaning of life as realizing some sort of dreams or accomplishments, what would we say about her? Would I be cold-hearted enough to say that her life is meaningless because of her early death, or is it not meaningless because she tried to live her best life until the final moments?

While I was writing that article, it struck me that trying to assign a meaning to our lives is also a main reason of my constant dread for death. By that, I do not mean that death itself is not something dreadful -- but the fact that I might live a meaningless life is more dreadful than the fact that all of us will eventually die. Life is fair in the sense that everyone has limited time in this world, but I have always been taught that the meaning of every single person's life is different. It is somehow despisable not to achieve something "meaningful", and we often mourn for people who passed away at a young age for their lost potential of achieving something later in their lives, not for the actual loss of a life.

In the article, I concluded that life does not, ultimately, have any particular meaning. Humans assign meaning to life, just like they assign meaning to everything else. But we should not forget that all of this is just a figment of the human mind -- nature, the universe, or whatever higher being you believe in, does not care even the tiniest bit of what we mere humans think of our lives. Compared to the age of the universe, even the longest-living humans are nothing more than a blip in the never-ending flow of time. If the universe had its own mind, what would it think of our tendency to judge our lives based on what we assign to them as "meaning"? Probably the same way how we see kids, just like me, who worry about life and death -- "cute".

Dreading for death before achieving some particular goal, in this sense, is as meaningless as life itself is. This does not mean, however, that all of us should just do nothing and wait for, or even accelerate our inevitable demise, at least not in my books. Think about it this way -- what do you do after you achieve your goal, if you think that the meaning of your life depends on that goal? I believe most people would not just say that they may as well die the moment they achieve their goals. It is the same case when you do not believe an inherent goal or meaning of life. There are many, many things to experience on this world -- way more than just achieving one or a few goals. Being born on this world is an opportunity, or, if you prefer, a blessing, to experience all that this world has to offer. Because of the lack of an inherent meaning to life, we get to decide what we want to do with our own lives. This of course including the decision to achieve something beneficial for the entire race of humanity -- but there are so much more. From this point of view, obsessing over an arbitrary "meaning of life" and not trying to experience life itself in its fullest form is a waste of a great opportunity.

The YouTube channel Kurzgesagt had a great video on Optimistic Nihilism, which generally matches what I described. It is classified as nihilism due to its rejection of the idea that life has to be inherently meaningful, but optimistic because it does not urge people to give up on life for the reason that makes it nihilistic. The logic goes the exact opposite way -- because life is inherently meaningless, and because how unimportant every single one of us is, it is us who should make the most out of our own short existence. There is no need to worry too much about whether I will wake up the same tomorrow, because it does not make a difference -- whether I live for one day, or 100 years, what I will do is exactly the same. As one of my friends hinted, extrapolating from the same topic: all that matters are the experiences and memories we collect along the way.

We will all eventually die. Is that dreadful? Of course, because what lies ahead is unknown. But before that moment eventually comes, we have all the opportunity to define our very own lives. Make friends, try new things, create art, do what you love, experience everything you can with your limited time. At the very least, when our final moments come, when our lives flash before our eyes, we could then smile and say, "that was a good life".

Cryptocurrency Ramblings

I used to be a cryptocurrency enthusiast, though not of the type who became billionaires by mining bitcoins on a single CPU for 30 minutes in the early 2010s. The story began in 2016, the year when I graduated from high school and finally became an undergraduate student. Naturally, I had a bit more financial freedom than I did in high school, which led me thinking about, well, "investment". Around that time, Bitcoin and blockchain in general was gaining unprecedented popularity, with a lot of money pouring in and new exchanges being founded almost every single day. Mining farms were being build everywhere in China. There were a few close friends of mine who started playing with blockchain, some of whom invested a considerable amount into Bitcoin. As someone who loves new technologies, I could not resist the trend but to also set up my own Bitcoin wallet and start to play around in the Bitcoin market.

Lucky for me, there was a serious uproar in the Bitcoin market nearing the end of 2016, right after my first ever investment made in Bitcoin. I vividly remember it was in a Monday morning, when I was on my way to the university, that I saw the unbelievable exchange rate on my phone. My heart started pounding like crazy. Even though I had next to zero experience in any sort of trading before, I still knew that such a ridiculous sudden climb in prices will not, on itself, hold for very long. As the seconds passed, I stared at my phone screen, with my hands sweating uncontrollably, hovering over the "sell" button. As the price reached around CN¥8000 (~US$1500), I made up my mind and clicked on the button.

That was the first time I earned anything through investment. I was thrilled, and even more thrilled later after learning that the Bitcoin market crashed a while after that peak. I was relieved that I made the right call, and also quite a bit complacent for my "ability" to make the right call at the right point. However, I did not really make a lot more investment into Bitcoin after that, simply due to the fact that I was worried I ran out of luck and will be tremendously disappointed the next time. Despite that, the first-time earning definitely sparked my interest in the technology as a whole. Following that year, I started to learn a lot about blockchains, including Bitcoins and other cryptocurrencies. I started mining CPU-based coins using a server I have idling. A lot of other decentralized software, not limited to just blockchains, entered my field of view as well. Some notable ones include ZeroNet and IPFS, and a plethora of content distribution systems, based on blockchains or not.

Though I did not continue investing a lot in Bitcoin or other cryptocurrencies themselves, I was nevertheless a firm believer of the entire blockchain ecosystem. The fact that these systems can work without a central authority, at least not technically, fascinated the young me who just started my CS program. To me, this was the future -- the decentralized future, where all centers of power are dissolved and a censorship-less, privacy-first internet, and, beyond that, such a society, would arise -- a pretty naïve technological anarchist, I know, but that was what I believed in. Despite not making direct investments into any cryptocurrency out of fear of volatility, I held onto a small but significant amount of Monero from my mining machines. For a brief moment, I even attempted to run a full Monero node. I tried to use cryptos for payment of everything, including my VPS, my dedicated servers, and donations to various foundations.

All good and dandy until I eventually started to realize the countless downsides of blockchain. Aside from the obvious fact that proof-of-work is extremely wasteful (which I did not realize at that point), the inconvenience of Bitcoin-based payments definitely bugged me a lot during those years. I held on to Monero, but I still had to use Bitcoin for payment quite a bit due to its popularity. Every time I try to do so, I had to sit in front of a screen waiting eagerly for the transaction to go through. Five minutes, ten minutes, one hour, until a confirmed check mark is finally shown on the transaction. This is simply excruciatingly painful. Although this is quite specific to Bitcoin due to its popularity and, well, inefficiency as a first-comer, and they did make the effort to improve the situation, it is nevertheless way more annoying to use than everything else.

This was far from the major deal-breaker for me with blockchain-based cryptocurrency, though. That turning point came way later, when I realized how 90% of new cryptocurrencies were simply money grabs, or worse, pretty much frauds. This realization was from my participation in a (at that time) new cryptocurrency which shall not be named. It promised great returns on investment. It promised great earnings from mining -- which is why a few friends and I all thought about mining and trading some of it. What I could not help but notice though, is that even though they mentioned all of these great investment prospects, they failed to present any technical innovation, not even the tiniest bit. They just forked the code of Monero, changed the name and the genesis block, and started a campaign. Did they believe in decentralization, free software, or even privacy? I fear not, as if so, they would have at least mentioned it in their whitepaper and homepage. At the very least, someone who really cares would not, in my opinion, do something like this without any substance.

After that, I went and checked a bunch of newly-launched cryptocurrencies. To my surprise (but probably to nobody else's), most of them fell into the exact same category -- loads of buzzwords about financial gains, but little or no technical substance whatsoever. My later experience with a few professors in my university who work on blockchains certainly did no help in improving my plunging impression about them. One of them, who shall not be named, allegedly might have mined cryptocurrencies in the university. The course he taught, which is supposed to be about foundational operating system concepts, ended up being nothing about what you expect from an OS course. Instead, the coursework literally asked students to write papers about blockchains or other related areas. He even ran one of his own conference-style thing about cryptocurrency for these substance-less papers. Another one was better than the previous one by a million light years, and I thank him sincerely for his appreciation of my skills and help in my academic life while I was working in his lab, but this still did not give me a better impression on the entire cryptocurrency community. His work, and work I have done with him, definitely had some substance in them instead of being money-grabbing bullshit like the others, or at least I believe so. However, at the end of the day, I still had no idea what our work meant, if cryptocurrencies were to be the future of economy. Did I work on something that make them better? I often ask myself. And the answer, to me, is a no.

Do I hate my professors? Other than the first one, no, not at all. On the contrary, I am extremely grateful for all that they have done for me as an undergraduate student. But the experience doing research in the field simply makes me realize the cold fact about the area -- most people are too profit-driven and few are really working in the field for what Satoshi Nakamoto originally believed in. And I don't even blame them personally -- were there an easy opportunity to become a millionaire, I would do it as well. This does show, however, that true decentralization cannot work purely based on what Nakamoto laid out as the blockchain technology. It creates a self-fulfilling market and the entire community built around such a market. Whatever Nakamoto envisioned for his brave new world, the truth is that everyone is working not for decentralization, but re-playing what has already happened -- centralization of wealth -- just on a different medium.

Nowadays, the sentiment against blockchain-based coins / technology is growing like wild fire. I should be happy, right? Maybe not. For all my hatred towards people who claim to be enthusiasts of cryptocurrency while chasing only profit, I cannot say the same to the technology itself. Don't get me wrong, the blockchain technology as it is today can never be something I will actively advocate for due to its countless pitfalls and shortcomings, not to mention the extreme centralization of computing power and the privacy issues in current popular implementations. But it is not like the non-blockchain financial system is much better in any of these aspects -- centralization of power, tick; privacy issues, tick; the only advantage of it is the power consumption because it does not involve any proof-of-work. Blockchains currently do not solve these problems per-se, but it is so far the only one that looks promising in any capacity at all. At the very, very least, trying to "freeze" accounts or "block" / "reverse" transactions on blockchains with proof-of-work is way harder than in your traditional banks, who have made the headline multiple times in the past year.

I could argue for days why this exact property of blockchains is a good thing or a bad thing, but at the end of the day, just like many things in society, what we need is a balance. The existence of an alternative to traditional banking systems, to me, is not to replace everything, because that would be impractical. Of course, something better than proof-of-work may be able to finally push blockchains towards practicality in general, but at this point it just does not seem likely without another few Satoshi Nakamoto. We have potential ideas for improvement, but they are delayed and delayed and the date of deployment seems pretty far away, not to mention that these ideas generally trade some of the advantages of a PoW blockchain for better performance. Not to mention that the ability to block accounts or reverse transactions can be desirable sometimes. Rather, in my imagined future, these systems, when they (potentially) become mature enough, should act as a check on the old systems, such that abuse of power in the old ones carries an additional risk from people fleeing into the other system.

Where does this put me now? I am not actively holding any number of cryptocurrencies at the moment, and I personally do not want to invest into them in the near future. Nor do I want to be involved in the current cryptocurrency community, academic or not, in any capacity. But I do hope that the technology will come to fruition one day, even though this day may be far, far in the future.

Writing Challenge

I have been thinking about taking the 100 days writing challenge for a while. Not just for a little while, but for at least a few years by now. Within these few years my blog have been destroyed and restored multiple times, I graduated and I moved -- basically, everything has changed. Yet I have never really made the decision to attempt to write every single day.

Not surprisingly, the main reason I have not done so is due to the big commitment I have to make in order to complete it. Writing everyday is not something very easy -- it's certainly not hard, but it still takes a non-negligible amount of time and energy out of every single day. Like any "beneficial" habit, it is simply hard to make up one's mind to make the initial commitment, just like many have not made up their minds to lose weight, or to try a different kind of diet.

To me, though, there is something more about this unwillingness to commit to writing as a habit. One of them is the idea that all writing has to present a well-supported argument with eloquent words and beautifully organized structure. If I am writing stories, then they have to at least be interesting to someone other than myself. They need to have an eye-grabbing beginning, a twisted plot, and a satisfying ending. Moreover, they have to try to show readers some takeaway through the story-telling. And of course, as English is my second language, I was basically trained to be extremely careful about grammatical errors by all the tests and exams I have been through. The result is simple -- every time I try to write, this pressing anxiety begins to creep into every single nerve of my brain, and, well, it makes writing, at least in English, a somewhat exhausting process. Every time I publish a blog article, I have to go through a time-consuming process of trying to organize the article in a bunch of different ways, figuring out what exactly to say in each paragraph or even each sentence, and so on. As you might be able to see, this means that I was really only willing to write about things I consider "important" for more people to know about, for example, technical challenges not solved by Google-fu.

I could simply not write in English, then, if the problems come from my training of English as a second language. Except I can't. First of all, the idea that writing has to be formal is not limited to just English. I did not get this from my English training, but rather, from the fact that all writing training I received is under an academic setting. Obviously, for something academic, one would want to be as formal and structured as possible, because you would not get too far in the academic world without some nice, cough, papers. Secondly, although my mother tongue is Mandarin, I, somehow, feel even more pressure when I try to write in Chinese. It might be from all the Chinese exams I had to take during my high school years, which forces me to come up with something nice for the writing task, taking up almost half of the total marks for those exams. What's the result of scratching my head over and over again for more than 3 years in high school? Every single Chinese exam, every single one of them, gave me just the passing mark for all my effort. I might write another blog post just about my current inability to write in my own native language. The takeaway here is that if I were to try the writing challenge in Chinese, it would be even harder.

I am trying to work my way out of this mindset, for both English and my native language Chinese. I need to stop thinking about what others would think of my writing. I of course write for others to read, but what I write needs to reflect me, not what I expect others to expect from me -- that, is too many levels of "indirection" to make sense. When I have something well-supported to argue about, fantastic, and I should definitely write a nice long article for it. But when I don't, it is no shame to simply admit that I am not sure. It is okay to not be that most knowledgeable guy. It is okay to make mistakes. Because these are all part of me -- and through writing, I'd like the readers to know me.

Will I ever take the 100 days writing challenge? I am not sure. Even if all the problems above are resolved, I might still not want to write publicly every single day. When you write that much, it is inevitable that aspects of your daily life will eventually be leaked into what you write, either directly through your own words when you have nothing else to write about, or through the patterns visible from your posts. I, coming from a background where everything can be used against you, probably will never be comfortable with such a possibility. I want to record my thoughts, and I want my readers to know me as a person, but not the entirety of me -- and I feel that taking on a challenge like that is the perfect opportunity not to do so.

What I will do, though, is to write more. Like, more than how much I did before. When I have blog ideas, I will try to force myself to get something out of them, even if the resulting product is not well-organized to my satisfaction. I am also going to start a private diary that I will, at least attempt to, update every day. It will not be public, but hopefully some great writing ideas can come out of it. It would also be a nice archive of who I am now and how I am changing over time, which is always nice to have. To be honest, I hope I have had a diary way earlier. When I was younger, I never thought that I could change so much one day, but here I am, almost a completely different person from who I was 10 years ago. It would be nice to be able to see how I changed, which could also serve as a guide for myself, or even others, in the future. Hopefully, this time, I will have such an archive.

The Past Self

While trying to rebuild this blog, I had to browse through an archive of my old articles and decide whether to import them to the new one. Reading articles written by myself in the past feels very strange -- I cannot say about others, but for me, thinking about my past self is one of the weirdest experiences to have. I clearly know that the person, either in my memory or in a written story, used to be me. Yet, all of the self-reflection is done as if it was in third-person. That me, or whoever it was, has a different personality, a different world view, different tastes in everything, and much more. It is almost a separate existence, while at the same time, obviously being me.

The feeling of disconnection from my past self sometimes freaks me out. Who am I if I am no longer the same person in my memory? Sure, I am still physically the same being, but if basically everything about me is different, what makes me the same me? If someone were to invent a time machine, and I had the chance to face my own past self, I would, not exaggeratedly, despise that person. There are just too many things I hate my past self about -- the unreasonable level of patriotism, the naïve admiration to Apple and (later) Google, the uncountably many stupid quibbles and unpleasant arguments I had with people around me, or all the friends I lost along the way. Heck, I was even once a shameless copycat who steals code and claims them to be my own. I could go down the memory lane for hours, but in summary, to me, the Peter from the past is just... plainly unacceptable, in all sorts of ways.

This bothered me for a very long time -- or rather, the past me -- because now I am looking back on this experience as well. Eventually, the realization came that I am simply unwilling to be associated with what I have done in the past. The past me seems awful because I judge my past from the point of view of me in the present. I learned from my experiences, and I changed according to what I think have done wrong. The experience of having done things I now recognize as "wrong", and the fact that I later realized these mistakes, turn them into something I am constantly on the look out for, not only on myself, but on everyone else, including the "me" now frozen as memory. This, of course, prevents me from doing the same thing ever again, but it also makes me extremely harsh, at least mentally, on anyone that does something I did in the past but stopped later. When I look back in my own memory, the realization that I was exactly someone like that causes me to try to distance myself from, well, myself.

What defines "me" is the constant journey from the past self, to the present self, and eventually, the future self. I am sure that in 10 years, or even just 2 to 3 years, many aspects of me will again change almost entirely. Looking back on what I do now, it will certainly feel stupid, embarrassing, or even repelling, again. But it does not mean that what I am doing now is not part of me in the future. Something cannot be "living" when it only exists in a single snapshot of time -- the very definition of "living" is dynamic. Just like we constantly ingest nutrients and replace the very building blocks of our body, we also rebuild our own personality, bit by bit and day by day, towards our own ideals at the moment. The only reason I am here right now, with all of my current beliefs and ideals, is that the past me tried to re-mold himself into something better. However despisable I was in the past, the person who I was had at least one thing good about him -- the willingness to change -- and I cannot be here without it. In this sense, I should be grateful to whoever I was in the past.

What this also means is that I should be kinder to others who I despise. I am not someone who tends to express despise via language or behavior, but my internal harshness towards people who behave like my past self might still be recognizable to others. Rather than someone who does something unacceptable to me, I should view them as someone who has still not "evolved" from a state I was in the past. What would I think if someone were so harsh about me in the past? Probably not too good. Just because someone is in a state right now does not mean they will not change in the future, just like how I did from my past self to my present. What is important is to try to help them accelerate the process -- like a lot of friends did for me -- rather than simply avoiding them. That does no help whatsoever. At the very least, I should not exacerbate the problem by not being kind to them.

Hello, world

Hello, world again. It's been a long time since I last hosted anything on this domain.

There used to be a blog here, but as I grew frustrated by a certain part of the internet, I deleted the entire blog and left everyone with a bare 404 page. Many have asked what had happened, but none of that matters anymore, to me, or to anyone else. My life has changed completely since then. I moved to a new country, had new plans, and I am basically starting a new life.

As such, I figured it is probably a good idea to try to restart my blog-writing hobby again. There might be good ideas as well as meaningless ramblings, but probably still worth keeping. I might also re-post some articles from the old blogs just to keep them around. Looking back at things written by myself from years ago is embarrassing, but at the same time, inspiring. It is a written record of how much I have changed as a person.

So, here we go again.

Encryption is not Security

(this post was imported from my old blog)

We are not in a time short of products that claim to "encrypt" your personal data with "military standards" and thus keeping them safe from leakage or deliberate attacks. This can really work in convincing a lot of non-tech-savvy people and even some with rudimentary computer knowledge about how secure those products are -- until some leakage events happens out of nowhere and everybody gets screwed.

The problem here is that things involving encryption does not necessarily imply security of the particular data you are concerned about. Encryption is a broad term that can be applied to anything that includes some algorithm to prevent part of the population from accessing some data. Anything from simple dictionary-based cipher to modern cryptography all fall into this category, but I am not even talking about the vulnerabilities concerning different ciphers here. What I am talking about is the question of which part of the population exactly do you want to block from accessing, in other words, the threat model.

The word "secure" itself is vague unless the context specifies a well-defined threat model. What are you afraid of? Who should be able to see your data and who should not? How do we ensure you are you, not someone else faking your identity? Of course, encryption is a powerful tool to achieve any sort of security, but any implementation cannot be said to be secure under all threat models. You are using military-grade encryption right now to browse this post because my blog is using HTTPS protocol which encrypts all plain-text traffic, but to my server, to me, the content still needs to be decrypted, and nothing prevents me from publishing all your IP addresses in some log format. No matter whether you consider IP address privacy-sensitive, I think it is pretty obvious that in this case, if I were to claim my website being secure from such leakage, it would be bogus. The HTTPS protocol defends against people spying on your Internet connection, but does absolutely nothing about both ends of communication. It is secure under the threat model where nobody in the communication channel except both endpoints can be trusted, but nothing else. One cannot imply that such use of encryption is secure under any other circumstances.

It is how encryption is used in a product that matters, not whether it is used. My previous absurd example is laughable, but when such claims come from some more complex or even "commercial" software products, somehow, many of us forget what being secure actually means. And I know that it is a stretch to assume everybody can learn these basics, but frankly, in the age of Internet, one must have such knowledge to "survive" -- I mean, to keep private data safe. There are a lot of resources out there about introductory cryptography, and I am 100% sure every single one of them will talk about the definition of "secure" and threat models at the very beginning. To be fair, many of them are not intended for people without a technical background, so we definitely need some of such resources in simpler language. But what we also need is people that actually try to learn about how to ensure their own security.

Not surprisingly, it also lies upon developers and, in the case of commercial software, companies, to stop throwing buzzwords that are not even well-defined in the first place (trust me, even some open-source projects do this). Do not claim your product to be secure just because you, somehow, used some encryption, somewhere, without mentioning what you are defending against, and how all the buzzwords contribute to this. Do not ever try to imply your product being more secure just because of encryption -- explain what it is for, and what adversary it could prevent. And, of course, you should always know, for yourself, what you are defending against, because some developers really do not. It is not whether actually being secure that matters here -- after all, the word is not well-defined by itself -- but the false sense of security you might implant on your users. The feeling of "I'm secure" without knowing what the hell it even means is much, much more dangerous than any security vulnerability.

(This article was partly motivated by some Magisk module here in China that saves your payment password and auto-fills upon fingerprint authentication to some payment apps. It claimed to be somehow more secure due to its use of encryption, but it actually just encrypts the keys with ANDROID_ID, which, though is not the same across all applications anymore, is still not intended for security purposes and can be predicted, given that the adversary can read the data files. It defends against no extra adversaries compared to not encrypting in the first place, but somehow people do believe its claims, and maybe the developer also does really think so.)

The Zygon War Speech from The Doctor

(this post was imported from my old blog)

(From "The Zygon Inversion", in 9th series of Doctor Who)


"It's not fair."

"Oh it's not fair. Oh I didn't realize that -- it's not fair. You know what, my TARDIS doesn't work properly, and I don't have my personal tailor."

"These things don't equate."

"These things have happened. They are facts. You, just want cruelty to beget cruelty. You are not superior to people who are cruel to you. You are just a whole bunch of new cruel people. A whole bunch of ... you cruel people, being cruel to some other people, who end up being cruel to you. The only way that anyone can live in peace, is if they are prepared to forgive. Why don't you break the cycle?"

"Why should we?"

"... What is it that you actually want?"


"Ah, right. And when this war is over, when you have a homeland, free from humans, what do you think it's gonna be like? Do you know? Have you thought about it? Have you given it any consideration? Because you are very close to getting what you want. What's it gonna be like? Paint me a picture. Are you going to live in houses? Do all people go to work? Will there be holidays? Oh, will there be music? Do you think people will be allowed to play violins? Who's gonna make the violins? Well, ..., oh, you don't actually know, do you? Because, like every other tantruming child in history, Bonnie, you don't actually know what you want. So, let me ask you a question about this brave new world of yours. When you've killed all the bad guys, and when it's all perfect, and just, and fair, when you have finally got it, exactly the way you wanted, what are you going to do with people like you? The troublemakers. How are you going to protect your glorious revolution, from the next one?"

"We'll win."

"Oh, will you? Well, maybe. Maybe you will win. But nobody wins for long. The wheel just keeps turning. So come on, break the cycle."

"Why are you still talking?"

"Because I want to get you to see... and I'm almost there."

"Do you know what I see, Doctor? A box, a box with everything I need. A fifty percent chance -- for us two."

"Everyone fingers on buzzers! Are you feeling lucky? Are you ready to play the game? Who's gonna be quick and who's gonna be luckiest?"

"This is not a game."

"No, it's not a game sweetheart and I mean that most sincerely."

"And why are you doing this? ... You set this (the truth and consequences buttons) up, why?"

"Because it's not a game. This is a scaled model of war. Every war ever fought, right there in front of you. Because it's always the same. When you fire that first shot, no matter how right you feel, you have no idea who's going to die. You don't know who's children are going to scream and burn. How many hearts will be broken. How many lives shattered. How much blood will spill until everybody does what they were always going to have to do from the very beginning. SIT DOWN AND TALK. (Sighs) Listen to me, listen -- but I just, I just want you to think."

"I will not change my mind."

"Then you would die stupid. Alternatively, you could step away from that box. You could walk right out that door, and you can stand your revolution down."

"I'm not stopping this, Doctor. I started it, I will not stop it. You think they will let me go after what I have done?"

"You're all the same you screaming kids, you know that? Look at me, I'm unforgiveable. Well here's the unforseeable, I forgive you. After all you've done. I forgive you."

"You don't understand. You will never understand."

"I don't understand? Are you kidding me? Of course I understand. And you're calling this a war, this funny little thing? This is not a war. I fought in a bigger war than you will ever know, and it's the worst thing you could ever imagine. And when I close my eyes... I hear more screams than anyone could ever be able to count. And you know what you do with all that pain? Shall I tell you where you put it? You hold it tight, that burns your hand. And you say this: no one else will ever have to live like this. No one else will have to feel this pain. Not on my watch."


"It's empty, isn't it? Both boxes, there's nothing in them. Just buttons."

"Of course. You know how you know that? Because you've started to think. Like me. ... No one should have to think like that. And no one will. Not on my watch. ...Gotcha."