Mastodon

New Year, New Password Manager

The walled garden of the Apple ecosystem is certainly a cozy one, but good luck if you ever want to venture out beyond into other realms, such as Linux. For some use cases, iCloud is not only perfectly fine, but even preferable. I don’t foresee myself needing access to my Shortcuts on any non-iOS devices, so I can’t say I have any real qualms about cordoning them off onto their own platform. My documents, on the other hand? That’s another story. Likewise, what about photos and, probably most importantly, passwords? To put it succinctly, I want a solution that lets me have access to only what I need on each device/OS that I use, and nothing more. 2020 has brought some new themes for me; one of which is action. I’ve decided that the first step I’m going to take towards achieving world domination my goal is tackling the most important domain: passwords.

As aforementioned, things are pretty great within the confines of the walled garden; though by no means is it a panacea. The Keychain app has some pretty gaping holes with regard to its capabilities on each of the various platforms. On macOS, it’s pretty great! There’s a good concept of the different kinds of information that can be securely stored within it: login passwords, keys, notes, etc. Sadly, this notion does not translate over to iOS, and that’s a problem. Reinstalling macOS and the encryption key of your backup is stored in a secure note? You better write that down ahead of time or have another Mac around. May the gods have pity on you if you need to access any passwords on a device that isn’t logged into your iCloud account, or *gasp* isn’t running an Apple OS.

There are myriad third-party password managers. I prefer open source solutions where possible, so I first tried Bitwarden. It’s… okay. It does tick all the big boxes that Apple’s first-party solutions do, with the added benefits of having a web app (!) and being much more cross-platform. I understand why all of the clients are Electron/React-based, but I much prefer native apps. Being open source, and seeing some existing attempts at native clients, I thought I’d try to revive one. In doing so, I see why it stagnated: there’s little to no documentation, both outside of and within the source.

Enter: KeePass

KeePass is more of a protocol than a platform, and this is how it shines! There are native clients for just about every OS (at least that I use), and syncing it is as simple as passing a single file, the database, around through whatever means you please (in my case, Nextcloud). Clients can take care of merging or reverting changes as needed.

Hello darkness Applescript, my old friend…

Migrating between proprietary applications is never without hiccups, and Apple usually does a better job than most at enabling interoperablilty *cough* Microsoft *cough*. Keychain.app though, is the absolute antithesis of this. I understand that a password manager should probably have additional safeguards in place around data export, but crippling that functionality is not a safeguard. Login passwords, such as internet passwords, cannot be exported. The category of secure items that I most likely need available to me on other platforms is the hardest thing to extract. Having almost 250 login items in Keychain, I was not about to type my password in for each. Thankfully, there’s an App[lescript] for That™. I had to modify it to work on 10.14.6+, and if you’re reading this more than six months from date of publication, I’m sorry that you’ll probably have to modify it further to work for yourself, but here, in all of its horrendous glory, is a script to copy a given number of items from Keychain.app to a csv file.

set x to 1
tell application "Keychain Access"
activate
repeat while (x ≤ NUMBER_OF_ITEMS_TO_EXPORT)
tell application "System Events"
click text field 1 of row 1 of outline 1 of scroll area 1 of splitter group 1 of window "Keychain Access" of application process "Keychain Access"
keystroke return
delay 0.2
keystroke tab
delay 0.2
keystroke tab
delay 0.2
keystroke tab
delay 0.2
keystroke "c" using command down
delay 0.2
do shell script "/usr/bin/pbpaste | xargs -I {} echo -n {}\",\" >> ~/exports.csv"
delay 0.2
keystroke tab using shift down
delay 0.2
keystroke "c" using command down
delay 0.2
do shell script "/usr/bin/pbpaste | xargs -I {} echo -n {}\",\" >> ~/exports.csv"
delay 0.2
click checkbox "Show password:" of tab group 1 of window 1 of application process "Keychain Access"
delay 0.2
keystroke KEYCHAIN_PASSWORD
delay 0.2
keystroke return
delay 0.2
keystroke tab using shift down
delay 0.2
keystroke tab using shift down
delay 0.2
keystroke tab using shift down
delay 0.2
keystroke "c" using command down
delay 0.2
do shell script "/usr/bin/pbpaste | xargs -I {} echo {}\",\" >> ~/exports.csv"
delay 0.2
click UI element 2 of window 1 of application process "Keychain Access"
delay 0.2
key code 125
delay 0.2
end tell
set x to (x + 1)
end repeat
end tell

You’ll want to substitute the number of items, as well as your password, and beware that it obviously exports them as plaintext (in plain text), so don’t save it to your Documents or Desktop folders if those are synced via iCloud. Additionally, you can sort items by “Kind” if you’re only interested in exporting certain types, such as login items. Then sit back, relax, maybe prepare a beverage, because it might take a while (About a half of an hour, in my case).

Part the Second, Converting to KeePass

KeePass has a diverse ecosystem of scripts and utilities for importing a variety of data formats through a client. For our purposes, there’s csv2keepassxml, an incredibly flexible Ruby utility that converts data from, you guessed it, csv into an importable xml file. If, unlike me, you’re a Ruby expert or don’t care about littering your system with packages you’ll install once and probably never use again, feel free to skip the next two sections.

rbenv

Because I wasn’t developing web apps in 2008, I’m not a big fan of Ruby, but I am a fan of using virtual environments, especially for languages with system installations, such as Python and, you guessed it, Ruby, on macOS (for now). If you don’t care about such things, feel free to skip this section. For everyone else, there’s rbenv. Much like its Python counterpart, pyenv, installation is simple and can be accomplished via brew.

$
brew install rbenv

Follow the instructions given by the init command to set up your shell.

$
rbenv init

Finally, source your config or restart your terminal to make the changes take effect.

Usage is equally simple. To install a far more up-to-date version of Ruby than what macOS may (or in the future may not) even have, simply use the install command.

$
rbenv install

rbenv-gemset

Virtual environments aren’t terribly useful without dependency management. For rbenv, this is where rbenv-gemset comes in. A plugin for rbenv, it allows dependencies to be managed per-project and even reside within the project directory.

Installation is as easy as rbenv, as it’s also available via brew.

$
brew install rbenv-gemset

In the root of the project, create a gemset using the current version of Ruby.

$
rbenv gemset init

You can now use gem as you would normally, with the gems being installed to a directory in the root of your project.

csv2keepassxml

If you’re joining us from the beginning of this part, welcome back! csv2keepassxml is available not via brew, so let’s clone the repository from Github.

$
git clone https://github.com/lifepillar/csv2keepassxml

Create a gemset, and install csv2keepassxml's dependencies into it.

$
gem install htmlentities

If you used the format of the aforementioned applescript, the following will create a KeePass2 database file from the exported csv file.

$
./csv2keepassxml -t 1 -U 1 -u 2 -p 3 ~/keychain-export.csv

Note: Indices are 1-based. Unfortunately.

Clients, Clients Everywhere!

There are a plethora of KeePass clients out there. Here are the ones that I use, and for the most part recommend. For an added bonus, they’re all open source!

Conclusion

This is the first step in my journey towards building a private infrastructure for my personal data. Over the upcoming months, I’ll be looking into solutions for file storage and syncing, and then eventually services such as email, contacts, and calendars.

❋❋❋

LightDM with an External Display and the Art of Pseudocode

Today I found the solution to an incredibly first-world problem that’s been plaguing me for the majority of the months I’ve been using Arch (I use Arch, btw) full-time: Logging into a session when my laptop is connected to an external display and in *gasp!* clamshell mode. Signal boosting a post that solved this problem that I’ve been procrastinating on lo these many weeks for me probably shouldn’t warrant a whole blog post but I wanted to praise the author for walking the reader through a step that we all probably do, or at least probably should be doing more deliberately: pseudocoding.

Much like in the process of writing my first paper in college where I started drafting an outline without even thinking about it, a credit to the years of English teachers in high school who made me do it even though the topics of many of the papers I wrote in those classes weren’t so complex that I felt I could adequately hold it all in memory, there are times when we find ourselves with a problem sufficiently complex that we need to utilize swap-I mean scratch paper, and we start making (quite literally if you’re me) back-of-the-napkin diagrams and rough pseudocode with horrendously-named functions that we swear we’ll fix when it comes time to implement. If the code you ultimately write never leaves the confines of your hard drive, it’s fine if the chicken scratch you’ve scribbled to yourself never makes it off the page, but if you share that solution with anyone, and especially if you share it in the form of a blog post, it’s really to everyone’s benefit (including your own), that you share the pseudocode as well.

For those consuming your code, it greatly improves the likelihood that they can conceptually understand and appreciate what you’ve made even if they can’t understand the implementation very well (For example, if it’s in an unfamiliar or obtuse language, like bash). It benefits the author as well, as it gives them an opportunity to think though the problem more generally and perhaps even explore multiple solutions without wasting keystrokes implementing each one. I particularly like this problem of telling LightDM which display to use as an example of the merits of explaining through pseudocode as the problem itself can be presented rather trivially; maybe so much so that one would just start hacking away at it inside of a text editor without giving it much thought. Upon closer inspection though, the problem is revealed to be a little more complex, with multiple sub-problems branching out like the length of a coastline, growing with each step in magnification.

❋❋❋

Ch-Ch-Changes

I’ve made some much-needed updates to the site over the last couple of weeks, and I’d like to summarize some of the changes and things I learned along the way.

Design

Unfortunately, I don’t have much formal training in design beyond art classes in middle school, but I like to think I at least have a sense of what looks good and what does not (though I probably couldn’t formulate a cogent explanation as to why something looks good). One facet I’ve been working to develop in is color theory. Ironically, I think the RGB color system may have deterred me from doing so for quite some time. As an implementation detail, RGB is great, and as a lifestlye, it can’t be beat! However, it is a terrible way to think about color. Need to find a tint or shade of grey? No problem! Just make sure all of the component values are equal? Need a tint or shade of a color? Good luck unless that color happens to be red, green, or blue. Enter: Hue, saturation, and lightness, or HSL. You know that weird circumscribed triangle you sometimes find in photo editors? Yeah, that’s HSL. It’s an incredibly powerful tool for describing color, as it expresses it in terms more analogous to how humans process color. Hue refers to the point around the color wheel where its pure color resides. Lightness is a spectrum from black to white and indicates how bright the color is. Saturation is a spectrum between the hue and lightness, and is orthogonal to it, defining how prevalent the pure color is. The pure color component is the key to HSL’s power, in my opinion. Want a tint or shade of purp—I mean violet? Dial in the hue and saturation you want and then slide along the lightness spectrum to your heart’s content. Try doing that in RGB!

HTML5 Semantic Elements

For the uninitiated, HTML is an initialism that stands for the Hypertext Markup Language. I’d like to direct your attention to the word “markup,” as it’s doing the real heavy lifting in describing what it does. HTML syntactically structures and encodes the semantics of the content of the document within the document itself. Generally, this additional information is used to determine how the document should be laid out visually, but that information can be expressed in different ways for different people. For example, italic tags exist because a visually-impaired individual might not be able to see the subtle change in font depending upon how the page is rendered, but a text-to-speech program would also be able to convey that emphasis audibly. With this in mind, I’ve been incorporating more HTML5 semantic elements where applicable, such as wrapping paginated entries in section tags to better delineate them, and adding the button tag to my theme toggle switch. They’re particularly great because there’s no need for to worry about graceful degradation, as even browsers as old as IE6 can be taught how to handle them (more on that later) with as little as a single CSS rule. The internet was invented as a means of sharing information, but that information is only useful to those who can access it. Increasing accessibility (and awareness of accessibility as a ideal) is only to the benefit of everyone.

Disregarding Deprecated Browsers

Time stops for no one, especially anything related to the web. Before I began this overhaul, I knew I wanted to fully-embrace technologies such as Flexbox, but I also wanted to make sure this site is accessible to as many people as possible. In order to maintain my sanity and minimize hacks, I drew a line in the sand; I won’t be supporting any browser that isn’t supported by their developer, which I believe to be a reasonable compromise. I was astounded to discover that meant I only had to support as far back as IE11. I should clarify that when I say support, I mean in terms of visual appearance and functionality. I’ll still worry about graceful degradation when appropriate, but nothing more. After all, I’m one guy, and this is a personal website. No one’s life depends on my site’s footer displaying correctly.

“Hello darkness, my old friend”

I meant to write a post about my dark theme implementation when I made it way back when, but I forgot to do so. C’est la vie. Let’s talk about JavaScript instead! Some people love it; some people hate it; I love to hate writing it. Personally, my take on it is it’s all good in moderation as long as it isn’t doing anything creepy. With that in mind, I principally use JavaScript to enhance the readability and aesthetics of the site. For example, JavaScript powers the collapsible header that you may or may not be able to see depending on your scroll state (Go ahead! Scroll around a bit if you’ve never noticed it before). Why bother with such a thing? Well, most laptop and desktop displays are wider than they are tall, just like human vision, so to afford as much vertical screen-real-estate as possible, the header collapses out of sight as you scroll down the page, and returns at the flick of a scroll control. This design lends itself to progressive disclosure, while being forgiving to users who may not understand why the header disappeared originally. Likewise, it also degrades gracefully, as the header’s initial state is open, and won’t collapse without JavaScript available. Another example on the aesthetic side of things is lazily-loading images (this is still a work in progress as of time of posting). Let’s be honest, we don’t all always have a 100 Gbps down connection available to use at all times. Images are some of the largest assets a page has to load, and god dammit it will do so when it gets around to them! This leads to an unfortunate state of those images materializing in a slow-motion vertical wipe long after the rest of the page has been rendered. Aesthetics aside, this can also needlessly burn CPU cycles if the page layout is altered by the absence of these assets. Both of these issues can be solved very elegantly by lazily-loading images. A lightweight placeholder (even an inline SVG, perhaps?) is displayed while the actual image is loaded; upon completion of which, a handler is called that swaps out the placeholder for the actual image in the img tag’s src attribute. For those of you who don’t believe in JavaScript, have no some fear, for the noscript tag is here! Unfortunately, there’s nothing I can do to prevent the slow-mo wipe effect of potential doom or possible page re-rendering as the layout updates, but I can make sure that the correct image is displayed without being downloaded twice by wrapping a fallback img in noscript tags. If JavaScript is enabled, the fallback image isn’t even loaded!

RSS, Weblinks, and You

I’m kicking myself for not taking note of where I first saw a weblinks page (although the idea is probably as old as the internet, because everything is a remix), but I love the idea! It’s basically your bookmarks bar (or at least the interesting links) publicly available for others to peruse. I’ve made my own (find it in your local browser window!), and hope that I can use it as an opportunity to not only share things that are new and interesting to me, but things that I’ve known about for awhile and still find interesting or noteworthy, because "every day somebody’s born who’s never seen The Flintstones"Copyright 2000-something Merlin MannCopyright 2011 John Siracusa (relavent xkcd). In a similar vein, I’ve also gotten into RSS like it’s 2009. My primary motivation was to limit my consumption of algorithmic content from platforms whose desires with respect to how I use the platform may not be (Read: aren’t) congruent with mine, which is totally fine, but recognizing that reality necessitates diversifying the channels through which I consume information. In the same spirit (and because it took basically no work on my part), I’ve also set up an RSS feed for this blog, so others can take a listen to what I have to say if they so desire, rather than if an algorithm is confident enough that they will. Oh, and I use and highly recommend FeedReader, as it’s built with Gtk, looks great, works great, and respects my window control preferences (@GNOME Feeds)!

Conclusion

I’m very satisfied with the updates I’ve made over the past couple of weeks, and there’s certainly still more to be done (apparently there’s some design paradigm known as “mobile first,” and I guess I’ll have to see what that’s about), and I’ll probably write some more about those in the future. I hope that others can take these ideas and lessons and apply them in their own endeavors of building a home for themselves on the web. As a wise man didn’t once say, “Be the change you want to see in the world.”