|
9 | 9 | [EDN](https://github.com/edn-format/edn) map, with arbitrary levels of |
10 | 10 | labeled nesting. |
11 | 11 |
|
12 | | - By default, the secrets file lives at .secrets.edn in the working directory, |
13 | | - but this path can be changed explicitly via `with-path` (or via the `:path` |
14 | | - flag at the command line)." |
| 12 | + The path used for the secrets file, in priority order, is one of: |
| 13 | +
|
| 14 | + - the one explicitly specified via `with-path` (or `:path` at the command |
| 15 | + line), |
| 16 | + - the `.secrets.edn` file in the working directory, or |
| 17 | + - the `.secrets.edn` file in the home directory." |
15 | 18 | (:require [buddy.core.codecs :as codecs] |
16 | 19 | [buddy.core.nonce :as nonce] |
17 | 20 | [buddy.core.crypto :as crypto] |
|
27 | 30 | (set! *warn-on-reflection* true) |
28 | 31 |
|
29 | 32 |
|
30 | | -(def ^:dynamic *path* |
31 | | - "Location of saved secrets on disk." |
32 | | - ".secrets.edn") |
| 33 | +(defn default-secrets-path [] |
| 34 | + (if (.exists (io/file ".secrets.edn")) |
| 35 | + ".secrets.edn" |
| 36 | + (let [home (System/getProperty "user.home")] |
| 37 | + (.getCanonicalPath (io/file home ".secrets.edn"))))) |
33 | 38 |
|
34 | 39 |
|
| 40 | +(def ^:dynamic *path* "Explicitly bound path." nil) |
35 | 41 | (defmacro with-path |
36 | 42 | "Set the file path used for saved secrets." |
37 | 43 | [path & body] |
38 | 44 | `(binding [*path* ~path] |
39 | 45 | ~@body)) |
40 | 46 |
|
41 | 47 |
|
| 48 | +(defn secrets-path |
| 49 | + "Location of saved secrets on disk." |
| 50 | + [] |
| 51 | + (or *path* (default-secrets-path))) |
| 52 | + |
| 53 | + |
42 | 54 | ;;; Primitives for key stretching & encryption |
43 | 55 |
|
44 | 56 |
|
|
185 | 197 | (defn read-secrets |
186 | 198 | "Prefer `with-secrets`." |
187 | 199 | [] |
188 | | - (if (.isFile (io/file *path*)) |
189 | | - (let [p (or *password* (read-password "Password: "))] |
190 | | - {:data (decrypt-from-disk {:password p :path *path*}) |
191 | | - :password p}) |
192 | | - {:data {} |
193 | | - :password nil})) |
| 200 | + (let [path (secrets-path)] |
| 201 | + (if (.isFile (io/file path)) |
| 202 | + (let [p (or *password* (read-password (str "Password for " path ": ")))] |
| 203 | + {:data (decrypt-from-disk {:password p :path path}) |
| 204 | + :password p}) |
| 205 | + {:data {} |
| 206 | + :password nil}))) |
194 | 207 |
|
195 | 208 |
|
196 | 209 | (defn write-secrets |
197 | 210 | "Prefer `swap-secrets!`." |
198 | 211 | [{:keys [data password]}] |
199 | 212 | (print "Encrypting data for writing...") |
200 | 213 | (flush) |
201 | | - (let [enc (encrypt-to-disk data {:password password :path *path*})] |
| 214 | + (let [path (secrets-path) |
| 215 | + enc (encrypt-to-disk data {:password password :path path})] |
202 | 216 | (println " Done.") |
203 | | - (println "Wrote" (count (.getBytes (prn-str enc))) "bytes.") |
| 217 | + (println "Wrote" (count (.getBytes (prn-str enc))) "bytes to" (str path ".")) |
204 | 218 | enc)) |
205 | 219 |
|
206 | 220 |
|
|
259 | 273 | (defn rand-n [coll n] (repeatedly n #(nth coll (rng-int (count coll))))) |
260 | 274 | (def passphrase |
261 | 275 | (let [words (string/split-lines (slurp "/usr/share/dict/words"))] |
262 | | - (string/join " " (rand-n words 6)))) |
| 276 | + (string/join " " (rand-n words 5)))) |
263 | 277 |
|
264 | 278 | ;; Encrypt some data with the passphrase to send to somebody else |
265 | 279 | (encrypt (prn-str {:foo :bar}) passphrase) |
|
0 commit comments