From 8713cb4e86f08724d38dab01d640dfa7a4cd3f53 Mon Sep 17 00:00:00 2001 From: Nick Zana Date: Thu, 11 May 2023 02:30:49 -0400 Subject: [PATCH] remove outdated projects --- content/projects/bamboo/index.md | 45 ------ content/projects/ciphey/index.md | 268 ------------------------------- content/projects/iso639/index.md | 19 --- 3 files changed, 332 deletions(-) delete mode 100644 content/projects/bamboo/index.md delete mode 100644 content/projects/ciphey/index.md delete mode 100644 content/projects/iso639/index.md diff --git a/content/projects/bamboo/index.md b/content/projects/bamboo/index.md deleted file mode 100644 index 9a0fcff..0000000 --- a/content/projects/bamboo/index.md +++ /dev/null @@ -1,45 +0,0 @@ -+++ -title = "Bamboo Media Server" -weight = 3 -[taxonomies] -tags = [] -+++ - -Bamboo is a self-hosted personal media server written in Rust that I've been -working on for the past two years with my friend -[Ersei](https://ersei.saggis.com). It aims to replace existing media servers -like Jellyfin and Plex by decoupling the front-end, API, and content as much as -possible, allowing for richer client applications and a wider range of content -and content types. - -Most of what makes Bamboo's architecture different is its ability to generalize -over types and sources of content while providing common primitives for richer -metadata. - -For example, Jellyfin provides a few distinct types of media that it can serve: -Movies, Music, Shows, Books, Photos, and Music Videos. Jellyfin's API is deeply -tied to its web front-end, so the content you can host on Jellyfin is limited to -what the Jellyfin web client is capable of displaying. This works okay for -classic media server content like Movies and TV, but even something slightly -beyond its expectations, like a YouTube video or Twitch stream, must be made to -conform to the formats that Jellyfin expects. - -Bamboo solves this problem by defining generic types that are common to all -media, such as the Title, a UUID, and a list of URLs it can be accessed at, and -allowing specific types of media to expand upon with additional data and fields. -This way, clients can be as specific or general as they desire based on their -required functionality. A media search application may not need to care about -anything beyond the title, while a Podcast application should only accept media -that is of the Podcast data type. - -Of course, being written in Rust, Bamboo utilizes Rust's type system to define -strict API specifications. Invariants, optional or mandatory fields, and data -types are explicitly encoded using `struct`s, `enum`s, and `serde` for -serialization and deserialization, removing any ambiguity in the specification. -This is important for an application as dynamic as Bamboo, as the vast range of -content that it's capable of serving is intentionally vague and thus incorrect -assumptions by the server or its clients can make for inconsistent, incorrect, -or buggy code. - -The public repository for the project can be found at -[git.nickzana.dev/bamboo/bamboo](https://git.nickzana.dev/bamboo/bamboo). diff --git a/content/projects/ciphey/index.md b/content/projects/ciphey/index.md deleted file mode 100644 index c40467c..0000000 --- a/content/projects/ciphey/index.md +++ /dev/null @@ -1,268 +0,0 @@ -+++ -title = "ciphey" -weight = 1 -[taxonomies] -tags = [] -+++ - -Simply put, `ciphey` is a password and secret manager that is like -[`pass`](https://passwordstore.org) if it used -[`age`](https://age-encryption.org) instead of PGP. More than anything, it is -an experiment to determine how cryptography can be combined in a minimalist -manner to protect passwords in a way that accounts for the most realistic -threats to their confidentiality, reliability, usability, and resiliency. It -takes many of the database and key management ideas from -[1Password](https://1password.com) and [Bitwarden](https://bitwarden.com) and -combines them with the Unix-like philosophy of `pass`. - -To be clear, `ciphey` is still in development. [The remaining work is outlined -below](#remaining-work). While I will be using it as my actual password manager, -I strongly recommend that you only experiment with it and not rely on it for any -actual passwords. - -*NOTE: This page is a work in progress.* - -## The Basics - -My goal is for `ciphey` to be simple enough that someone with a bit of knowledge -about cryptography who wants to understand how their passwords are protected can -do so after a short explanation. This sections aims to be that explanation. - -### Entries - -Everything you store in `ciphey` goes into an entry. Generally, you'll have one -`entry` per password. However, passwords come in many different forms: as a -result, entries are plaintext, which means any file can be used as an entry. - -This doesn't mean there is no structure to entries. For example, take a look at -the entry for a hypothetical [`xkcd.com`](https://xkcd.com) account below: - -``` -correct horse battery staple -name: xkcd.com -tag: comics -username: Tr0ub4dor&3 -url: https://xkcd.com/936 - -To anyone who understands information theory and security and is in an -infuriating argument with someone who does not (possibly involving mixed case), -I sincerely apologize. -``` - -The first line of every entry is interpreted as the entry's "secret." In this -case, the secret is `correct horse battery staple`, the password for the -account. This is usually a password or private key, but can be any value that -you might want to access by default. If this doesn't work for you for some -reason, no worries; just leave the line blank. - -The secret is followed by any number of optional field-value pairs. Every -field-value pair lives on its own line and can contain any information you want, -so long as it follows the format `FIELD: VALUE`. Fields can be repeated and in -any order. The only limitation is that your `FIELD` cannot contain a `: ` (`:` -followed by a space), but the `VALUE` can. - -There are no `FIELD`s with any special meaning (yet), but keeping them -consistent will help you find entries more quickly. I strongly recommend giving -each entry a `name` field, as this is what `ciphey` uses to search for entries -by default. - -Finally, the contents of the file from the first line that doesn't match the -pattern `FIELD: VALUE` down to the end of the file is left uninterpreted, -meaning that you can save any text that you'd like there. This is called the -"note." In the example above, the "note" is the caption text from -[xkcd.com/936](https://xkcd.com/936). Separate the notes and the preceding -section with a newline. - -### The Entries - -Your `ciphey` database is a folder of files that can live on any filesystem. -This folder is completely encrypted, and thus can safely be backed up, shared, -or otherwise accessed without any unauthorized party gaining access to the -contents of the file. - -``` -ciphey/ -└── entries/ - ├── age1sdnql3ksstj7krh7azddygh860f6uttus5t3e9j52t4k5z34kutqyzgr4e.age - ├── age1ryutmsg486w4y06kq7w0rqm2s08r3sgzlwcl9p9p00jducedevvqkgrvyw.age - ├── age1mqr5htmadgzlmcdjks79d6ucfe5k46ruavnaxm08m64lpl6h5udqhkwwvp.age - └── age1r908d20yj3ntp9q8g0448kwflfgf3au2qmhkkx7zp8xnesfdjfhqpd3r2d.age -``` - -Each file in the "entries" folder contains a single "entry." The name of each -file is the `age` public key the entry is encrypted to. Every entry into your -database is encrypted to a unique public key. Without that public key's -corresponding private key, the contents of the entry cannot be accessed. - -However, keep in mind that some metadata does leak. Namely, any data associated -with the filesystem (date created, date last modified, owner/group, etc.) is NOT -protected by `ciphey` by default. It's still a good idea to keep your database -away from any curious eyes when it's avoidable. - -### Your Keys - -Every time you unlock your `ciphey` database, you must have two things: - -1. Your `Primary Passphrase` (something you know) -2. A `Device Key` (something you have) - -Every "device" you have (i.e. your desktop, laptop, and phone) has its own -`Device Key`. This key is generated and stored as a normal file when you first -set up `ciphey` on the device, and never leaves it. - -Each `Device Key` is encrypted with your `Primary Passphrase`. Without your -`Primary Passphrase`, the `Device Key` cannot be used. - -Alternatively, you can use a `Device Key` stored on a hardware token, such as a -Yubikey or OnlyKey. This has the added benefit that the key material never -leaves the hardware token, protecting against attacks that can steal key -material from your computer's local disk. In order to decrypt your entries, an -attacker would have to physically have access your hardware token, in addition -to learning your `Primary Passphrase`. - -### Entry Keys - -Every entry in your database is encrypted to a specific `Entry Key`. These entry -keys are stored next to the `database` directory in the `keys` directory. Every -entry gets its own key so that access can be cryptographically restricted on an -entry-by-entry basis. - -The keys stored on the filesystem are encrypted to every `Device Key` that -you've given access to the entry. - -### Disaster Recovery - -When you set up your `ciphey` database for the first time, you'll be prompted to -create a `Recovery Key`, which is an `age` key encrypted with your `Recovery -Passphrase` (By default, your `Primary Passphrase`, but this can optionally be -changed). This key should be written down and stored in a safe place, such as in -a safe. This way, if you lose all of your devices, you can still regain access -to your passwords. - -You can also give a copy of this key and your `Recovery Passphrase` to anybody -else who should have access to your accounts in case of an emergency. This way, -you can be sure that you're unlikely to ever lose access to your `ciphey` keys. - -### Summary - -Every entry is encrypted with its own unique `Entry Key`. - -`Entry Key`s are encrypted to each `Device Key` that is granted access to the -entry. They can be encrypted to other people's `Device Key`s to share an entry -with them. - -`Device Key`s are encrypted with your `Primary Passphrase`. They can either live -on your filesystem or on a hardware token, like a Yubikey. - -When you first set up `ciphey`, you also create a `Recovery Key`, which every -`Entry Key` is encrypted to by default. This `Recovery Key` is encrypted with -your `Recovery Passphrase`, which are to be stored offline in a safe place -and/or given to trusted individuals so they can be used in case of an emergency. - -### Usage - -## Implementation - -### Entry Parsing - -The entry format was designed to be easy to parse for both humans and programs. -The following Rust snippet is a (simplified) example of parsing an Entry from a -String `s`: - -```rust -// The entry's secret -let mut secret: String; -// A vector of key/value pairs -let mut fields: (String, String) = Vec::new(); -// The entry's notes -let mut notes: Option = None; - -// An iterator over the decrypted lines of the entry file -let mut lines = s.lines(); - -// The first line contains the secret -secret = lines.next(); - -while let Some(line) = lines.by_ref().next() { - if let Some((key, value)) = line.split_once(": ") { - // Add the key and value to fields - fields.push((key, value)); - } else { - // Take the rest of the lines and put them into notes - notes = Some( - std::iter::once(line) - .chain(lines.by_ref()) - .collect::>() - .join("\n"), - ); - } -} -``` - -This particular implementation has a lot of room for improvement. The biggest -issue adding complexity is that Rust's `take_while` iterator method is -consuming, not peekable, meaning that ownership of the lines it checks is passed -to its closure. Thus, the following snippet, which is much easier to -read, would not work: - -```rust -// An iterator over the decrypted lines of the entry file -let mut lines = s.lines(); - -// The first line contains the secret -secret = lines.next(); - -// Take lines while they can be parsed as key/value pairs split by ": " -fields = lines.take_while(line.split_once(": ")).map(...); -// first line failing take_while is incorrectly dropped here - -// Join the remaining lines as notes -notes = lines.collect::>().join("\n"); -``` - -This is because even though the first line that fails the conditional is -consumed by `take_while`, it would neither be added to the fields (as it cannot -be parsed as one) nor collected into the vector over the lines of notes, instead -being dropped, causing data loss. - -There are a few Rust crates that provide a peekable `take_while`, but they're -too big to justify as adding as dependencies for just this feature. It's -possible that a simpler approach is possible using an iterative method, but I -have not been able to come up with one yet. - -## Remaining Work - -### Password History - -At the moment, there is no built-in support for keeping track of entry changes -over time. `pass` uses git to keep track of changes at the filesystem level, -while password managers like Bitwarden have built-in support for storing the -history of passwords over time. - -Currently, there is nothing stopping someone from manually checking entries into -git or another backup solution. However, one way to provide better integration -into `ciphey` would be to allow for `pre-hooks` and `post-hooks`. These hooks -are scripts that are run before or after specific actions are taken by `ciphey`. -This would allow, for example, automatically committing the changes to a git -repository and pushing those changes to a remote server after every change made -by `ciphey`. - -### File storage - -For the moment, entries must be plaintext files. If you want to encrypt an -arbitrary file with `ciphey`, you have to manually create an encryption key, -store that key as an entry in `ciphey`, and then manually encrypt said file with -the newly-created key. - -It would be beneficial to devise a way to treat encrypted files just like any -entry so that the key material for other files can be automatically managed in -the same way. - -### Backup - -While `ciphey` makes sure that you don't lose your secret key material through -the use of `Recovery Key`s, `ciphey` does not have any built-in backup system -for the encrypted `ciphey` database. Of course, you can still back up `ciphey` -like any other directory (which is a benefit of it living as just a plain -directory), but it may be useful to consider ways that `ciphey` can better -integrate or accomodate backups. diff --git a/content/projects/iso639/index.md b/content/projects/iso639/index.md deleted file mode 100644 index 6def5c9..0000000 --- a/content/projects/iso639/index.md +++ /dev/null @@ -1,19 +0,0 @@ -+++ -title = "iso639_enum" -weight = 4 -[taxonomies] -tags = [] -+++ - -`iso639_enum` is a small Rust crate I wrote for my Bamboo media server project. -ISO639 is a standard that enumerates world languages and provides two and three -character codes to represent them. This is important in the context of a media -server because any media in a particular language (basically anything with -spoken or written words) will represent its language in its metadata in some -form, usually as a two or three character language code. - -The documentation for the crate can be found at -[lib.rs/iso639_enum](https://lib.rs/iso639_enum). - -The repository for the crate can be found at -[git.nickzana.dev/nick/rust-iso639](https://git.nickzana.dev/nick/rust-iso639).