README.md (7264B)
1 MOSS - command-line password manager using age 2 3 Yes, it's yet another [pass](https://www.passwordstore.org/pass)-like 4 program that uses [age](https://github.com/FiloSottile/age) instead of 5 GPG, because it seemed like less effort to write one than to 6 understand the uses and limitations of anyone else's. I am not a 7 security professional, so the best offer I can make for its abilities 8 is that it *may* be OK. Hence the name "Maybe OK Secret Store"; c.f. 9 "Pretty Good Privacy", "Actually Good Encryption" 10 11 Status: pre-alpha, i don't use it for anything important yet and I 12 don't think you should either. 13 14 ## Installation 15 16 make install # defaults to /usr/local/bin 17 18 or 19 20 nix-env -i -f release.nix # for Nix users 21 22 `moss.rb` is a standalone Ruby file, so if neither of these approaches fits your needs, you could just copy it to anywhere on your search path 23 24 ## Setup 25 26 moss needs you to create an age identity that it will use to decrypt 27 your secrets. You can choose to protect this key with a passphrase, if 28 you have age 1.0.0-rc3 or later 29 30 $ age-keygen | age -p > key.age # password-protected key 31 $ age-keygen > key.age # key with no password (if you have FDE) 32 33 $ moss init key.age 34 35 $ moss git init # if you want to share it with other machines 36 $ moss git remote add me@githost.example.com:/home/git/passwords 37 38 moss keeps its secrets in 39 40 * `$MOSS_HOME/store`, if the MOSS_HOME environemt variable exists, or 41 * `$XDG_DATA_HOME/moss/store`, if the XDG_DATA_HOME environment variable exists, or 42 * `$HOME/.local/share/moss/store` : $HOME is assumed to exist 43 44 45 ## Storing a secret 46 47 $ echo 'supersekritpw' | moss add folder/secretname 48 [main 42f9587] new secret 49 1 file changed, 7 insertions(+) 50 create mode 100644 folder/secretname.age 51 52 If the store directory is managed by Git, `moss add` will add and 53 commit the new or changed secret to version control 54 55 ## Showing a secret 56 57 $ moss cat folder/secretname 58 supersekritpw 59 60 ## Listing or searching for secrets 61 62 $ moss list folder 63 folder/secretname 64 65 ## Sharing the secret store 66 67 By default, moss will encrypt secrets using the public key associated 68 with the identity you supplied when you ran `moss init` 69 70 * You can change the key, or add keys, by editing the `.recipients` 71 file in the store directory. This is an age recipient file, so may 72 contain "one or more recipients, one per line. Empty lines and lines 73 starting with "#" are ignored as comments." 74 75 * You can have different keys in different subtrees of the store by 76 creating `.recipients` files in those subtrees. The recipients file in 77 a subdirectory *overrides* the recipients in a parent directory - it 78 is not additive 79 80 * you can run [Git](https://git-scm.com/) commands on the store using 81 `moss git` - so use e.g. `moss git push origin` to push to a 82 previously configured git remote 83 84 To find your store directory, run `moss config` 85 86 87 ## Development 88 89 ### Prerequisites 90 91 moss is written in Ruby using only the standard library (no gems). 92 The test suite requires 93 [Cucumber](https://cucumber.io/docs/installation/ruby/) and [Rspec](https://rspec.info/). 94 95 On Nix, run `nix-shell` to download everything you need. On other 96 Unixlikes, you will need to install Ruby and run `bundle install` to 97 get cucumber and rspec gems 98 99 100 ### Running tests 101 102 The scenarios in [features/moss.feature](features/moss.feature) should 103 illustrate what it does: add, generate, edit, show a password, search 104 password names, etc. Run `cucumber`, or if you have `entr` installed, 105 you can use it to rerun tests whenever something changes. 106 107 make watch 108 109 If you need to edit the Gemfile, use `make gemset.nix` to regenerate 110 `gemset.nix` 111 112 113 ## Converting from pass 114 115 I don't suggest you do this, at least until moss is a bit more mature. I am 116 only writing this down because I figured out how to 117 118 cd $HOME/.password-store 119 for i in `find * -name \*.gpg` ;do ( gpg -d $i | moss add "${i%.*}" );done 120 121 ## Security considerations 122 123 Read this section with the caveat that this program has not been 124 reviewed by a security professional. I welcome feedback on any of the 125 points here, or on any other points that aren't here but should be. 126 127 The primary consideration with regard to threat modelling is that 128 moss encrypts and decrypts files using age, in much the same way as 129 you might otherwise invoke age by hand. If this doesn't fit your 130 security requirements, look elsewhere. 131 132 * secrets stored in moss depend on the security guarantees provided by 133 age. age is written by Filippo Valsorda, who is a real 134 cryptographer, so this is probably not the part you should be most 135 worried about 136 137 * moss expects that your `$MOSS_HOME` is kept on a local filesystem, 138 or at least that the file server is trusted and traffic to it can't 139 be tampered with. Secrets are not signed, so (I think) you cannot 140 detect when an attacker substitutes a secret other than the one you 141 asked for. 142 143 * if an attacker can read files on your computer, but you have 144 encrypted the private key, security of your secrets depends on the 145 strength of your passphrase and on their being no relevant bugs in age. 146 moss does not store or see your passphrase in this scenario: it runs 147 age as a subprocess which opens `/dev/tty` directly. 148 149 * if an attacker can read files on your computer and you have not 150 encrypted your private key, security of your secrets depends on 151 whether you are using an encrypted filesystem, the quality of that 152 filesystem and/or whether the attacker can gain access to it while 153 it's mounted. I believe that most Linux systems won't unmount it 154 while the screen is locked, for one. 155 156 * if an attacker can write files in your store, they can wipe out your 157 secrets or replace them with other ones, and you might not notice 158 (until you try using them, anyway) because secrets are not signed 159 160 * if you have any of: insecure buggy virtual keyboards, keystroke 161 loggers, cameras pointing at your keyboard, virtual hosts with 162 compromised hypervisors, then moss won't help you 163 164 * `pass edit` uses Ruby's Tempfile class to write a temporary 165 plaintext file containing the secret. According to the Ruby 166 documentation the "filename picking method is both thread-safe and 167 inter-process-safe", so can be relied on to be race-free. It creates 168 the file mode 0600. The file is deleted after the editor exits, but 169 will not be cleaned up if the moss process is killed while the 170 editor is running, 171 172 * all cryptographic operations are performed by running `age` in a 173 subprocess. Care has been taken to ensure it uses arrays instead 174 of interpolating values into strings which may give rise to shell 175 shell injection attacks 176 177 * the first time an encrypted identity is needed (i.e when reading a 178 secret), we create a temporary file using Tempfile, and unlink it 179 before running age to decrypt the secret into it. This is so that 180 `moss rebuild` prompts only once for the passphrase instead of once 181 per secret. moss does not read the decrypted file itself. 182 183 * reasonable care has been taken to set appropriate file permissions 184 on keys and secrets, so you should be good against other non-root 185 users on your machine 186 187 188 ## TO DO 189 190 * copy to clipboard 191 * warn or fail if iffy store permissions?