Recent changes to this wiki:

fix url
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 72d7e61..334df3b 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -143,7 +143,7 @@ source of disk IO.
 
 It's early days still, but keysafe's server code works well enough.
 
-* `git clone git://git.joeyh.name/code/keysafe`
+* `git clone git://git.joeyh.name/keysafe`
 * Be sure to verify the gpg signature of the git repository!
 * You will need to install keysafe from source; see its INSTALL file.
   Use `make install` to install it, including a systemd service file.

blog update
diff --git a/blog/entry/keysafe_beta_release.mdwn b/blog/entry/keysafe_beta_release.mdwn
new file mode 100644
index 0000000..b09deb2
--- /dev/null
+++ b/blog/entry/keysafe_beta_release.mdwn
@@ -0,0 +1,25 @@
+After a month of development, [[code/keysafe]] 0.20160922 is released, 
+and ready for beta testing. And it needs servers.
+
+With this release, the whole process of backing up and restoring a gpg
+secret key to keysafe servers is implemented. Keysafe is started at desktop
+login, and will notice when a gpg secret key has been created, and prompt
+to see if it should back it up.
+
+At this point, I recommend only using keysafe for lower-value secret keys,
+for several reasons:
+
+* There could be some bug that prevents keysafe from restoring a backup.
+* Keysafe's design has not been completely reviewed for security.
+* None of the keysafe servers available so far or planned to be deployed
+  soon meet all of the security requirements for a recommended keysafe server.
+  While server security is only the initial line of defense, it's still
+  important.
+
+Currently the only keysafe server is one that I'm running myself.
+Two more keysafe servers are needed for keysafe to really be usable,
+and I can't run those.
+
+If you're interested in running a keysafe server, read
+[[the_keysafe_server_requirements|code/keysafe/servers]]
+and get in touch.

update
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 579a55d..72d7e61 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -130,7 +130,9 @@ Each key takes a minimum of 64 KiB to store, perhaps more for gpg keys
 with lots of signatures. So 10 GiB of disk is sufficient for 160 thousand
 users, which is enough for a small keysafe server.
 
-The keysafe server uses very little memory and CPU.
+The keysafe server uses very little memory and CPU. It does rate limiting
+with client-side proof-of-work to prevent it being abused for
+general-purpose data storage.
 
 There is some disk IO overhead, because keysafe updates the mtime and ctime
 of all shards stored on the server, as frequently as every 30 minutes.
@@ -141,7 +143,7 @@ source of disk IO.
 
 It's early days still, but keysafe's server code works well enough.
 
-* git clone keysafe
+* `git clone git://git.joeyh.name/code/keysafe`
 * Be sure to verify the gpg signature of the git repository!
 * You will need to install keysafe from source; see its INSTALL file.
   Use `make install` to install it, including a systemd service file.
@@ -153,5 +155,5 @@ It's early days still, but keysafe's server code works well enough.
 * Once ready, email id@joeyh.name to get added to keysafe's server list.
 
 Here's a the [[code/propellor]] config for my own keysafe server:
-<http://source.propellor.branchable.com/?p=source.git;a=blob;f=joeyconfig.hs;h=fa37e97ba94eecf8f4cbe47d41fbc7c1cd89723b;hb=HEAD#l461>
+<http://source.propellor.branchable.com/?p=source.git;a=blob;f=joeyconfig.hs;h=15a00f7c2dffa15ed275fdd44e84e2edcc226559;hb=b9f87f0c08d94c5d43224a2c6bbacb332ebfc1b6#l460>
 --[[Joey]]

add news item for keysafe 0.20160922
diff --git a/code/keysafe/news/version_0.20160922.mdwn b/code/keysafe/news/version_0.20160922.mdwn
new file mode 100644
index 0000000..0cf5ac8
--- /dev/null
+++ b/code/keysafe/news/version_0.20160922.mdwn
@@ -0,0 +1,17 @@
+keysafe 0.20160922 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Keysafe now knows about 3 servers, although only 1 is currently in
+     operation. It will queue uploads to the other 2 servers until
+     they are added in a later keysafe release.
+   * Added --autostart mode, and make both keysafe --backup and
+     the Makefile install a FDO desktop autostart file to use it.
+   * In --autostart mode, retry any queued uploads.
+   * In --autostart mode, check for gpg keys that have not been
+     backed up, and offer to back them up. Only ask once per key.
+   * Changed format of ~/.keysafe/backup.log
+   * Server: Reduce number of buckets in rate limiter, avoiding ones with very low
+     proof of work.
+   * Server: Make rate limiter adapt to ongoing load more quickly -- every 15
+     minutes instead of every 60.
+   * Server: Added --backup-server and --restore-server to aid in backing
+     up keysafe servers with minimal information leakage."""]]
\ No newline at end of file

let's not mix
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 7c5c755..579a55d 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -80,10 +80,8 @@ lhmhvShr0WRqB8fWYPkc
 ### Alternate
 
 * Keysafe port only exposed via tor hidden service.
-* Dedicated to only running keysafe, no other services. (Other than ssh for
-  admin) (Since it's running tor, it's also ok to be a tor bridge, or
-  relay; this way unused bandwidth benefits the tor network. However, see
-  [here](https://trac.torproject.org/projects/tor/ticket/8742).)
+* Dedicated to only running keysafe, no other services. (Other than tor and 
+  ssh for admin)
 * The set of people who administer the server, and procedures for giving
   others access is well-defined.
 * Noone who has access to the server also has access to any Recommended

note
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index cff7c90..7c5c755 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -82,7 +82,8 @@ lhmhvShr0WRqB8fWYPkc
 * Keysafe port only exposed via tor hidden service.
 * Dedicated to only running keysafe, no other services. (Other than ssh for
   admin) (Since it's running tor, it's also ok to be a tor bridge, or
-  relay; this way unused bandwidth benefits the tor network.)
+  relay; this way unused bandwidth benefits the tor network. However, see
+  [here](https://trac.torproject.org/projects/tor/ticket/8742).)
 * The set of people who administer the server, and procedures for giving
   others access is well-defined.
 * Noone who has access to the server also has access to any Recommended

update
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index af743f2..cff7c90 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -100,17 +100,14 @@ lhmhvShr0WRqB8fWYPkc
   It may be better to run some servers without backups and adjust the
   number of shards needed to recover keys; a server losing its data
   need not be catastrophic.)
-* Any backup does not record the whole history of the /var/lib/keysafe
-  directory. Doing so interferes with keysafe's obscuring of when shards
-  were stored on the server.
-
-  It may be useful to keep some old versions of /var/lib/keysafe so that
-  if files get accidentially deleted, they can be recovered. For example,
-  one version for each of the past 7 days, and past 4 weeks.
-  But bear in mind that this lets anyone who can access those backups
-  make guesses about what shares belong with other shares stored on other
-  servers in the same time period. See [[details]] for how that makes it 
-  somewhat easier for an attacker.
+* Any backup should take care to not leak information about what objects
+  were present on the server at multiple times in the past. That would 
+  let an attacker who can access the backups make guesses about shares
+  belong with other shares stored on other servers in the same time period.
+  See [[details]] for how that makes it somewhat easier for an attacker.
+
+  keysafe --backup-server can be used to generate encrypted files to back up,
+  in a way that is designed to avoid these problems.
 
 * Similarly, the filesystem and storage system should not allow rolling back
   to old snapshots.

more on incremental backups
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 6fdf95c..af743f2 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -100,9 +100,18 @@ lhmhvShr0WRqB8fWYPkc
   It may be better to run some servers without backups and adjust the
   number of shards needed to recover keys; a server losing its data
   need not be catastrophic.)
-* Any backup is *not* incremental. Incremental backups interfere with
-  keysafe's obscuring of when shards were stored on the server, and can
-  be used in correlation attacks.
+* Any backup does not record the whole history of the /var/lib/keysafe
+  directory. Doing so interferes with keysafe's obscuring of when shards
+  were stored on the server.
+
+  It may be useful to keep some old versions of /var/lib/keysafe so that
+  if files get accidentially deleted, they can be recovered. For example,
+  one version for each of the past 7 days, and past 4 weeks.
+  But bear in mind that this lets anyone who can access those backups
+  make guesses about what shares belong with other shares stored on other
+  servers in the same time period. See [[details]] for how that makes it 
+  somewhat easier for an attacker.
+
 * Similarly, the filesystem and storage system should not allow rolling back
   to old snapshots.
 

allow servers to also run as tor bridges etc
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 554d893..6fdf95c 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -80,8 +80,9 @@ lhmhvShr0WRqB8fWYPkc
 ### Alternate
 
 * Keysafe port only exposed via tor hidden service.
-* Dedicated to only running keysafe, no other services (other than ssh for
-  admin)
+* Dedicated to only running keysafe, no other services. (Other than ssh for
+  admin) (Since it's running tor, it's also ok to be a tor bridge, or
+  relay; this way unused bandwidth benefits the tor network.)
 * The set of people who administer the server, and procedures for giving
   others access is well-defined.
 * Noone who has access to the server also has access to any Recommended

add news item for keysafe 0.20160914
diff --git a/code/keysafe/news/version_0.20160914.mdwn b/code/keysafe/news/version_0.20160914.mdwn
new file mode 100644
index 0000000..9b0dcd1
--- /dev/null
+++ b/code/keysafe/news/version_0.20160914.mdwn
@@ -0,0 +1,21 @@
+keysafe 0.20160914 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Fix bug that prevented keysafe --server from running when there was no
+     controlling terminal and zenity was not installed.
+   * Added --name and --othername options.
+   * Added proof of work to client/server protocol.
+   * Server-side rate limiting and DOS protection.
+   * server: Added --months-to-fill-half-disk option, defaulting to 12.
+   * Several new dependencies.
+   * Another fix to gpg secret key list parser.
+   * Warn when uploads fail and are put in the upload queue.
+   * Warn when --uploadqueued fails to upload to servers.
+   * Fix --uploadqueued bug that prevented deletion of local queued file.
+   * Added --chaff mode which uploads random junk to servers.
+     This is useful both to test the server throttling of uploads,
+     and to make it harder for servers to know if an object actually
+     contains secret key information.
+   * Store information about backed up keys in ~/.keysafe/backup.log
+     This can be deleted by the user at any time, but it's useful
+     in case a server is known to be compromised, or a problem is found
+     with keysafe's implementation that makes a backup insecure."""]]
\ No newline at end of file

comment
diff --git a/blog/entry/PoW_bucket_bloom/comment_7_266728691c8dc55601cdcf589a4afbd6._comment b/blog/entry/PoW_bucket_bloom/comment_7_266728691c8dc55601cdcf589a4afbd6._comment
new file mode 100644
index 0000000..13ffc9e
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom/comment_7_266728691c8dc55601cdcf589a4afbd6._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 7"""
+ date="2016-09-14T01:14:15Z"
+ content="""
+Another bonus to using HMAC is that a large/distributed keysafe server cluster's
+nodes can all share the secret used to generate a request id, and then any
+node will accept a request id that was produced by any node. So that might
+be very useful in future scaling. Thanks for the help improving that part
+of this!
+"""]]

update
diff --git a/blog/entry/PoW_bucket_bloom/comment_6_5c7ef854b7164100cfa05df2a60ac862._comment b/blog/entry/PoW_bucket_bloom/comment_6_5c7ef854b7164100cfa05df2a60ac862._comment
index f3cbced..e25b393 100644
--- a/blog/entry/PoW_bucket_bloom/comment_6_5c7ef854b7164100cfa05df2a60ac862._comment
+++ b/blog/entry/PoW_bucket_bloom/comment_6_5c7ef854b7164100cfa05df2a60ac862._comment
@@ -5,4 +5,13 @@
  content="""
 SYN cookies rely on knowing the client's IP address. Keysafe, as a TOR hidden
 service, does not have such a means to distinguish clients.
+
+But, SYN cookie's use of a cryptographic hash makes me think of an HMAC.
+Could generate a request ID by `(hmac secret random, random)`. Then the
+server can verify incoming request IDs using the secret.
+
+That does seem to be simple enough to be worth implementing, to get rid of
+that first bloom filter. Thanks guys!
+
+"mac PoW bucket bloom"? :)
 """]]

comment
diff --git a/blog/entry/PoW_bucket_bloom/comment_6_5c7ef854b7164100cfa05df2a60ac862._comment b/blog/entry/PoW_bucket_bloom/comment_6_5c7ef854b7164100cfa05df2a60ac862._comment
new file mode 100644
index 0000000..f3cbced
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom/comment_6_5c7ef854b7164100cfa05df2a60ac862._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 6"""
+ date="2016-09-13T23:57:12Z"
+ content="""
+SYN cookies rely on knowing the client's IP address. Keysafe, as a TOR hidden
+service, does not have such a means to distinguish clients.
+"""]]

Added a comment
diff --git a/blog/entry/PoW_bucket_bloom/comment_5_2d23a1fba91fedac5761196d26d7b211._comment b/blog/entry/PoW_bucket_bloom/comment_5_2d23a1fba91fedac5761196d26d7b211._comment
new file mode 100644
index 0000000..8164abb
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom/comment_5_2d23a1fba91fedac5761196d26d7b211._comment
@@ -0,0 +1,7 @@
+[[!comment format=mdwn
+ username="mju"
+ subject="comment 5"
+ date="2016-09-13T23:23:48Z"
+ content="""
+Just a suggestion: Maybe something like the technique for syn cookies works better and faster than asymmetric cryptography.
+"""]]

update
diff --git a/blog/entry/PoW_bucket_bloom.mdwn b/blog/entry/PoW_bucket_bloom.mdwn
index 585dcb2..91b91fe 100644
--- a/blog/entry/PoW_bucket_bloom.mdwn
+++ b/blog/entry/PoW_bucket_bloom.mdwn
@@ -30,10 +30,12 @@ necessary. At the worst, a client may have to do 8-16 minutes of work to
 access a keysafe server that is under heavy load, which would not be ideal,
 but is acceptible for keysafe since it's not run very often.
 
-(If the client provides a PoW good enough to allow accessing the last token
+If the client provides a PoW good enough to allow accessing the last token
 bucket, the request will be accepted even when that bucket is drained. The
 client has done plenty of work at this point, so it would be annoying to
-reject it.)
+reject it. To prevent an attacker that is willing to burn CPU from abusing
+this loophole to flood the server with object stores, the server delays
+until the last token bucket fills back up.
 
 ----
 
@@ -81,7 +83,7 @@ will have plenty of time to complete its proof of work.
 This sounds complicated, and probably it is, but the implementation only
 took 333 lines of code. About the same number of lines that it took to
 implement the entire keysafe HTTP client and server using the amazing
-[servant](http://hackage.haskell.org/package/servant) library. 
+[servant](http://hackage.haskell.org/package/servant) library.
 
 There are a number of knobs that may need to be tuned to dial it in,
 including the size of the token buckets, their refill rate, the size of the
@@ -90,3 +92,10 @@ Servers may eventually need to adjust those on the fly, so that if someone
 decides it's worth burning large quantities of CPU to abuse keysafe for
 general data storage, the server throttles down to a rate that will take
 a very long time to fill up its disk.
+
+This protects against DOS attacks that fill up the keysafe server storage.
+It does not prevent a determined attacker, who has lots of CPU to burn,
+from flooding so many requests that legitimate clients are forced to do
+an expensive proof of work and then time out waiting for the server. But
+that's an expensive attack to keep running, and the proof of work can 
+be adjusted to make it increasingly expensive.

simplify
diff --git a/blog/entry/PoW_bucket_bloom/comment_4_c05ea3d9d10d17337c54227432377203._comment b/blog/entry/PoW_bucket_bloom/comment_4_c05ea3d9d10d17337c54227432377203._comment
index fc3ca90..b110b70 100644
--- a/blog/entry/PoW_bucket_bloom/comment_4_c05ea3d9d10d17337c54227432377203._comment
+++ b/blog/entry/PoW_bucket_bloom/comment_4_c05ea3d9d10d17337c54227432377203._comment
@@ -3,29 +3,5 @@
  subject="""comment 3"""
  date="2016-09-13T16:48:56Z"
  content="""
-Also, I found another use for the meta-token-bucket, as Josh calls it.
-
-Recall that, if a client provides a maximum size proof of work, it's always
-allowed to store data. This forgiveness of the last token bucket being
-drained is nice, but also problimatic.
-
-A determined attacker, who is willing to burn enough CPU (probably hundreds
-or thousands of CPUS) can flood in requests that all have maximum PoW. Such
-an attacker could pretty quickly fill up the keysafe server storage.
-That wouldn't be economical for data storage, but it would be economical to
-DOS keysafe.
-
-The meta-token-bucket though, can be tuned to guard against that.
-The keysafe server can delay generating request IDs when it's empty,
-and so throttle back such an attacker. The refill rate can be tuned
-to be such that such an attack can't store any more data than would be
-stored if keysafe didn't always accept maximum sized PoW.
-
-The meta-token-bucket can have a high burst size (tends to hundreds
-of thousands of tokens), and refill somewhat slowly (eg one token per
-minute) and so not cause any delays except for in such a DOS scenario.
-
-----
-
-(Oh yeah, asymetric crypto would be the way to go.)
+Oh yeah, asymetric crypto would be the way to go.
 """]]

comment
diff --git a/blog/entry/PoW_bucket_bloom/comment_3_c05ea3d9d10d17337c54227432377203._comment b/blog/entry/PoW_bucket_bloom/comment_3_c05ea3d9d10d17337c54227432377203._comment
deleted file mode 100644
index 9ff8c1e..0000000
--- a/blog/entry/PoW_bucket_bloom/comment_3_c05ea3d9d10d17337c54227432377203._comment
+++ /dev/null
@@ -1,25 +0,0 @@
-[[!comment format=mdwn
- username="joey"
- subject="""comment 3"""
- date="2016-09-13T16:48:56Z"
- content="""
-Also, I found another use for the meta-token-bucket, as Josh calls it.
-
-Recall that, if a client provides a maximum size proof of work, it's always
-allowed to store data. This forgiveness of the last token bucket being
-drained is "nice", but also problimatic.
-
-A determined attacker, who is willing to burn enough CPU (probably hundreds
-or thousands of CPUS) can flood in requests that all have maximum PoW. Such
-an attacker could pretty quickly fill up the keysafe server storage.
-
-The meta-token-bucket though, can be tuned to guard against that.
-The keysafe server can delay generating request IDs when it's empty,
-and so throttle back such an attacker. The refill rate can be tuned
-to be such that such an attack doesn't store any more data than would be
-stored if keysafe didn't always accept maximum sized PoW.
-
-The meta-token-bucket can have a high burst size (tends to hundreds
-of thousands of tokens), and refill somewhat slowly (eg one token per
-minute) and so not cause any delays except for in such a DOS scenario.
-"""]]
diff --git a/blog/entry/PoW_bucket_bloom/comment_4_c05ea3d9d10d17337c54227432377203._comment b/blog/entry/PoW_bucket_bloom/comment_4_c05ea3d9d10d17337c54227432377203._comment
new file mode 100644
index 0000000..fc3ca90
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom/comment_4_c05ea3d9d10d17337c54227432377203._comment
@@ -0,0 +1,31 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2016-09-13T16:48:56Z"
+ content="""
+Also, I found another use for the meta-token-bucket, as Josh calls it.
+
+Recall that, if a client provides a maximum size proof of work, it's always
+allowed to store data. This forgiveness of the last token bucket being
+drained is nice, but also problimatic.
+
+A determined attacker, who is willing to burn enough CPU (probably hundreds
+or thousands of CPUS) can flood in requests that all have maximum PoW. Such
+an attacker could pretty quickly fill up the keysafe server storage.
+That wouldn't be economical for data storage, but it would be economical to
+DOS keysafe.
+
+The meta-token-bucket though, can be tuned to guard against that.
+The keysafe server can delay generating request IDs when it's empty,
+and so throttle back such an attacker. The refill rate can be tuned
+to be such that such an attack can't store any more data than would be
+stored if keysafe didn't always accept maximum sized PoW.
+
+The meta-token-bucket can have a high burst size (tends to hundreds
+of thousands of tokens), and refill somewhat slowly (eg one token per
+minute) and so not cause any delays except for in such a DOS scenario.
+
+----
+
+(Oh yeah, asymetric crypto would be the way to go.)
+"""]]

comment
diff --git a/blog/entry/PoW_bucket_bloom/comment_3_c05ea3d9d10d17337c54227432377203._comment b/blog/entry/PoW_bucket_bloom/comment_3_c05ea3d9d10d17337c54227432377203._comment
new file mode 100644
index 0000000..9ff8c1e
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom/comment_3_c05ea3d9d10d17337c54227432377203._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 3"""
+ date="2016-09-13T16:48:56Z"
+ content="""
+Also, I found another use for the meta-token-bucket, as Josh calls it.
+
+Recall that, if a client provides a maximum size proof of work, it's always
+allowed to store data. This forgiveness of the last token bucket being
+drained is "nice", but also problimatic.
+
+A determined attacker, who is willing to burn enough CPU (probably hundreds
+or thousands of CPUS) can flood in requests that all have maximum PoW. Such
+an attacker could pretty quickly fill up the keysafe server storage.
+
+The meta-token-bucket though, can be tuned to guard against that.
+The keysafe server can delay generating request IDs when it's empty,
+and so throttle back such an attacker. The refill rate can be tuned
+to be such that such an attack doesn't store any more data than would be
+stored if keysafe didn't always accept maximum sized PoW.
+
+The meta-token-bucket can have a high burst size (tends to hundreds
+of thousands of tokens), and refill somewhat slowly (eg one token per
+minute) and so not cause any delays except for in such a DOS scenario.
+"""]]

Added a comment
diff --git a/blog/entry/PoW_bucket_bloom/comment_3_610123f7b53662d2d9be2d24cf597477._comment b/blog/entry/PoW_bucket_bloom/comment_3_610123f7b53662d2d9be2d24cf597477._comment
new file mode 100644
index 0000000..c2370bb
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom/comment_3_610123f7b53662d2d9be2d24cf597477._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="josh@ccccabe84317e1b7429fd465de0b38fd54925dea"
+ nickname="josh"
+ subject="comment 3"
+ date="2016-09-13T16:51:45Z"
+ content="""
+I was thinking of asymmetric crypto, but yeah, using additional crypto does mean much more careful analysis.
+"""]]

comment
diff --git a/blog/entry/PoW_bucket_bloom/comment_2_b8c8bfe5e23ef4ea28460f7872ab1d4f._comment b/blog/entry/PoW_bucket_bloom/comment_2_b8c8bfe5e23ef4ea28460f7872ab1d4f._comment
new file mode 100644
index 0000000..5220de0
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom/comment_2_b8c8bfe5e23ef4ea28460f7872ab1d4f._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2016-09-13T16:10:27Z"
+ content="""
+That is indeed a good idea Josh. If the bloom filter memory
+use ever comes to be a problem that would be a good way to at half it.
+
+It does add a fair bit of complexit. So many gotchas involved in
+using AES. Reusing an IV might allow key recovery attacks..
+
+The 64 mb or so that would be freed is probably going to be peanuts on the
+average keysafe server (even if it's a fairly low-spec arm box), since
+they're supposed to be bare-metal servers only running keysafe.
+"""]]

Added a comment: Signed tokens?
diff --git a/blog/entry/PoW_bucket_bloom/comment_1_5b3479923bddc661d27a7c2482df9316._comment b/blog/entry/PoW_bucket_bloom/comment_1_5b3479923bddc661d27a7c2482df9316._comment
new file mode 100644
index 0000000..000ee94
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom/comment_1_5b3479923bddc661d27a7c2482df9316._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="josh@ccccabe84317e1b7429fd465de0b38fd54925dea"
+ nickname="josh"
+ subject="Signed tokens?"
+ date="2016-09-13T07:39:44Z"
+ content="""
+To avoid having to store not-yet-used request IDs even in a bloom filter, what about signing them using a server key, handing them to the client, and then throwing them away?  You can verify when you get the request ID back that it has a valid signature, so you've effectively let the client store it for you, indefinitely.
+
+You'd still need the mechanism to remember *used* request IDs to avoid reuse, but you wouldn't have to store unused request IDs, which reduces memory usage and potentially avoids the need for the meta-token-bucket for request IDs.
+"""]]

blog
diff --git a/blog/entry/PoW_bucket_bloom.mdwn b/blog/entry/PoW_bucket_bloom.mdwn
new file mode 100644
index 0000000..585dcb2
--- /dev/null
+++ b/blog/entry/PoW_bucket_bloom.mdwn
@@ -0,0 +1,92 @@
+[[!meta title="PoW bucket bloom: throttling anonymous clients with proof of work, token buckets, and bloom filters"]]
+
+An interesting side problem in [[code/keysafe]]'s design is that keysafe
+servers, which run as tor hidden services, allow anonymous data storage and
+retrieval. While each object is limited to 64 kb, what's to stop someone
+from making many requests and using it to store some big files?
+
+The last thing I want is a [[code/git-annex]] keysafe special remote. ;-)
+
+I've done a mash-up of three technologies to solve this,
+that I think is perhaps somewhat novel. Although it could be entirely old
+hat, or even entirely broken. (All I know so far is that the code
+compiles.) It uses proof of work, token buckets, and bloom filters.
+
+----
+
+Each request can have a proof of work attached to it, which is just a value
+that, when hashed with a salt, starts with a certain number of 0's.
+The salt includes the ID of the object being stored or retrieved.
+
+The server maintains a list of token buckets. The first can be accessed
+without any proof of work, and subsequent ones need progressively more
+proof of work to be accessed.
+
+Clients will start by making a request without a PoW, and that will often
+succeed, but when the first token bucket is being drained too fast by other
+load, the server will reject the request and demand enough proof of work
+to allow access to the second token bucket. And so on down the line if
+necessary. At the worst, a client may have to do 8-16 minutes of work to
+access a keysafe server that is under heavy load, which would not be ideal,
+but is acceptible for keysafe since it's not run very often.
+
+(If the client provides a PoW good enough to allow accessing the last token
+bucket, the request will be accepted even when that bucket is drained. The
+client has done plenty of work at this point, so it would be annoying to
+reject it.)
+
+----
+
+So far so simple really, but this has a big problem: What prevents a proof
+of work from being reused? An attacker could generate a single PoW good
+enough to access all the token buckets, and flood the server with requests
+using it, and so force everyone else to do excessive amounts of work to use
+the server.
+
+Guarding against that DOS is where the bloom filters come in. The server
+generates a random request ID, which has to be included in the PoW salt and
+sent back by the client along with the PoW. The request ID is added to a
+bloom filter, which the server can use to check if the client is providing
+a request ID that it knows about. And a second bloom filter is used to
+check if a request ID has been used by a client before, which prevents the
+DOS.
+
+Of course, when dealing with bloom filters, it's important to consider what
+happens when there's a rare false positive match. This is not a problem with
+the first bloom filter, because a false positive only lets some made-up
+request ID be used. A false positive in the second bloom filter will cause
+the server to reject the client's proof of work. But the server can just
+request more work, or send a new request ID, and the client will follow
+along.
+
+The other gotcha with bloom filters is that filling them up too far
+sets too many bits, and so false positive rates go up. To deal with this,
+keysafe just keeps count of how many request IDs it has generated, and once
+it gets to be too many to fit in a bloom filter, it makes a new, empty
+bloom filter and starts storing request IDs in it. The old bloom filter is
+still checked too, providing a grace period for old request IDs to be used.
+Using bloom filters that occupy around 32 mb of RAM, this rotation
+only has to be done every million requests of so.
+
+But, that rotation opens up another DOS! An attacker could cause lots of
+request IDs to be generated, and so force the server to rotate its bloom
+filters too quickly, which would prevent any requests from being accepted.
+To solve this DOS, just use one more token bucket, to limit the rate
+that request IDs can be generated, so that the time it would take an
+attacker to force a bloom filter rotation is long enough that any client
+will have plenty of time to complete its proof of work.
+
+----
+
+This sounds complicated, and probably it is, but the implementation only
+took 333 lines of code. About the same number of lines that it took to
+implement the entire keysafe HTTP client and server using the amazing
+[servant](http://hackage.haskell.org/package/servant) library. 
+
+There are a number of knobs that may need to be tuned to dial it in,
+including the size of the token buckets, their refill rate, the size of the
+bloom filters, and the number of argon2 iterations in the proof of work.
+Servers may eventually need to adjust those on the fly, so that if someone
+decides it's worth burning large quantities of CPU to abuse keysafe for
+general data storage, the server throttles down to a rate that will take
+a very long time to fill up its disk.

better DOS protection with bloom filters
diff --git a/code/keysafe/details.mdwn b/code/keysafe/details.mdwn
index aafc9b2..4b18e32 100644
--- a/code/keysafe/details.mdwn
+++ b/code/keysafe/details.mdwn
@@ -197,18 +197,15 @@ DOS attacks.
 
 Assuming that the client communicates with the server over http:
 
-	PUT /keysafe/objects/N?S
-	GET /keysafe/objects/N?S
+	PUT /keysafe/objects/N
+	GET /keysafe/objects/N
 
 The server's response can be either the result of the request,
 or a proof of work requirement, which specifies the difficulty D 
-(number of 0's needed), random value R, and the number of argon2
-iterations. The client provides the proof of work in S, which is a 
-string such that argon2(N,S+R) starts with a given number of 0's.
-
-The random value R is picked when the server starts up, and may be changed
-from time to time. It prevents a client from reusing proofs of work 
-between servers, and is also useful to mitigate DOS attacks.
+(number of 0's needed), random salt RS, and the number of argon2
+iterations. The client provides the proof of work in a query parameter,
+which is a string S such that argon2(N,S+RS) starts with a given number
+of 0's.
 
 (The server should only be able to control the number of iterations,
 not other argon2 parameters, to avoid forcing the client to use too much
@@ -230,18 +227,18 @@ token every minute, then the maximum allowed throughput is 4 requests
 per minute. If calculating the proof of work takes 2^D seconds on average, 
 then it will take on average 16 minutes work to access B4.
 
-Since this scheme is stateless, it lets an attacker do work once for a
-given N and then flood the server with repeated requests for N?S, reusing the
-proof of work. This is a DOS because the attacker can keep all the token
-buckets drained and so not let legitimate requests through. But, the server
-can detect when this DOS is occurring (when a proof of work allows
-accessing the last token bucket, and the bucket is empty), and pick a new R
-(and also perhaps increase the number of argon2 iterations to make the PoW
-a little bit harder). This invalidates the attacker's cached proof of work,
-and gives other clients a chance to get some requests through while the
-attacker is generating new proofs of work for the new R. Another defense
-against this attack is for the server to keep a small cache of recent N's
-(expiring after an hour) and reject repeated requests for them.
+The server can generate a different RS for each request, and can
+insert them into a bloom filter to keep track of ones it has given out.
+Bloom filter false positives are not a problem because they are quite
+rare and so it is not efficient for a client to make up RS in hope that
+there will be a false positive.
+
+To guard against DOS attacks that reuse proofs of work, the server can
+maintain a second bloom filter, putting RS into it once it's used, and
+rejecting attempts that reuse a RS. Since the bloom filter will
+(with a low probability) yield a false positive, the server should reject
+an attempt by generating a new RS' and requesting a new proof of work from
+the client.
 
 ## Avoiding correlations
 

better PoW design
diff --git a/code/keysafe/details.mdwn b/code/keysafe/details.mdwn
index 925c16d..aafc9b2 100644
--- a/code/keysafe/details.mdwn
+++ b/code/keysafe/details.mdwn
@@ -18,7 +18,7 @@
 * Servers reject attempts to store an object under a name that is
   already in use.
 * Servers do not allow enumerating all objects stored,
-  and require a proof of work client puzzle to handle any request.
+  and require a proof of work to handle any request.
 * Upload S1-S3 to separate servers under the names N1-N3.
   If any of the uploads is rejected as name already in use, 
   ask user to enter a different name or password.
@@ -72,7 +72,7 @@ choose a strong password. A name that attackers are unlikely to guess
 prevents this attack, which is why keysafe prompts for not only the
 user's name, but also a more obscure name. Each name guess that the
 attacker makes takes 10 minutes of CPU time to generate N, as well
-as whatever work the servers impose to solve their client puzzle.
+as whatever proof of work the servers require.
 
 The sharding prevents a single malicious server from blindly 
 guessing weak passwords across its entire collection of objects.
@@ -147,13 +147,15 @@ in gpg to compromise the user's system.
 There's a server list shipped with the client, giving their tor onion address
 and the organization providing the server. 
 
-Three of the servers in the list are designated default servers.
+Three of the servers in the list are recommended servers.
 Shards are stored on these unless overridden by other configuration.
 
-When recovering a key, the client tries the default servers first. But, if
-it fails to recover the key using those, it goes on to try other servers on
-the list. This way we don't need to remember which servers the shards were
-stored on, and can change the default servers when necessary.
+When recovering a key, the client tries the recommended servers first. But,
+if it fails to recover the key using those, it goes on to try other servers
+on the list. This way we don't need to remember which servers the shards
+were stored on, and can change the recommended servers when necessary.
+
+See [[servers]] for more on the server list.
 
 ## Servers
 
@@ -183,38 +185,63 @@ Objects shoud be padded to a fixed size before they are encrypted, to
 prevent attackers from correlating and targeting particular objects based
 on size.
 
-## Client puzzles
+## client-server Proof of Work
+
+The Proof of Work prevents servers being flooded with requests.
+This is particularly important to prevent misuse of keysafe servers
+to store large data on them. It's also somewhat useful to prevent attackers
+guessing the name someone used to store a key; but the cost of generating
+N from a name makes the server's proof of work only a secondary line of
+defense against such an attack. Finally, PoW is useful to protect against
+DOS attacks.
 
 Assuming that the client communicates with the server over http:
 
 	PUT /keysafe/objects/N?S
 	GET /keysafe/objects/N?S
 
-Then, the S can be required to be a string such that argon2(N,S)
-starts with a given number of 0's. This allows the server to verify the
-client's proof of work without maintaining any state.
-
-The required number of 0's can be queried:
-
-	GET /keysafe/proofofwork/
+The server's response can be either the result of the request,
+or a proof of work requirement, which specifies the difficulty D 
+(number of 0's needed), random value R, and the number of argon2
+iterations. The client provides the proof of work in S, which is a 
+string such that argon2(N,S+R) starts with a given number of 0's.
 
-With a response like "zeros=4 iterations=1".
+The random value R is picked when the server starts up, and may be changed
+from time to time. It prevents a client from reusing proofs of work 
+between servers, and is also useful to mitigate DOS attacks.
 
 (The server should only be able to control the number of iterations,
 not other argon2 parameters, to avoid forcing the client to use too much
 memory. Normally, the server will keep iterations small, probably 1,
-since it does need to calculate the argon2 hash itself.)
-
-Note that this scheme lets a client do work once for a given N and then
-request that N from multiple servers, as long as they have similar zeros=
-parameters (and the same iterations= parameters). This is probably a good
-thing; it means that keysafe doesn't need to do extra work when checking
-servers to get a shard.
-
-Servers can change their proof of work parameters as needed, but that can
-cause a client that was connected to the server to generate a bad POW.
-The server can respond with 402 Payment Required in that case, so the
-client knows to retry.
+since it does need to calculate the argon2 hash once itself.)
+
+The server can use a [token bucket](https://en.wikipedia.org/wiki/Token_bucket)
+to throttle requests to a given rate. In fact, there can be a whole
+series of token buckets B0,B1.., for increasing difficulty proofs of work.
+
+A request without a proof of work is checked in B0. If that bucket is empty,
+the server responds with a proof of work requirement D=1, and
+the client makes a new request whose proof of work allows access to B1.
+If the server is under load, B1 might also be empty, and so the client 
+will have to try again with D=2 to access B2, and so on.
+
+If there are 4 buckets, and each bucket refills at the rate of a
+token every minute, then the maximum allowed throughput is 4 requests
+per minute. If calculating the proof of work takes 2^D seconds on average, 
+then it will take on average 16 minutes work to access B4.
+
+Since this scheme is stateless, it lets an attacker do work once for a
+given N and then flood the server with repeated requests for N?S, reusing the
+proof of work. This is a DOS because the attacker can keep all the token
+buckets drained and so not let legitimate requests through. But, the server
+can detect when this DOS is occurring (when a proof of work allows
+accessing the last token bucket, and the bucket is empty), and pick a new R
+(and also perhaps increase the number of argon2 iterations to make the PoW
+a little bit harder). This invalidates the attacker's cached proof of work,
+and gives other clients a chance to get some requests through while the
+attacker is generating new proofs of work for the new R. Another defense
+against this attack is for the server to keep a small cache of recent N's
+(expiring after an hour) and reject repeated requests for them.
 
 ## Avoiding correlations
 

teleconsole is yet another option
diff --git a/code/debug-me/discussion.mdwn b/code/debug-me/discussion.mdwn
index 8027f1a..ab5c469 100644
--- a/code/debug-me/discussion.mdwn
+++ b/code/debug-me/discussion.mdwn
@@ -10,6 +10,7 @@ Some similar projects you may be interested in looking at, if only for "how not
 * [Mosh][] - the mobile shell, interesting concepts of local terminal emulation and predictive capabilities
 * [Monkeysphere][] - OpenPGP web of trust applied to SSH and HTTP servers and clients
 * [watch-my-terminal][] - Allows a remote users to watch your terminal session via any modern browser (script+node on the broadcaster side, javascript on the watchers' side). Terminal emulation is quite good; it correctly renders vim, less and aptitude.
+* [teleconsole][] - can share terminal sessions through SSH or the browser through a SSH proxy
 
 [Gitso]: https://code.google.com/archive/p/gitso/
 [more recent fork]: https://github.com/AustP/Gitso
@@ -19,5 +20,6 @@ Some similar projects you may be interested in looking at, if only for "how not
 [Mosh]: https://mosh.mit.edu/
 [Monkeysphere]: http://web.monkeysphere.info
 [watch-my-terminal]: https://jasonwoof.com/gitweb/?p=watch-my-terminal.git;a=tree
+[teleconsole]: https://github.com/gravitational/teleconsole
 
 It would seem to me preferable to reuse existing components (SSH, especially) instead of reinventing the wheel too much here. So much trouble with terminal emulation and so on, as I am sure you know...

comment
diff --git a/blog/entry/hiking_the_Roan/comment_2_4e7a05cd8a2fb55ec0122da231908be1._comment b/blog/entry/hiking_the_Roan/comment_2_4e7a05cd8a2fb55ec0122da231908be1._comment
new file mode 100644
index 0000000..cbd66d5
--- /dev/null
+++ b/blog/entry/hiking_the_Roan/comment_2_4e7a05cd8a2fb55ec0122da231908be1._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2016-09-08T15:17:54Z"
+ content="""
+I actually did that hike with my laptop in my pack because I
+needed it on the larger trip for other reasons and did not want to
+leave it unattended in my car overnight. Even with trash bags to protect
+from moisture, that was very suboptimal, do not recommend.
+"""]]

note GLU/CPU comparison
diff --git a/code/keysafe/faq.mdwn b/code/keysafe/faq.mdwn
index 578b5b6..4512be7 100644
--- a/code/keysafe/faq.mdwn
+++ b/code/keysafe/faq.mdwn
@@ -44,6 +44,10 @@ Compare these numbers with the cost to crack keysafe passwords
 * Weak password (30 entropy): 51072 CPU-years 
 * Super-weak password (19 entropy): 25 CPU-years 
 
+(Note that is a comparison between GPU years and CPU years; SHA-1 used by
+gpg can easily be run fast on GPUs, while keysafe uses argon2 which is
+designed to be GPU-resistent.)
+
 Big difference! Indeed, the design of gpg prevents a really expensive hash
 being used to protect against passphrase cracking, because it would slow down
 day-to-day use of gpg. Keysafe can make cracking the password much more

Added a comment: question
diff --git a/blog/entry/hiking_the_Roan/comment_1_db91f5e569a74a87cff0a42b7d656906._comment b/blog/entry/hiking_the_Roan/comment_1_db91f5e569a74a87cff0a42b7d656906._comment
new file mode 100644
index 0000000..461ef89
--- /dev/null
+++ b/blog/entry/hiking_the_Roan/comment_1_db91f5e569a74a87cff0a42b7d656906._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="jmz@2d336904dde22d29d81d9ae1644d7e9db6613317"
+ nickname="jmz"
+ subject="question"
+ date="2016-09-08T01:20:39Z"
+ content="""
+Do you take a laptop or anything while you camp? PocketChip? Or just a digital camera? Just curious, I've taken a cheap laptop once.
+"""]]

corrections
thanks, kwadronaut
diff --git a/code/keysafe/faq.mdwn b/code/keysafe/faq.mdwn
index 098a017..578b5b6 100644
--- a/code/keysafe/faq.mdwn
+++ b/code/keysafe/faq.mdwn
@@ -10,7 +10,7 @@ theft, raids, and compromised printers. Gold standard.
 Using keysafe is analagous to storing the paperkey printout in a safety
 deposit box at a bank, and using a really really strong gpg passphrase.
 Since we don't trust a single bank (server), we shred the printout and
-evenly distribute the shreds amoung several banks. While the banks know the
+evenly distribute the shreds among several banks. While the banks know the
 safety deposit boxes belong to you and could put the shreds back together,
 a keysafe server has very little identifying information to go on (it only
 knows when you made the deposit).
@@ -19,10 +19,10 @@ knows when you made the deposit).
 
 So, you rely on your gpg passphrase for security.
 
-Gpg uses between 1024 (the default) and 65011712 rounds of SHA-1 hashing of
-the passphrase. In 2012, a GPU could calculate 2 billion SHA-1 hashes
-per second, so this is not much of an impediment to password cracking at
-all.
+Gpg uses between 1024 and 65011712 rounds of SHA-1 hashing of
+the passphrase, with the default probably being 65536. 
+In 2012, a GPU could calculate 2 billion SHA-1 hashes per second,
+so this is not much of an impediment to password cracking at all.
 
 Assuming 100 gpg passphrases can be tried per second, and gpg is
 configured to use the maximum rounds (which it normally is NOT):
@@ -55,7 +55,7 @@ Not recommended. Use a brain wallet.
 
 Keysafe might be more secure than a paper wallet in some situations.
 It's happened before that someone has stumbled over someone else's
-list of electrum words amoung their papers. Using keysafe avoids such
+list of electrum words among their papers. Using keysafe avoids such
 scenarios.
 
 #### How is keysafe different from other systems for private key backup/sync?

foo
diff --git a/code/keysafe/faq.mdwn b/code/keysafe/faq.mdwn
index 75f59de..098a017 100644
--- a/code/keysafe/faq.mdwn
+++ b/code/keysafe/faq.mdwn
@@ -60,7 +60,8 @@ scenarios.
 
 #### How is keysafe different from other systems for private key backup/sync?
 
-Here are some similar systems:
+Here are some similar systems, and intial impressions (which may be
+inaccurate; corrections welcomed):
 
 * [Whiteout](https://blog.whiteout.io/2014/07/07/secure-pgp-key-sync-a-proposal/)
   uses a 24 letter code to encrypt the secret key. This has to be written

improve
diff --git a/code/keysafe/faq.mdwn b/code/keysafe/faq.mdwn
index 1e33e4e..75f59de 100644
--- a/code/keysafe/faq.mdwn
+++ b/code/keysafe/faq.mdwn
@@ -58,7 +58,7 @@ It's happened before that someone has stumbled over someone else's
 list of electrum words amoung their papers. Using keysafe avoids such
 scenarios.
 
-#### Hw is keysafe different from other systems for private key backup/sync?
+#### How is keysafe different from other systems for private key backup/sync?
 
 Here are some similar systems:
 
@@ -75,7 +75,7 @@ Here are some similar systems:
   rate-limit logins and so avoid password cracking (except by the server).
   (This idea is worth keysafe stealing!)
 * [LEAP](https://leap.se/en/docs/tech/hard-problems#availability-problem)'s
-  [Soledad](https://leap.se/soledad) uses a large storage secret to encrypt
+  [Soledad](https://leap.se/soledad) uses a large secret to encrypt
   private keys. This can be stored in a recovery document in a recovery
   database, which anyone can make requests from. To prevent attacks,
   the recovery database delays responses, and a recovery code is needed

ideas
diff --git a/code/keysafe/details.mdwn b/code/keysafe/details.mdwn
index 4fd7fea..925c16d 100644
--- a/code/keysafe/details.mdwn
+++ b/code/keysafe/details.mdwn
@@ -296,3 +296,46 @@ Note that the argon2 hash parameters to vary between versions should not be
 merely the number of rounds, as that would allow an attacker to hash for
 each version's number of rounds in one pass. Instead, vary the hash
 memory parameter.
+
+## Ideas
+
+Some ideas for improvements to keysafe.
+
+### Assisted Password-based Key Derivation
+
+An idea from [Nigori](http://www.links.org/files/nigori/nigori-protocol-01.html#anchor15):
+
+If the user has an account at some server, the server can contribute part
+of the data used to generate the key encryption key K. So not only is the
+user's keysafe password needed for key recovery, but the user has to
+authenticate to the server. As well as adding entropy to K, the server 
+can do rate limiting to prevent password guessing.
+
+Risks include:
+
+* The server becomes a target to be compromised.
+* If the server goes down, the user loses the ability to recover their gpg
+  key from keysafe.
+
+### Entangled objects
+
+An idea from Anthony Towns:
+
+Two or more objects stored on a keysafe server can be entangled.
+When one of them is requested, the server should delete the others.
+
+This could be used in several ways:
+
+* Keysafe could upload random objects entangled with a key's object,
+  and keep local records of the names of the random objects. Then if the
+  user wants to stop storing a key on keysafe servers, keysafe can request
+  the entangled objects to (hopefully) delete the real objects from the
+  server.
+* Keysafe could pick or prompt for some tripwire names that an attacker
+  might try if they were looking for a user's data. Then an attacker
+  risks deleting the data stored on the server. Although this also has 
+  DOS potential.
+* The user could pick a real name and fake name and keysafe uploads
+  objects for both. If the user is being forced to give up their keysafe
+  name and password, they could provide the fake name, and if it were
+  used, their data would get deleted from the keysafe servers.

reviewed some similar systems
diff --git a/code/keysafe/faq.mdwn b/code/keysafe/faq.mdwn
index 21387eb..1e33e4e 100644
--- a/code/keysafe/faq.mdwn
+++ b/code/keysafe/faq.mdwn
@@ -57,3 +57,27 @@ Keysafe might be more secure than a paper wallet in some situations.
 It's happened before that someone has stumbled over someone else's
 list of electrum words amoung their papers. Using keysafe avoids such
 scenarios.
+
+#### Hw is keysafe different from other systems for private key backup/sync?
+
+Here are some similar systems:
+
+* [Whiteout](https://blog.whiteout.io/2014/07/07/secure-pgp-key-sync-a-proposal/)
+  uses a 24 letter code to encrypt the secret key. This has to be written
+  down to back it up. Since it is high-entropy (256 bits), the encryption
+  can be fast, and so it can be used to sync private keys between devices.
+* [Nigori](http://www.links.org/files/nigori/nigori-protocol-01.html)
+  uses a password to encrypt and SSS to split the private key.
+  Its main protection against password guessing seems be to be
+  its "Assisted Password-based Key Derivation", where some separate server
+  that the user has an account at supplies part of the encryption key after
+  the user has authenticated at the server. This allows the server to
+  rate-limit logins and so avoid password cracking (except by the server).
+  (This idea is worth keysafe stealing!)
+* [LEAP](https://leap.se/en/docs/tech/hard-problems#availability-problem)'s
+  [Soledad](https://leap.se/soledad) uses a large storage secret to encrypt
+  private keys. This can be stored in a recovery document in a recovery
+  database, which anyone can make requests from. To prevent attacks,
+  the recovery database delays responses, and a recovery code is needed
+  to access a document. The recovery code is a 16 character code that the
+  user has to write down.

foo
diff --git a/code/scroll.mdwn b/code/scroll.mdwn
index 9741937..fa21794 100644
--- a/code/scroll.mdwn
+++ b/code/scroll.mdwn
@@ -77,3 +77,5 @@ Many thanks to all the reviewers! --[[Joey]]
 ## coda
 
 [[game_designer_thoughts|scroll/thoughts]]
+
+	<paroneayea> through a rogue lens, all texts are adventures.

update
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 3c1e726..554d893 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -102,6 +102,8 @@ lhmhvShr0WRqB8fWYPkc
 * Any backup is *not* incremental. Incremental backups interfere with
   keysafe's obscuring of when shards were stored on the server, and can
   be used in correlation attacks.
+* Similarly, the filesystem and storage system should not allow rolling back
+  to old snapshots.
 
 ### Recommended
 

more
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 80a8d99..3c1e726 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -99,6 +99,9 @@ lhmhvShr0WRqB8fWYPkc
   It may be better to run some servers without backups and adjust the
   number of shards needed to recover keys; a server losing its data
   need not be catastrophic.)
+* Any backup is *not* incremental. Incremental backups interfere with
+  keysafe's obscuring of when shards were stored on the server, and can
+  be used in correlation attacks.
 
 ### Recommended
 
@@ -113,12 +116,19 @@ lhmhvShr0WRqB8fWYPkc
 * The keysafe data store and any swap partitions are encrypted,
   and have to be manually unlocked when the server is booted.
 
-## Disk space use
+## Server scaling
 
 Each key takes a minimum of 64 KiB to store, perhaps more for gpg keys
 with lots of signatures. So 10 GiB of disk is sufficient for 160 thousand
 users, which is enough for a small keysafe server.
 
+The keysafe server uses very little memory and CPU.
+
+There is some disk IO overhead, because keysafe updates the mtime and ctime
+of all shards stored on the server, as frequently as every 30 minutes.
+Once a large number of shards are stored, this could become a significant
+source of disk IO.
+
 ## Server setup
 
 It's early days still, but keysafe's server code works well enough.

link
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 5ce512f..80a8d99 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -134,6 +134,6 @@ It's early days still, but keysafe's server code works well enough.
   Required.
 * Once ready, email id@joeyh.name to get added to keysafe's server list.
 
-A [[code/propellor]] config for a keysafe server is in propellor's
-joeyconfig.hs file, and shows how I set up my own keysafe server.
+Here's a the [[code/propellor]] config for my own keysafe server:
+<http://source.propellor.branchable.com/?p=source.git;a=blob;f=joeyconfig.hs;h=fa37e97ba94eecf8f4cbe47d41fbc7c1cd89723b;hb=HEAD#l461>
 --[[Joey]]

clarify
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index fc3c2fa..5ce512f 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -89,7 +89,7 @@ lhmhvShr0WRqB8fWYPkc
 * Commitment to either keep the server running long-term (ie, 10+ years),
   or transition the data to a replacement server that meets these
   requirements and that must not contain any related shards.
-* No open ports (other than ssh).
+* No other open ports (other than ssh).
 * Ssh authentication only by ssh key, not password.
 * Either off-server backup, or replication of shards to additional disks.
   (rsync to additional local disks would work perfectly well and avoids

update
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 9772e58..fc3c2fa 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -109,7 +109,7 @@ lhmhvShr0WRqB8fWYPkc
 * Warrant canary.
 * Hardware is hosted in-house. A VM at a cloud provider is right out
   because the provider could be made to give access to it without the
-  server operator knowing about it.
+  server operator knowing about it. Which would bypass the warrant canary.
 * The keysafe data store and any swap partitions are encrypted,
   and have to be manually unlocked when the server is booted.
 

server setup
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 4a77016..9772e58 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -118,3 +118,22 @@ lhmhvShr0WRqB8fWYPkc
 Each key takes a minimum of 64 KiB to store, perhaps more for gpg keys
 with lots of signatures. So 10 GiB of disk is sufficient for 160 thousand
 users, which is enough for a small keysafe server.
+
+## Server setup
+
+It's early days still, but keysafe's server code works well enough.
+
+* git clone keysafe
+* Be sure to verify the gpg signature of the git repository!
+* You will need to install keysafe from source; see its INSTALL file.
+  Use `make install` to install it, including a systemd service file.
+* `systemctl enable keysafe.service`
+* Install tor and set up a tor hidden service. Keysafe listens on port 4242
+  by default, so use that port.
+* Configure the server to meet all the requirements for Alternate or
+  Required.
+* Once ready, email id@joeyh.name to get added to keysafe's server list.
+
+A [[code/propellor]] config for a keysafe server is in propellor's
+joeyconfig.hs file, and shows how I set up my own keysafe server.
+--[[Joey]]

tweaks
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 39172f5..4a77016 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -4,7 +4,7 @@ keysafe server.
 
 ## Server categories
 
-Keysafe's server list puts servers in four categories:
+Keysafe's server list puts servers in three categories:
 
 1. **Recommended**: Servers that meet all best practices for security and
    are run by a well-known, trusted entity.
@@ -22,13 +22,7 @@ Keysafe's server list puts servers in four categories:
    store 1 share on an Alternate server, and the other 2 shares on two
    Recommended servers.
 
-3. **Readonly**: Servers that are secured to at least Alternate level of
-   security, but are not accepting new uploads.
-
-   This can be used when a server runs out of disk space, or otherwise
-   should not be used to store new keys.
-
-4. **Untrusted**: Servers that are not secured well or are run by an untrusted
+3. **Untrusted**: Servers that are not secured well or are run by an untrusted
    entity.
    
    Keysafe will never store data on Untrusted servers. 
@@ -37,7 +31,7 @@ Keysafe's server list puts servers in four categories:
    keysafe will warn the user about this problem.
    
    The only time keysafe will use untrusted servers is if it's restoring a
-   key, and cannot find enough shares on Recommended/Alternate/Readonly
+   key, and cannot find enough shares on Recommended/Alternate
    servers, and has to fall back to downloading from an Untrusted server.
 
 ## Server list
@@ -88,40 +82,39 @@ lhmhvShr0WRqB8fWYPkc
 * Keysafe port only exposed via tor hidden service.
 * Dedicated to only running keysafe, no other services (other than ssh for
   admin)
-* Run by a well known and trustworthy entity.
 * The set of people who administer the server, and procedures for giving
   others access is well-defined.
+* Noone who has access to the server also has access to any Recommended
+  server.
 * Commitment to either keep the server running long-term (ie, 10+ years),
   or transition the data to a replacement server that meets these
   requirements and that must not contain any related shards.
-* No other recommended server in keysafe's server list is run by the same
-  entity, or administered by the same people.
 * No open ports (other than ssh).
 * Ssh authentication only by ssh key, not password.
-* Either off-site backup, or replication of shards to additional disks.
-  (rsync to additional local disk would work perfectly well and avoids
+* Either off-server backup, or replication of shards to additional disks.
+  (rsync to additional local disks would work perfectly well and avoids
   the complications of RAID)
-* Any off-server backup is encrypted, and there's a well-defined procedure for
-  how the backup works and where it's stored.  
+* Any off-server backup is strongly encrypted.
   (There's a trade-off here; any backup widens the attack surface.
   It may be better to run some servers without backups and adjust the
   number of shards needed to recover keys; a server losing its data
   need not be catastrophic.)
-* Enough disk space for a reasonable number of users to store keys.
-  Each key takes a minimum of 64 KiB to store, perhaps more for gpg keys
-  with lots of signatures. So 10 GiB of disk is sufficient for 160 thousand
-  users, which is probably enough to start with.
-
-### Readonly
-
-* Same as Alternate except for disk space requirements.
 
 ### Recommended
 
 * Everything in Alternate, to start with.
+* Run by a well known and trustworthy entity.
+* Noone who has access to the server also has access to any other
+  Recommended or Alternate server.
 * Warrant canary.
 * Hardware is hosted in-house. A VM at a cloud provider is right out
   because the provider could be made to give access to it without the
   server operator knowing about it.
 * The keysafe data store and any swap partitions are encrypted,
   and have to be manually unlocked when the server is booted.
+
+## Disk space use
+
+Each key takes a minimum of 64 KiB to store, perhaps more for gpg keys
+with lots of signatures. So 10 GiB of disk is sufficient for 160 thousand
+users, which is enough for a small keysafe server.

add news item for keysafe 0.20160831
diff --git a/code/keysafe/news/version_0.20160831.mdwn b/code/keysafe/news/version_0.20160831.mdwn
new file mode 100644
index 0000000..7331f21
--- /dev/null
+++ b/code/keysafe/news/version_0.20160831.mdwn
@@ -0,0 +1,16 @@
+keysafe 0.20160831 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Server implementation is ready for initial deployment.
+   * Keysafe as a client is not yet ready for production use.
+   * Removed embedded copy of secret-sharing library, since finite-field
+     only supports prime fields. This caused shares to be twice the size of
+     the input value.
+   * Reduced chunk size to 32kb due to share size doubling.
+   * Fix gpg secret key list parser to support gpg 2.
+   * Tuned argon2 hash parameters on better hardware than my fanless laptop.
+   * Improve time estimates, taking into account the number of cores.
+   * Added basic test suite.
+   * Added options: --store-directory --test --port --address
+   * Added a Makefile
+   * Added a systemd service file.
+   * Added a desktop file."""]]
\ No newline at end of file

also
diff --git a/blog/entry/keysafe_alpha_release/comment_2_778223273bd6d260a9392ca29f6df573._comment b/blog/entry/keysafe_alpha_release/comment_2_778223273bd6d260a9392ca29f6df573._comment
index 807bd47..bd2fd13 100644
--- a/blog/entry/keysafe_alpha_release/comment_2_778223273bd6d260a9392ca29f6df573._comment
+++ b/blog/entry/keysafe_alpha_release/comment_2_778223273bd6d260a9392ca29f6df573._comment
@@ -21,4 +21,8 @@ need to run 4 threads, and those should run on 4 cpus. This is factored
 into the benchmark; if the system has at least 4 cores, it expects the
 benchmark to run in 1/4th the time it would on an equivilant single core
 system.)
+
+Oh, one other thing: It would probably be good to build argon2 from source
+on the system being benchmarked. It has at least some CPU-specific
+optimisations that are disabled in the debian build for portability.
 """]]

comment
diff --git a/blog/entry/keysafe_alpha_release/comment_2_778223273bd6d260a9392ca29f6df573._comment b/blog/entry/keysafe_alpha_release/comment_2_778223273bd6d260a9392ca29f6df573._comment
new file mode 100644
index 0000000..807bd47
--- /dev/null
+++ b/blog/entry/keysafe_alpha_release/comment_2_778223273bd6d260a9392ca29f6df573._comment
@@ -0,0 +1,24 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2016-08-31T22:06:36Z"
+ content="""
+I am very interested in benchmark results from your 72-way system,
+especially if it has very fast CPUs. But, be sure to install keysafe from
+git and not this alpha release, as the hashes being benchmarked have
+changed and the benchmark improved.
+
+The reason the benchmark does not parallelize is because we want to
+learn how long it takes to run the operation on a single CPU core.
+
+From there we can estimate that a N core machine can perform N concurrent
+operations in the same amount of time (or somewhat longer;
+hyperthreading overheads & etc), and use that in calculating
+the expected brute-force attack cost.
+
+(Actually, it should parallelize slightly, because argon2 is configured to
+need to run 4 threads, and those should run on 4 cpus. This is factored
+into the benchmark; if the system has at least 4 cores, it expects the
+benchmark to run in 1/4th the time it would on an equivilant single core
+system.)
+"""]]

keysafe servers
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 7e8bfd1..d27bfbf 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -68,6 +68,10 @@ Note that there is a manpage, but stack doesn't install it yet.
 
 Email <id@joeyh.name>
 
+## Servers
+
+See [[servers]] for information on the keysafe servers.
+
 ## License
 
 Keysafe is licensed under the terms of the AGPL 3+
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 34d4351..39172f5 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -1,8 +1,89 @@
-There are currently no keysafe servers. We need at least 3 for keysafe to
-work. Please contact <id@joeyh.name> if you would like to run a keysafe server.
+There are currently not enough keysafe servers. We need at least 3 for
+keysafe to work. Please contact <id@joeyh.name> if you would like to run a
+keysafe server.
 
-Requirements for a server to be included in keysafe's server list as a
-recommended server:
+## Server categories
+
+Keysafe's server list puts servers in four categories:
+
+1. **Recommended**: Servers that meet all best practices for security and
+   are run by a well-known, trusted entity.
+
+   Keysafe prefers to store data only on Recommended servers when possible.
+
+2. **Alternate**: Servers that are not secured well enough to be
+   Recommended.
+
+   Keysafe will store data on Alternate servers if it has to, but will
+   avoid storing enough data to allow the key to be recovered using only
+   the data stored on Alternate servers.
+
+   For example, with 2 of 3 shares needed to restore a key, keysafe can
+   store 1 share on an Alternate server, and the other 2 shares on two
+   Recommended servers.
+
+3. **Readonly**: Servers that are secured to at least Alternate level of
+   security, but are not accepting new uploads.
+
+   This can be used when a server runs out of disk space, or otherwise
+   should not be used to store new keys.
+
+4. **Untrusted**: Servers that are not secured well or are run by an untrusted
+   entity.
+   
+   Keysafe will never store data on Untrusted servers. 
+   
+   If a server becomes untrusted and keysafe stored data on it in the past,
+   keysafe will warn the user about this problem.
+   
+   The only time keysafe will use untrusted servers is if it's restoring a
+   key, and cannot find enough shares on Recommended/Alternate/Readonly
+   servers, and has to fall back to downloading from an Untrusted server.
+
+## Server list
+
+### Recommended
+
+**None yet!**
+
+### Alternate
+
+* keysafe.joeyh.name
+
+<pre>
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA256
+
+  keysafe.joeyh.name is provided by me, Joey Hess.
+
+  I intend to run this server for at least 10 years (through 2027),
+  or failing that, to transition any data stored on it to another
+  server that is of similar or higher security.
+
+  It is a Digital Ocean VPS, located in Indonesia. I can't tell if the
+  hosting provider is accessing the contents of the server, and so
+  this server is not securely hosted enough to be Recommended.
+-----BEGIN PGP SIGNATURE-----
+
+iQIcBAEBCAAGBQJXx0qFAAoJEMkQ2SIlEuPHyGMQALSLL7LZEpTi+zf2kPYGoBMQ
+3z3FDB9B6SaF4uN3r+XlAw2Vzas2KVLCbNkO+np7tLzC0qdY5dBLDI7+ZJXiKi2v
+iqxKICl0E8+ih8JOe0JWfoysO974I1DesEI7X6VUewwNpd35OgCuIL5RmknKrX4I
+x7gUfsONiojUKgOT0yMErUfw3VNYB0Kbzw4Xic66eIkFl5z6APMknjqvOC1196v9
+BW0rSM+OsthB9xkj7ULKQv+1LrxmwNu0+FL62qNKGObbXHayfLBGm8TT9Y7etQYD
+3zRDiUfa0m2aYu7ZRx5HSIgExVVd3YosDUFA4xsIb6N4wBbP1zS2TG2Zo5o/+3gt
+BerkQL/xkMWhIMVCYp1hWc47MenHk1MJU5EhS+duL/fnlqW2HcFanM+fOv+/ZWt6
+da2mdjSR95Ekq22BXN9eHO54AFJKLWYNdT9E5W2rlwqUoC4dqsqYGT3XWnAaKHC/
+he9+B/wdEf7165Qy+MKo/36Ib7pfhPQv4hip2cuMP9w0E6JoKZusBV5AdxRvGAGf
+GvUhvNog6v9/t+cqUp6dSTT2WVllkXJ/5deGJYLzZMJjZS3cZ75ZKr8OD5oQxr+m
+7oL6BDvxha7Q4qHo/RZgxyd/qZ7zWHTT6Tn6qNCBGUi4b6Etb0kEd5Os66WoLCSK
+lhmhvShr0WRqB8fWYPkc
+=SNGN
+-----END PGP SIGNATURE-----
+</pre>
+
+## Detailed requirements
+
+### Alternate
 
 * Keysafe port only exposed via tor hidden service.
 * Dedicated to only running keysafe, no other services (other than ssh for
@@ -10,31 +91,37 @@ recommended server:
 * Run by a well known and trustworthy entity.
 * The set of people who administer the server, and procedures for giving
   others access is well-defined.
-* No other recommended server in keysafe's server list is run by the same
-  entity, or administered by the same people. `*`
 * Commitment to either keep the server running long-term (ie, 10+ years),
   or transition the data to a replacement server that meets these
-  requirements and that must not contain any related shards. `*`
-* Warrant canary.
+  requirements and that must not contain any related shards.
+* No other recommended server in keysafe's server list is run by the same
+  entity, or administered by the same people.
 * No open ports (other than ssh).
 * Ssh authentication only by ssh key, not password.
-* The keysafe data store and any swap partitions are encrypted,
-  and have to be manually unlocked when the server is booted.
-* Hardware is hosted in-house. A VM at a cloud provider is right out
-  because the provider could be made to give access to it without the
-  server operator knowing about it.
-* RAID or other replication of shards to additional disks.
-  (rsync would work perfectly well and avoids the complications of RAID)
+* Either off-site backup, or replication of shards to additional disks.
+  (rsync to additional local disk would work perfectly well and avoids
+  the complications of RAID)
 * Any off-server backup is encrypted, and there's a well-defined procedure for
-  how the backup works and where it's stored. `*`
+  how the backup works and where it's stored.  
   (There's a trade-off here; any backup widens the attack surface.
   It may be better to run some servers without backups and adjust the
   number of shards needed to recover keys; a server losing its data
   need not be catastrophic.)
+* Enough disk space for a reasonable number of users to store keys.
+  Each key takes a minimum of 64 KiB to store, perhaps more for gpg keys
+  with lots of signatures. So 10 GiB of disk is sufficient for 160 thousand
+  users, which is probably enough to start with.
 
-Note that if a keysafe server runs out of disk space, or otherwise should
-not be used to store new keys, it can still be included in the server list,
-as a non-recommended server. Keysafe won't store data there, but it will
-download shards from the server if necessary to restore a key. A
-non-recommended server should meet all criteria above except for those
-marked with `*`.
+### Readonly
+
+* Same as Alternate except for disk space requirements.
+
+### Recommended
+
+* Everything in Alternate, to start with.
+* Warrant canary.
+* Hardware is hosted in-house. A VM at a cloud provider is right out
+  because the provider could be made to give access to it without the
+  server operator knowing about it.
+* The keysafe data store and any swap partitions are encrypted,
+  and have to be manually unlocked when the server is booted.

Added a comment: Automatic parallelism?
diff --git a/blog/entry/keysafe_alpha_release/comment_1_56c555d4e274186cd22789ddce497586._comment b/blog/entry/keysafe_alpha_release/comment_1_56c555d4e274186cd22789ddce497586._comment
new file mode 100644
index 0000000..a82a97a
--- /dev/null
+++ b/blog/entry/keysafe_alpha_release/comment_1_56c555d4e274186cd22789ddce497586._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="josh@ccccabe84317e1b7429fd465de0b38fd54925dea"
+ nickname="josh"
+ subject="Automatic parallelism?"
+ date="2016-08-31T21:02:58Z"
+ content="""
+keysafe --benchmark seems to run single-threaded.  Would you consider automatically parallelizing across all CPUs, to provide a more accurate benchmark?  I have a 72-way system I can send you benchmarks from.
+"""]]

Added a comment
diff --git a/blog/entry/late_summer/comment_1_39d29c8990dfb2d4c0d7d807e9297f53._comment b/blog/entry/late_summer/comment_1_39d29c8990dfb2d4c0d7d807e9297f53._comment
new file mode 100644
index 0000000..3703a13
--- /dev/null
+++ b/blog/entry/late_summer/comment_1_39d29c8990dfb2d4c0d7d807e9297f53._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="mr@e1f11bbd433e35f4e30d1cacaf1585fe2573f933"
+ nickname="mr"
+ subject="comment 1"
+ date="2016-08-31T19:06:06Z"
+ content="""
+Very interesting! Looking forward to hear more about off grid problems being solved with hacker skills and ethos. It must be so much easier to go off grid now than it was back when you did?
+"""]]

update
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
index 2f61176..34d4351 100644
--- a/code/keysafe/servers.mdwn
+++ b/code/keysafe/servers.mdwn
@@ -23,7 +23,9 @@ recommended server:
 * Hardware is hosted in-house. A VM at a cloud provider is right out
   because the provider could be made to give access to it without the
   server operator knowing about it.
-* Any backup is encrypted, and there's a well-defined procedure for
+* RAID or other replication of shards to additional disks.
+  (rsync would work perfectly well and avoids the complications of RAID)
+* Any off-server backup is encrypted, and there's a well-defined procedure for
   how the backup works and where it's stored. `*`
   (There's a trade-off here; any backup widens the attack surface.
   It may be better to run some servers without backups and adjust the

blog update
diff --git a/blog/entry/late_summer.mdwn b/blog/entry/late_summer.mdwn
new file mode 100644
index 0000000..bf453cc
--- /dev/null
+++ b/blog/entry/late_summer.mdwn
@@ -0,0 +1,23 @@
+With days beginning to shorten toward fall, my house is in initial power
+saving mode. Particularly, the internet gateway is powered off overnight.
+Still running electric lights until bedtime, and still using the inverter
+and other power without much conservation during the day.
+
+Indeed, I had two laptops running cpu-melting keysafe benchmarks for much
+of today and one of them had to charge up from empty too. That's why the
+house power is a little low, at 11.0 volts now, despite over 30 amp-hours
+of power having been produced on this mostly clear day. (1 week average is
+18.7 amp-hours)
+
+September/October is the tricky time where it's easy to fall off a battery
+depletion cliff and be stuck digging out for a long time. So time to start
+dusting off the conservation habits after summer's excess.
+
+----
+
+I think this is the first time I've mentioned any details of living off
+grid with a bare minimum of PV capacity in over 4 years. [[Solar]] has a
+lot of older posts about it, and I'm going to note down the typical
+milestones and events over the next 8 months.
+
+[[!tag solar]]

add solar feed
diff --git a/blog/entry/freedombox_for_a_solar_powered_house.mdwn b/blog/entry/freedombox_for_a_solar_powered_house.mdwn
index ff2745e..21afe2d 100644
--- a/blog/entry/freedombox_for_a_solar_powered_house.mdwn
+++ b/blog/entry/freedombox_for_a_solar_powered_house.mdwn
@@ -51,3 +51,5 @@ bits."]]
 
 Since the solar house is in the sticks, the result is a server I call
 "[[boxen/stick]]".
+
+[[!tag solar]]
diff --git a/blog/entry/getting_to_know_my_batteries.mdwn b/blog/entry/getting_to_know_my_batteries.mdwn
index 218e1e0..163b28c 100644
--- a/blog/entry/getting_to_know_my_batteries.mdwn
+++ b/blog/entry/getting_to_know_my_batteries.mdwn
@@ -48,6 +48,6 @@ battery capacity to get through up to a week of solid clouds in midwinter.
 
 [[!img pics/boxandpanel.jpeg size=x480 caption="battery box and solar panel"]]
 
-[[!tag diy energy battery lay]]
+[[!tag diy energy battery solar lay]]
 
 [[!meta title="getting to know my batteries"]]
diff --git a/blog/entry/infrastructure_update.mdwn b/blog/entry/infrastructure_update.mdwn
index b482374..f004497 100644
--- a/blog/entry/infrastructure_update.mdwn
+++ b/blog/entry/infrastructure_update.mdwn
@@ -24,6 +24,6 @@ I hope this was only an early taste of spring. Would be nice to have some
 more icy weather so I can put off dealing with refrigeration a little while
 longer. I have my eye on a 12v/propane fridge.
 
-[[!tag lay]]
+[[!tag lay solar]]
 
 [[!meta title="infrastructure update"]]
diff --git a/blog/entry/solar_day_2.mdwn b/blog/entry/solar_day_2.mdwn
index 2e2b224..093fe34 100644
--- a/blog/entry/solar_day_2.mdwn
+++ b/blog/entry/solar_day_2.mdwn
@@ -25,14 +25,14 @@ for the stove, and kerosine for the lanterns. And of course always the state
 of the batteries. So far, the first battery bank seems likely to last longer
 than the ice. I'll know better tomorrow.
 
-Unfortunatly I burned out the 5v power suppzly I was using to run my NSLU2
+Unfortunatly I burned out the 5v power supply I was using to run my NSLU2
 in a wiring mishap, so I have to run that on an inverter for now, and the
 batteries, though not low, can barely power both the inverter and my
 laptop. This has made staying online tricky. But I'm finding dialup
-psurpisingly tolerable, and it helps to generally slow down, too. Despite
+surpisingly tolerable, and it helps to generally slow down, too. Despite
 all the above, I got about as much real work done today as I normally
 would.
 
-[[!tag lay offgrid]] 
+[[!tag lay offgrid solar]] 
 
 [[!meta title="solar day 2"]]
diff --git a/blog/haskell.mdwn b/blog/haskell.mdwn
index 393865d..b48beb1 100644
--- a/blog/haskell.mdwn
+++ b/blog/haskell.mdwn
@@ -1,3 +1,3 @@
-The most recent haskell-related posts to [[Joey]]'s [[blog]].
+Haskell-related posts to [[Joey]]'s [[blog]].
 
-[[!inline pages="blog/entry/* and link(haskell) and !*/Discussion" show=40]]
+[[!inline pages="blog/entry/* and link(haskell) and !*/Discussion" show=0]]
diff --git a/blog/solar.mdwn b/blog/solar.mdwn
new file mode 100644
index 0000000..d81458c
--- /dev/null
+++ b/blog/solar.mdwn
@@ -0,0 +1,4 @@
+Posts related to solar power and off the grid living.
+
+[[!inline pages="blog/entry/* and link(solar) and !*/Discussion"
+actions=yes show=0]]

keysafe server requirements
diff --git a/code/keysafe/servers.mdwn b/code/keysafe/servers.mdwn
new file mode 100644
index 0000000..2f61176
--- /dev/null
+++ b/code/keysafe/servers.mdwn
@@ -0,0 +1,38 @@
+There are currently no keysafe servers. We need at least 3 for keysafe to
+work. Please contact <id@joeyh.name> if you would like to run a keysafe server.
+
+Requirements for a server to be included in keysafe's server list as a
+recommended server:
+
+* Keysafe port only exposed via tor hidden service.
+* Dedicated to only running keysafe, no other services (other than ssh for
+  admin)
+* Run by a well known and trustworthy entity.
+* The set of people who administer the server, and procedures for giving
+  others access is well-defined.
+* No other recommended server in keysafe's server list is run by the same
+  entity, or administered by the same people. `*`
+* Commitment to either keep the server running long-term (ie, 10+ years),
+  or transition the data to a replacement server that meets these
+  requirements and that must not contain any related shards. `*`
+* Warrant canary.
+* No open ports (other than ssh).
+* Ssh authentication only by ssh key, not password.
+* The keysafe data store and any swap partitions are encrypted,
+  and have to be manually unlocked when the server is booted.
+* Hardware is hosted in-house. A VM at a cloud provider is right out
+  because the provider could be made to give access to it without the
+  server operator knowing about it.
+* Any backup is encrypted, and there's a well-defined procedure for
+  how the backup works and where it's stored. `*`
+  (There's a trade-off here; any backup widens the attack surface.
+  It may be better to run some servers without backups and adjust the
+  number of shards needed to recover keys; a server losing its data
+  need not be catastrophic.)
+
+Note that if a keysafe server runs out of disk space, or otherwise should
+not be used to store new keys, it can still be included in the server list,
+as a non-recommended server. Keysafe won't store data there, but it will
+download shards from the server if necessary to restore a key. A
+non-recommended server should meet all criteria above except for those
+marked with `*`.

nah
diff --git a/blog/entry/hiking_the_Roan.mdwn b/blog/entry/hiking_the_Roan.mdwn
index 374b657..421d259 100644
--- a/blog/entry/hiking_the_Roan.mdwn
+++ b/blog/entry/hiking_the_Roan.mdwn
@@ -14,5 +14,4 @@ touch, but not this trip. Good to have a goal.
 
 [[!img pics/sunsetmist.jpg size=1024x]]
 
-Near sunset, land and sky merge as the mist moves in. In the dwarf
-blackberry bushes, baby birds call for their mother.
+Near sunset, land and sky merge as the mist moves in.

up
diff --git a/blog/entry/hiking_the_Roan.mdwn b/blog/entry/hiking_the_Roan.mdwn
index 421d259..374b657 100644
--- a/blog/entry/hiking_the_Roan.mdwn
+++ b/blog/entry/hiking_the_Roan.mdwn
@@ -14,4 +14,5 @@ touch, but not this trip. Good to have a goal.
 
 [[!img pics/sunsetmist.jpg size=1024x]]
 
-Near sunset, land and sky merge as the mist moves in.
+Near sunset, land and sky merge as the mist moves in. In the dwarf
+blackberry bushes, baby birds call for their mother.

blog update
diff --git a/blog/entry/hiking_the_Roan.mdwn b/blog/entry/hiking_the_Roan.mdwn
new file mode 100644
index 0000000..421d259
--- /dev/null
+++ b/blog/entry/hiking_the_Roan.mdwn
@@ -0,0 +1,17 @@
+Three moments from earlier this week..
+
+[[!img pics/footview.jpg size=1024x]]
+
+Sprawled under a tree after three hours of hiking with a heavy,
+water-filled pack, I look past my feet at six ranges of mountains behind
+mountains behind flowers.
+
+[[!img pics/roantent.jpg size=1024x]]
+
+From my campsite, I can see the rest of the path of the Appalachian Trail
+across the Roan balds, to Big Hump mountain. It seems close enough to
+touch, but not this trip. Good to have a goal.
+
+[[!img pics/sunsetmist.jpg size=1024x]]
+
+Near sunset, land and sky merge as the mist moves in.
diff --git a/blog/pics/roanten.jpg b/blog/pics/roanten.jpg
deleted file mode 100644
index 8f2b547..0000000
Binary files a/blog/pics/roanten.jpg and /dev/null differ
diff --git a/blog/pics/roantent.jpg b/blog/pics/roantent.jpg
new file mode 100644
index 0000000..8f2b547
Binary files /dev/null and b/blog/pics/roantent.jpg differ

add
diff --git a/blog/pics/footview.jpg b/blog/pics/footview.jpg
new file mode 100644
index 0000000..3b8b693
Binary files /dev/null and b/blog/pics/footview.jpg differ
diff --git a/blog/pics/roanten.jpg b/blog/pics/roanten.jpg
new file mode 100644
index 0000000..8f2b547
Binary files /dev/null and b/blog/pics/roanten.jpg differ
diff --git a/blog/pics/sunsetmist.jpg b/blog/pics/sunsetmist.jpg
new file mode 100644
index 0000000..109447e
Binary files /dev/null and b/blog/pics/sunsetmist.jpg differ

add news item for github-backup 1.20160922
diff --git a/code/github-backup/news/version_1.20150807.mdwn b/code/github-backup/news/version_1.20150807.mdwn
deleted file mode 100644
index 13d0ccd..0000000
--- a/code/github-backup/news/version_1.20150807.mdwn
+++ /dev/null
@@ -1,8 +0,0 @@
-github-backup 1.20150807 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Added bash completion.
-   * Add --no-forks flag that turns off backing up forks.
-     Thanks, Phil Ruffwind.
-   * Avoid nonzero exit due to temporary failures that can be retried next
-     time github-backup runs, so that it can be used in a cron job with eg,
-     chronic."""]]
\ No newline at end of file
diff --git a/code/github-backup/news/version_1.20160922.mdwn b/code/github-backup/news/version_1.20160922.mdwn
new file mode 100644
index 0000000..b9e1464
--- /dev/null
+++ b/code/github-backup/news/version_1.20160922.mdwn
@@ -0,0 +1,11 @@
+github-backup 1.20160922 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Increase base bounds to 4.8 to get mapM\_ etc that works on Vector.
+   * Recommended build method is now to use stack, for more reliable builds.
+   * Explicitly list modules and other files in github-backup.cabal.
+   * The hackage .tar.gz now omits the debian directory and may omit other
+     source files in the future; the purpose of that tarball is to make
+     stack/cabal install work, not to be a complete source distribution.
+     Use git repository to get complete source.
+   * Various updates to internal git and utility libraries shared
+     with git-annex."""]]
\ No newline at end of file

correction
diff --git a/code/keysafe/faq.mdwn b/code/keysafe/faq.mdwn
index 03005fd..21387eb 100644
--- a/code/keysafe/faq.mdwn
+++ b/code/keysafe/faq.mdwn
@@ -10,7 +10,7 @@ theft, raids, and compromised printers. Gold standard.
 Using keysafe is analagous to storing the paperkey printout in a safety
 deposit box at a bank, and using a really really strong gpg passphrase.
 Since we don't trust a single bank (server), we shred the printout and
-evenly distribute the shreds amoung three banks. While the banks know the
+evenly distribute the shreds amoung several banks. While the banks know the
 safety deposit boxes belong to you and could put the shreds back together,
 a keysafe server has very little identifying information to go on (it only
 knows when you made the deposit).

expand
diff --git a/code/keysafe/faq.mdwn b/code/keysafe/faq.mdwn
index 2d0b91a..03005fd 100644
--- a/code/keysafe/faq.mdwn
+++ b/code/keysafe/faq.mdwn
@@ -1,5 +1,20 @@
 [[!toc]]
 
+### How does keysafe compare with paperkey?
+
+Using paperkey to print out your gpg key and locking it in a safe is a great
+solution to gpg key backup. It requires a printer, a safe, and typing in many
+numbers to restore the key. It avoids all attack methods except physical
+theft, raids, and compromised printers. Gold standard.
+
+Using keysafe is analagous to storing the paperkey printout in a safety
+deposit box at a bank, and using a really really strong gpg passphrase.
+Since we don't trust a single bank (server), we shred the printout and
+evenly distribute the shreds amoung three banks. While the banks know the
+safety deposit boxes belong to you and could put the shreds back together,
+a keysafe server has very little identifying information to go on (it only
+knows when you made the deposit).
+
 ### I copy secring.gpg to dropbox to back it up. Why bother with keysafe?
 
 So, you rely on your gpg passphrase for security.
@@ -34,13 +49,6 @@ being used to protect against passphrase cracking, because it would slow down
 day-to-day use of gpg. Keysafe can make cracking the password much more
 expensive because it's only used for backup and restore.
 
-### How does keysafe compare with paperkey?
-
-Using paperkey to print out your gpg key and locking it in a safe is a great
-solution to gpg key backup. It requires a printer, a safe, and typing in many
-numbers to restore the key. It avoids all attack methods except physical
-theft, raids, and compromised printers. Gold standard.
-
 ### Is keysafe suitable for backing up bitcoin wallets?
 
 Not recommended. Use a brain wallet.

POW
diff --git a/code/keysafe/details.mdwn b/code/keysafe/details.mdwn
index 6d7d28e..4fd7fea 100644
--- a/code/keysafe/details.mdwn
+++ b/code/keysafe/details.mdwn
@@ -176,19 +176,45 @@ desirable to store the public and secret key together. This way,
 a user does not have to publish the key to keyservers, which makes some
 attack methods much less likely to try to crack their key.
 
-So, the object size should be at least a few tens of KB. If keysafe needs
-to store a larger key, it can chunk it up, and include a count of the
-number of chunks in the first encrypted object.
+So, the object size should be at least a few tens of KB. 64kb seems
+reasonable. If keysafe needs to store a larger key, it can chunk it up.
 
 Objects shoud be padded to a fixed size before they are encrypted, to
 prevent attackers from correlating and targeting particular objects based
 on size.
 
-When a client connects to a server, it sends a request. The server
-replies with a
-[proof of work puzzle](https://en.wikipedia.org/wiki/Client_Puzzle_Protocol)
-that the client must solve to make that request.
-This can be used by servers to avoid DOS attacks.
+## Client puzzles
+
+Assuming that the client communicates with the server over http:
+
+	PUT /keysafe/objects/N?S
+	GET /keysafe/objects/N?S
+
+Then, the S can be required to be a string such that argon2(N,S)
+starts with a given number of 0's. This allows the server to verify the
+client's proof of work without maintaining any state.
+
+The required number of 0's can be queried:
+
+	GET /keysafe/proofofwork/
+
+With a response like "zeros=4 iterations=1".
+
+(The server should only be able to control the number of iterations,
+not other argon2 parameters, to avoid forcing the client to use too much
+memory. Normally, the server will keep iterations small, probably 1,
+since it does need to calculate the argon2 hash itself.)
+
+Note that this scheme lets a client do work once for a given N and then
+request that N from multiple servers, as long as they have similar zeros=
+parameters (and the same iterations= parameters). This is probably a good
+thing; it means that keysafe doesn't need to do extra work when checking
+servers to get a shard.
+
+Servers can change their proof of work parameters as needed, but that can
+cause a client that was connected to the server to generate a bad POW.
+The server can respond with 402 Payment Required in that case, so the
+client knows to retry.
 
 ## Avoiding correlations
 

add
diff --git a/code.mdwn b/code.mdwn
index ba9ad89..2bd4dc0 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -27,6 +27,7 @@ In maintenance mode mostly, but I still have my hands in it somewhat.
 [[filters]]
 [[electrum-mnemonic]]
 [[brainfuck-monad]]
+[[zxcvbn-c]]
 [[scroll]]
 
 ## Past projects
diff --git a/code/zxcvbn-c.mdwn b/code/zxcvbn-c.mdwn
new file mode 100644
index 0000000..a73cf29
--- /dev/null
+++ b/code/zxcvbn-c.mdwn
@@ -0,0 +1,6 @@
+A quick haskell interface to the zxcvbn-c password strength estimation
+library.
+
+<http://hackage.haskell.org/package/zxcvbn-c>
+
+At some point, it would be good to implement this in pure haskell.

faq
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 0047cba..7e8bfd1 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -38,6 +38,7 @@ also makes it hard for an attacker to even find your encrypted secret key.
 
 For a more in-depth explanation, and some analysis of different attack
 vectors (and how keysafe thwarts them), see [[details]].
+Also, there's a [[FAQ]].
 
 ## News
 
@@ -71,74 +72,6 @@ Email <id@joeyh.name>
 
 Keysafe is licensed under the terms of the AGPL 3+
 
-## Comparisons with other approaches
-
-### paperkey
-
-Using paperkey to print out your gpg key and locking it in a safe is a great
-solution to gpg key backup. It requires a printer, a safe, and typing in many
-numbers to restore the key. It avoids all attack methods except physical
-theft, raids, and compromised printers. Gold standard.
-
-### storing secring.gpg in the cloud
-
-Some people copy secring.gpg to dropbox or similar to back it up,
-and rely on the gpg passphrase for security.
-
-Gpg uses between 1024 (the default) and 65011712 rounds of SHA-1 hashing of
-the passphrase. In 2012, a GPU could calculate 2 billion SHA-1 hashes
-per second, so this is not much of an impediment to password cracking at
-all.
-
-Assuming 100 gpg passphrases can be tried per second, and gpg is
-configured to use the maximum rounds (which it normally is NOT):
-
-* Strong passphrase (50 entropy): 21421231 GPU-years
-* Weak passphrase (30 entropy): 10 GPU-years
-* Super-weak passphrase (19 entropy): 2 GPU-days
-
-So this might be secure enough for some, but only with a really good
-passphrase. Probably, most people who copy their secring.gpg to
-the cloud have either a weakish passphrase, or have not tuned gpg to
-use maximum SHA-1 rounds, or both. So, they can probably be cracked in
-days to weeks.
-
-Compare these numbers with the cost to crack keysafe passwords
-(explained in [[details]]):
-
-* Strong password (50 entropy): 53553077761 CPU-years 
-* Weak password (30 entropy): 51072 CPU-years 
-* Super-weak password (19 entropy): 25 CPU-years 
-
-Big difference! Indeed, the design of gpg prevents a really expensive hash
-being used to protect against passphrase cracking, because it would slow down
-day-to-day use of gpg. Keysafe can make cracking the password much more
-expensive because it's only used for backup and restore.
-
-### non-sharded variant of keysafe
-
-Worth comparing the sharding approach with the most secure and simple
-non-sharded approach I can think of:
-
-* Generate decryption puzzle P, a byte chosen at random.
-* Generate K by argon2(password, salt=name+P), tuned to take 0.195 minutes.
-* AES encrypt (data + checksum) with K as the key.
-* upload to diverse locations using the gpg keyid as a unique ID
-  (with some complication to handle objects maliciously uploaded using
-  the same ID)
-
-The key encryption is the same as keysafe in this approach, so the
-difficulty in brute forcing an encrypted key is the same as described
-in [[details]]. Brute-forcing is only feasible for weak passwords.
-
-But brute forcing can start right away, and be performed by anyone,
-unlike with sharding where only two colluding servers can start brute
-forcing right away.
-
-So, this isn't too bad, but for all the users who use weak passwords
-(you know who you are (yes, you)), it's not as good a choice as keysafe.
-At worst, keysafe degrades to being as secure as this approach.
-
 ## Thanks
 
 Thanks to Anthony Towns for his help with keysafe's design.
diff --git a/code/keysafe/faq.mdwn b/code/keysafe/faq.mdwn
new file mode 100644
index 0000000..2d0b91a
--- /dev/null
+++ b/code/keysafe/faq.mdwn
@@ -0,0 +1,51 @@
+[[!toc]]
+
+### I copy secring.gpg to dropbox to back it up. Why bother with keysafe?
+
+So, you rely on your gpg passphrase for security.
+
+Gpg uses between 1024 (the default) and 65011712 rounds of SHA-1 hashing of
+the passphrase. In 2012, a GPU could calculate 2 billion SHA-1 hashes
+per second, so this is not much of an impediment to password cracking at
+all.
+
+Assuming 100 gpg passphrases can be tried per second, and gpg is
+configured to use the maximum rounds (which it normally is NOT):
+
+* Strong passphrase (50 entropy): 21421231 GPU-years
+* Weak passphrase (30 entropy): 10 GPU-years
+* Super-weak passphrase (19 entropy): 2 GPU-days
+
+So this might be secure enough for some, but only with a really good
+passphrase. Probably, most people who copy their secring.gpg to
+the cloud have either a weakish passphrase, or have not tuned gpg to
+use maximum SHA-1 rounds, or both. So, they can probably be cracked in
+days to weeks.
+
+Compare these numbers with the cost to crack keysafe passwords
+(explained in [[details]]):
+
+* Strong password (50 entropy): 53553077761 CPU-years 
+* Weak password (30 entropy): 51072 CPU-years 
+* Super-weak password (19 entropy): 25 CPU-years 
+
+Big difference! Indeed, the design of gpg prevents a really expensive hash
+being used to protect against passphrase cracking, because it would slow down
+day-to-day use of gpg. Keysafe can make cracking the password much more
+expensive because it's only used for backup and restore.
+
+### How does keysafe compare with paperkey?
+
+Using paperkey to print out your gpg key and locking it in a safe is a great
+solution to gpg key backup. It requires a printer, a safe, and typing in many
+numbers to restore the key. It avoids all attack methods except physical
+theft, raids, and compromised printers. Gold standard.
+
+### Is keysafe suitable for backing up bitcoin wallets?
+
+Not recommended. Use a brain wallet.
+
+Keysafe might be more secure than a paper wallet in some situations.
+It's happened before that someone has stumbled over someone else's
+list of electrum words amoung their papers. Using keysafe avoids such
+scenarios.

patreon
diff --git a/blog/entry/keysafe_alpha_release.mdwn b/blog/entry/keysafe_alpha_release.mdwn
index 30aa358..c9787ee 100644
--- a/blog/entry/keysafe_alpha_release.mdwn
+++ b/blog/entry/keysafe_alpha_release.mdwn
@@ -29,3 +29,5 @@ that's less than a year old, send me a benchmark:
 Bonus announcement: <http://hackage.haskell.org/package/zxcvbn-c/> is my
 quick Haskell interface to the C version of the zxcvbn password strength
 estimation library.
+
+PS: Past 50% of my goal on [Patreon](https://www.patreon.com/joeyh)!

typo
diff --git a/blog/entry/keysafe_alpha_release.mdwn b/blog/entry/keysafe_alpha_release.mdwn
index 86843a5..30aa358 100644
--- a/blog/entry/keysafe_alpha_release.mdwn
+++ b/blog/entry/keysafe_alpha_release.mdwn
@@ -22,7 +22,7 @@ to `~/.keysafe/objects/local/`
 
 I still need to tune the argon2 hash difficulty, and I need benchmark data
 to do so. If you have a top of the line laptop or server class machine
-that's less than a year old, send me a bechmark:
+that's less than a year old, send me a benchmark:
 
 	~/.local/bin/keysafe --benchmark | mail keysafe@joeyh.name -s benchmark
 

blog update
diff --git a/blog/entry/keysafe_alpha_release.mdwn b/blog/entry/keysafe_alpha_release.mdwn
new file mode 100644
index 0000000..86843a5
--- /dev/null
+++ b/blog/entry/keysafe_alpha_release.mdwn
@@ -0,0 +1,31 @@
+[[code/Keysafe]] securely backs up a gpg secret key or other short secret
+to the cloud. But not yet. Today's alpha release only supports storing the
+data locally, and I still need to finish tuning the argon2 hash
+difficulties with modern hardware. Other than that, I'm fairly happy with
+how it's turned out.
+
+Keysafe is written in Haskell, and many of the data types in it keep track
+of the estimated CPU time needed to create, decrypt, and brute-force them.
+Running that through a AWS SPOT pricing cost model lets keysafe estimate
+how much an attacker would need to spend to crack your password.
+
+[[code/keysafe/screenshots/4.png]]  
+(Above is for the password "makesad spindle stick")
+
+If you'd like to be an early adopter, install it like this:
+
+	sudo apt-get install haskell-stack libreadline-dev libargon2-0-dev zenity
+	stack install keysafe
+
+Run `~/.local/bin/keysafe --backup --store-local` to back up a gpg key
+to `~/.keysafe/objects/local/`
+
+I still need to tune the argon2 hash difficulty, and I need benchmark data
+to do so. If you have a top of the line laptop or server class machine
+that's less than a year old, send me a bechmark:
+
+	~/.local/bin/keysafe --benchmark | mail keysafe@joeyh.name -s benchmark
+
+Bonus announcement: <http://hackage.haskell.org/package/zxcvbn-c/> is my
+quick Haskell interface to the C version of the zxcvbn password strength
+estimation library.

de-hide
diff --git a/code/keysafe/news/version_0.20160819.mdwn b/code/keysafe/news/version_0.20160819.mdwn
index 38d9b31..1fe832a 100644
--- a/code/keysafe/news/version_0.20160819.mdwn
+++ b/code/keysafe/news/version_0.20160819.mdwn
@@ -1,5 +1,5 @@
-keysafe 0.20160819 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
+keysafe 0.20160819 released
+
    * First release of keysafe. This is not yet ready for production use.
    * Network support is not yet implemented, but --store-local works for
      testing with local data storage.
@@ -8,4 +8,4 @@ keysafe 0.20160819 released with [[!toggle text="these changes"]]
      1 data will be supported by every later version.
    * Argon2 hashes are not yet tuned for modern hardware, but only for my
      laptop. So, cracking cost estimates may be low. To help with this
-     tuning, run `keysafe --bechmark` and send the output to me."""]]
\ No newline at end of file
+     tuning, run `keysafe --bechmark` and send the output to me.

add news item for keysafe 0.20160819
diff --git a/code/keysafe/news/version_0.20160819.mdwn b/code/keysafe/news/version_0.20160819.mdwn
new file mode 100644
index 0000000..38d9b31
--- /dev/null
+++ b/code/keysafe/news/version_0.20160819.mdwn
@@ -0,0 +1,11 @@
+keysafe 0.20160819 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * First release of keysafe. This is not yet ready for production use.
+   * Network support is not yet implemented, but --store-local works for
+     testing with local data storage.
+   * Data backed up with keysafe version 0.* will not be able to be restored
+     by any later version! Once the data format stabalizes, keysafe version
+     1 data will be supported by every later version.
+   * Argon2 hashes are not yet tuned for modern hardware, but only for my
+     laptop. So, cracking cost estimates may be low. To help with this
+     tuning, run `keysafe --bechmark` and send the output to me."""]]
\ No newline at end of file

update
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 84131fa..0047cba 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -129,7 +129,7 @@ non-sharded approach I can think of:
 
 The key encryption is the same as keysafe in this approach, so the
 difficulty in brute forcing an encrypted key is the same as described
-above. Brute-forcing is only feasible for weak passwords.
+in [[details]]. Brute-forcing is only feasible for weak passwords.
 
 But brute forcing can start right away, and be performed by anyone,
 unlike with sharding where only two colluding servers can start brute

updates
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index fdae453..84131fa 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -73,6 +73,13 @@ Keysafe is licensed under the terms of the AGPL 3+
 
 ## Comparisons with other approaches
 
+### paperkey
+
+Using paperkey to print out your gpg key and locking it in a safe is a great
+solution to gpg key backup. It requires a printer, a safe, and typing in many
+numbers to restore the key. It avoids all attack methods except physical
+theft, raids, and compromised printers. Gold standard.
+
 ### storing secring.gpg in the cloud
 
 Some people copy secring.gpg to dropbox or similar to back it up,
@@ -86,14 +93,27 @@ all.
 Assuming 100 gpg passphrases can be tried per second, and gpg is
 configured to use the maximum rounds (which it normally is NOT):
 
-* Strong password (50 entropy): 21421231 GPU-years
-* Weak password (30 entropy): 10 GPU-years
-* Super-weak password (19 entropy): 2 GPU-days
+* Strong passphrase (50 entropy): 21421231 GPU-years
+* Weak passphrase (30 entropy): 10 GPU-years
+* Super-weak passphrase (19 entropy): 2 GPU-days
+
+So this might be secure enough for some, but only with a really good
+passphrase. Probably, most people who copy their secring.gpg to
+the cloud have either a weakish passphrase, or have not tuned gpg to
+use maximum SHA-1 rounds, or both. So, they can probably be cracked in
+days to weeks.
+
+Compare these numbers with the cost to crack keysafe passwords
+(explained in [[details]]):
+
+* Strong password (50 entropy): 53553077761 CPU-years 
+* Weak password (30 entropy): 51072 CPU-years 
+* Super-weak password (19 entropy): 25 CPU-years 
 
-Indeed, the design of gpg prevents a really expensive hash being used to 
-protect against passphrase cracking, because it would slow down day-to-day
-use of gpg. Keysafe can make cracking the password much more expensive
-because it's only used for backup and restore.
+Big difference! Indeed, the design of gpg prevents a really expensive hash
+being used to protect against passphrase cracking, because it would slow down
+day-to-day use of gpg. Keysafe can make cracking the password much more
+expensive because it's only used for backup and restore.
 
 ### non-sharded variant of keysafe
 

crop
diff --git a/code/keysafe/screenshots/4.png b/code/keysafe/screenshots/4.png
index 3c137a2..418844a 100644
Binary files a/code/keysafe/screenshots/4.png and b/code/keysafe/screenshots/4.png differ

typog
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index bfb5f44..fdae453 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -29,7 +29,7 @@ before backing up the key.
 
 Keysafe is designed so that it should take millions of dollars of computer
 time to crack any fairly good password. (This is accomplished using
-[Argon2](https://en.wikipedia.org/wiki/Argon2)).
+[Argon2](https://en.wikipedia.org/wiki/Argon2).)
 With a truely good password, such as four random words, the cracking cost
 should be many trillions of dollars.
 

reduce size
diff --git a/code/keysafe/screenshots/4.png b/code/keysafe/screenshots/4.png
index 31e0517..3c137a2 100644
Binary files a/code/keysafe/screenshots/4.png and b/code/keysafe/screenshots/4.png differ

foo
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 9946f01..bfb5f44 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -5,7 +5,8 @@ ten million systems. It's about making it possible for users to use gpg who
 currently don't, and who would find it too hard to use `paperkey` to back
 up and restore their key as they reinstall their laptop.
 
-Needs security review! May run over your dog! Not suitable for bitcoin keys!
+Not yet ready for production use! Needs security review!
+May run over your dog! Not suitable for bitcoin keys!
 
 ## Screenshots
 

rss
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 36b31a4..9946f01 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -38,6 +38,10 @@ also makes it hard for an attacker to even find your encrypted secret key.
 For a more in-depth explanation, and some analysis of different attack
 vectors (and how keysafe thwarts them), see [[details]].
 
+## News
+
+[[!inline pages="code/keysafe/news/* and !*/Discussion" show="3"]]
+
 ## Git repository
 
 `git clone git://git.joeyh.name/keysafe.git`

update
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 534123d..36b31a4 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -62,6 +62,10 @@ Note that there is a manpage, but stack doesn't install it yet.
 
 Email <id@joeyh.name>
 
+## License
+
+Keysafe is licensed under the terms of the AGPL 3+
+
 ## Comparisons with other approaches
 
 ### storing secring.gpg in the cloud

update
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 380f660..534123d 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -23,8 +23,8 @@ Keysafe checks your password strength (using the excellent but not perfect
 and shows an estimate of the cost to crack your password,
 before backing up the key. 
 
-[[screenshots/3.png]] [[screenshots/4.png]]
-(Entered password was "makesad spindle stick")
+[[screenshots/4.png]]  
+(Above is for the password "makesad spindle stick")
 
 Keysafe is designed so that it should take millions of dollars of computer
 time to crack any fairly good password. (This is accomplished using

reorg
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 2e198c7..380f660 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -9,11 +9,7 @@ Needs security review! May run over your dog! Not suitable for bitcoin keys!
 
 ## Screenshots
 
-[[screenshots/1.png]] [[screenshots/2.png]]
-
-[[screenshots/3.png]] [[screenshots/4.png]] (Entered password was "makesad spindle stick")
-
-[[screenshots/5.png]] [[screenshots/6.png]]
+See [[screenshots]]. (Keysafe can also run in text mode in a terminal.)
 
 ## How it works, basically
 
@@ -27,6 +23,9 @@ Keysafe checks your password strength (using the excellent but not perfect
 and shows an estimate of the cost to crack your password,
 before backing up the key. 
 
+[[screenshots/3.png]] [[screenshots/4.png]]
+(Entered password was "makesad spindle stick")
+
 Keysafe is designed so that it should take millions of dollars of computer
 time to crack any fairly good password. (This is accomplished using
 [Argon2](https://en.wikipedia.org/wiki/Argon2)).
@@ -41,7 +40,8 @@ vectors (and how keysafe thwarts them), see [[details]].
 
 ## Git repository
 
-Keysafe's git repository is <git://git.joeyh.name/keysafe.git>.
+`git clone git://git.joeyh.name/keysafe.git`
+
 All tags and commits in this repository are gpg signed, and you should
 verify the signature before using it.
 
diff --git a/code/keysafe/screenshots.mdwn b/code/keysafe/screenshots.mdwn
new file mode 100644
index 0000000..3e35cf2
--- /dev/null
+++ b/code/keysafe/screenshots.mdwn
@@ -0,0 +1,14 @@
+
+[[screenshots/1.png]]
+
+[[screenshots/2.png]]
+
+[[screenshots/3.png]] 
+
+(Entered password was "makesad spindle stick")
+
+[[screenshots/4.png]]  
+
+[[screenshots/5.png]]
+
+[[screenshots/6.png]]

wording
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 7679176..2e198c7 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -112,5 +112,4 @@ At worst, keysafe degrades to being as secure as this approach.
 
 ## Thanks
 
-Thanks to Anthony Towns for his help reviewing the security properties of
-keysafe.
+Thanks to Anthony Towns for his help with keysafe's design.

update
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index d3a7d78..7679176 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -5,345 +5,62 @@ ten million systems. It's about making it possible for users to use gpg who
 currently don't, and who would find it too hard to use `paperkey` to back
 up and restore their key as they reinstall their laptop.
 
-Not yet implemented! Needs security review! May run over your dog!
-Not suitable for bitcoin keys!
+Needs security review! May run over your dog! Not suitable for bitcoin keys!
 
-## Example
+## Screenshots
 
-	> keysafe --backup --name="email@example.com" --type=gpg
-	Password:
-	Verify password:
-	Please wait...
-	Key backed up to 3 servers, hosted by:
-		eff.org
-		riseup.net
-		joeyh.name
+[[screenshots/1.png]] [[screenshots/2.png]]
 
-	> keysafe --restore --name="email@example.com" --type=gpg
-	Password:
-	Please wait...
-	Key successfully restored.
+[[screenshots/3.png]] [[screenshots/4.png]] (Entered password was "makesad spindle stick")
 
-	[also, imagine a GUI here]
+[[screenshots/5.png]] [[screenshots/6.png]]
 
 ## How it works, basically
 
-The secret key is split into three shards, and each is uploaded to a server
-run by a different entity. Any two of the shards are sufficient to recover
-the original key. So any one server can go down and you can still recover
-the key.
-
-A password is used to encrypt the key. Using a strong password is highly
-recommended, especially for well-known keys. Brute forcing a strong
-password is infeasible with keysafe. Keysafe is designed so that
-even a well-chosen 8 letter long password protects a key for years. Basing
-passwords on dictionary words of course makes them much easier to crack.
-
-If your gpg key ID is not published to keyservers or elsewhere,
-it's very unlikely any attacker will find the encrypted key that keysafe
-stores, let alone devote years of work to cracking this unknown key.
-
-All you need to recover the key is the --name you used when backing it up,
-and the password.
-
-## Storing a key
-
-* Input password and name from user. The name is a combination of their own
-  name and a more obscure name (such as the name of their high-school
-  sweetheart).
-* Get the keyid of the key. (This can be any a public value
-  unique to the private key, eg a gpg keyid. It's only used to allow
-  storing multiple keys under a given name. If a gpg public key is not on the
-  keyservers, or the key is not a gpg key, can use "" for the keyid.)
-* Generate N by argon2(name, salt=keyid), tuned to take 10 minutes.
-* Generate N1-N3 by sha256 of N+1,2,3
-* Generate decryption puzzle P, a byte chosen at random.
-* Generate K by argon2(password, salt=name+P), tuned to take 0.195 minutes.
-* AES encrypt (data + checksum) with K as the key.
-* Shamir the encrypted key with N=2, M=3, yeilding S1-S3.
-* Servers reject attempts to store an object under a name that is
-  already in use.
-* Servers do not allow enumerating all objects stored,
-  and require a proof of work client puzzle to handle any request.
-* Upload S1-S3 to separate servers under the names N1-N3.
-  If any of the uploads is rejected as name already in use, 
-  ask user to enter a different name or password.
-
-So, storing a key takes 10 minutes.
-
-## Recovering a key
-
-* Input password and name from user.
-* Calculate N and N1-N2
-* Request N1-N3 from servers until two objects are available.
-* Shamir recombine the objects.
-* Guess a value for P.
-* Generate K by argon2(password, salt=name+P)
-* AES decrypt
-* Repeat with new P until checksum verifies.
-
-This takes 10 minutes to calculate N, plus on average 128 guesses of P.
-Total recovery time varies from 10 minutes to 60 minutes, with an
-average of 35 minutes.
-
-## Difficulty of brute forcing a single encrypted key
-
-* Assume we know the name and keyid, or have otherwise found a way to
-  determine the shards of a key. Download and recombine the shards.
-* Guess a password.
-* For each possible value of P, AES decrypt with
-  K = argon2(password, salt=name+P), and check if checksum verifies.  
-  This takes 0.195 minutes * 256 = 50 minutes total.
-* Repeat for next password.
-
-So, for a password with N entropy, the number of CPU-years of work
-is to crack it is: 2^(N-1)*50/60/24/365
-
-* Strong password (50 entropy): 53553077761 CPU-years
-* Weak password (30 entropy): 51072 CPU-years
-* Super-weak password (19 entropy): 25 CPU-years
-
-So, if an attacker is able to find the right shards for a secret key, it's
-feasible for them to crack super-weak and weak passwords, assuming the
-secret key is worth the cost of doing do. Stronger passwords quickly
-become infeasible to crack.
-
-## Attack methods
-
-An attacker who wants to target a particular person can guess the name they
-used, derive N1-N3, download two of S1-S3 and start brute forcing the
-password soon after the object is stored. This is the most likely attack
-method, so any user who could potentially be targeted like this should
-choose a strong password. A name that attackers are unlikely to guess
-prevents this attack, which is why keysafe prompts for not only the
-user's name, but also a more obscure name. Each name guess that the
-attacker makes takes 10 minutes of CPU time to generate N, as well
-as whatever work the servers impose to solve their client puzzle.
-
-The sharding prevents a single malicious server from blindly 
-guessing weak passwords across its entire collection of objects.
-It takes two servers colluding to try to recombine their shards.
-
-If recombining two shards yielded data which could be checked to see if
-it's valid, then it would become fairly inexpensive to try all combinations
-of shards, and obtain all the encrypted keys for further cracking. So it's
-important that there not be any checksum or header in addition to the AES
-encrypted data. (AES encrypted data cannot be distinguised from random
-garbage except by block size.) Get that right, and with N keysafe users, an
-attacker would need to try 2^(N-1) combinations of shards to find one on
-average, and would need to brute force the password of each combination.
-With only 20 keysafe users, assuming all users have super-weak passwords,
-this attack takes 13107200 years of CPU work (2^19*25) to crack one. With
-50 users, this jumps to quadrillions of years of CPU work.
-
-Colluding servers can try to correlate related objects based on access
-patterns and recombine pairs of those, and then brute force the password.
-The correlation needs to be very fine-grained for this to work.
-If 15 users' objects are all bucketed together by the correlation,
-then the attacker has 16384 combinations to try on average before
-finding a correct combination. Multiply by 5 years CPU work for cracking
-only super-weak passwords.
-
-Colluding servers who want to target a particular person
-can guess their N1-N3, check if those objects exist on the server, and
-begin brute-forcing the password. This is not much cheaper than the same
-attack performed by a third-party attacker, except that the attacker
-doesn't need to wait for an object to download from the server to check if
-it exists.
-
-A state-level entity may try to subpoena the entire contents of keysafe
-servers. Once 2 servers are compromised, the state-level entity can try the
-same attacks that colluding servers can use (but probably cannot use
-attacks involving correlation because the server operators should not be
-retaining the data needed for correlation). Of course, they probably have
-many more resources to throw at the problem. But with only 50 keysafe
-users, recombining shards and trying super-weak passwords would be
-prohibitively expensive as detailed above. So, a state-level entity
-will probably only find it feasible to target particular people.
-Since such an attack can be performed by anyone as discussed above,
-there seems to actually be no incentive for a state-level to subpoena data.
-
-A state-level entity's best bet at getting lots of keys is probably to use
-their resources to compromise keysafe servers, and modify them to log data.
-Then a correlation attack can be done as discussed above.
-
-A different kind of attack: Legal/extralegal action to get a 
-particular person's key removed from storage servers to try to
-deny them access to it. Or, to entirely take down storage servers.
-
-### Malicious data attack
-
-Two servers could collude to serve up malicious data to try to exploit the
-user's system.
-
-For example, if the user is using their gpg key to encrypt emails,
-and they restore a different gpg key, they might use it to encrypt with and
-then what they said could be decrypted by the attacker.
-
-To perform this attack, the attacker first has to manage to crack the user's
-password. Then they can replace the objects with malicious versions, encrypted
-with the same password.
-
-So, this is not too useful for gpg key replacement, since the attacker
-must already know the secret key. However, perhaps they could exploit bugs
-in gpg to compromise the user's system.
-
-## Server list
-
-There's a server list shipped with the client, giving their tor onion address
-and the organization providing the server. 

(Diff truncated)
obscure name
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index bcb7a26..d3a7d78 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -48,7 +48,9 @@ and the password.
 
 ## Storing a key
 
-* Input password and name from user.
+* Input password and name from user. The name is a combination of their own
+  name and a more obscure name (such as the name of their high-school
+  sweetheart).
 * Get the keyid of the key. (This can be any a public value
   unique to the private key, eg a gpg keyid. It's only used to allow
   storing multiple keys under a given name. If a gpg public key is not on the
@@ -112,8 +114,11 @@ An attacker who wants to target a particular person can guess the name they
 used, derive N1-N3, download two of S1-S3 and start brute forcing the
 password soon after the object is stored. This is the most likely attack
 method, so any user who could potentially be targeted like this should
-choose a strong password. A name that attackers are unlikely to guess also
-helps.
+choose a strong password. A name that attackers are unlikely to guess
+prevents this attack, which is why keysafe prompts for not only the
+user's name, but also a more obscure name. Each name guess that the
+attacker makes takes 10 minutes of CPU time to generate N, as well
+as whatever work the servers impose to solve their client puzzle.
 
 The sharding prevents a single malicious server from blindly 
 guessing weak passwords across its entire collection of objects.

comparison
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 52f926d..bcb7a26 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -342,6 +342,30 @@ Reading the key from gpg into locked memory is the other challenge.
 
 ## Comparisons with other approaches
 
+### storing secring.gpg in the cloud
+
+Some people copy secring.gpg to dropbox or similar to back it up,
+and rely on the gpg passphrase for security.
+
+Gpg uses between 1024 (the default) and 65011712 rounds of SHA-1 hashing of
+the passphrase. In 2012, a GPU could calculate 2 billion SHA-1 hashes
+per second, so this is not much of an impediment to password cracking at
+all.
+
+Assuming 100 gpg passphrases can be tried per second, and gpg is
+configured to use the maximum rounds:
+
+* Strong password (50 entropy): 21421231 GPU-years
+* Weak password (30 entropy): 10 GPU-years
+* Super-weak password (19 entropy): 2 GPU-days
+
+Indeed, the design of gpg prevents an expensive hash being used to 
+protect against passphrase cracking, because it would slow down day-to-day
+use of gpg. Keysafe can make cracking the password much more expensive
+because it's only used for backup and restore.
+
+### non-sharded variant of keysafe
+
 Worth comparing the sharding approach with the most secure and simple
 non-sharded approach I can think of:
 

minor tweaks to attack methods
and recalculated some attack costs
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index dbc8e4e..52f926d 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -50,7 +50,9 @@ and the password.
 
 * Input password and name from user.
 * Get the keyid of the key. (This can be any a public value
-  unique to the private key, eg a gpg keyid.)
+  unique to the private key, eg a gpg keyid. It's only used to allow
+  storing multiple keys under a given name. If a gpg public key is not on the
+  keyservers, or the key is not a gpg key, can use "" for the keyid.)
 * Generate N by argon2(name, salt=keyid), tuned to take 10 minutes.
 * Generate N1-N3 by sha256 of N+1,2,3
 * Generate decryption puzzle P, a byte chosen at random.
@@ -84,56 +86,60 @@ average of 35 minutes.
 
 ## Difficulty of brute forcing a single encrypted key
 
-* Assume we know the name.
+* Assume we know the name and keyid, or have otherwise found a way to
+  determine the shards of a key. Download and recombine the shards.
 * Guess a password.
 * For each possible value of P, AES decrypt with
-  argon2(password, salt=name+P), and check if checksum verifies.
-* Repeat for next password
+  K = argon2(password, salt=name+P), and check if checksum verifies.  
+  This takes 0.195 minutes * 256 = 50 minutes total.
+* Repeat for next password.
 
-So, for a password with N entropy, the number of years of work
-is: 2^(N-1)*50/60/24/365 (Not adjusted for moore's law.)
+So, for a password with N entropy, the number of CPU-years of work
+is to crack it is: 2^(N-1)*50/60/24/365
 
-* Strong password (50 entropy): 53553077761
-* Weak password (30 entropy): 51072
-* Super-weak password (19 entropy): 25
+* Strong password (50 entropy): 53553077761 CPU-years
+* Weak password (30 entropy): 51072 CPU-years
+* Super-weak password (19 entropy): 25 CPU-years
 
-## Attack methods
-
-(Assuming rainbow tables won't be of use due to the salting.)
+So, if an attacker is able to find the right shards for a secret key, it's
+feasible for them to crack super-weak and weak passwords, assuming the
+secret key is worth the cost of doing do. Stronger passwords quickly
+become infeasible to crack.
 
-An attacker who wants to target a particular person with a known keyid can
-guess their N1-N3, download two of S1-S3 and start brute forcing the
-password soon after the object is stored.
+## Attack methods
 
-If a gpg key is not published to keyservers, the attacker is unlikely to
-know its keyid, and so this method skips over such keys. And if the name
-used to store the key is different than the name on the keyservers, this
-method will skip over it too.
+An attacker who wants to target a particular person can guess the name they
+used, derive N1-N3, download two of S1-S3 and start brute forcing the
+password soon after the object is stored. This is the most likely attack
+method, so any user who could potentially be targeted like this should
+choose a strong password. A name that attackers are unlikely to guess also
+helps.
 
 The sharding prevents a single malicious server from blindly 
 guessing weak passwords across its entire collection of objects.
-
-Two servers can collude to recombine shards. If recombining two shards
-yielded data which can be checked to see if it's valid, then
-it would become fairly inexpensive to try all combinations of shards, and
-obtain all the encrypted keys for further cracking. So it's important that
-there not be any checksum or header in addition to the AES encrypted data.
-(AES encrypted data cannot be distinguised from random garbage except by
-block size.) Get that right, and with N keysafe users, an attacker
-would need to try 2^(N-1) combinations of shards to find one on average,
-and would need to brute force the password of each combination. With only
-20 keysafe users, even if all users have super-weak passwords,
-this attack takes 2621440 years of CPU work to crack one.
+It takes two servers colluding to try to recombine their shards.
+
+If recombining two shards yielded data which could be checked to see if
+it's valid, then it would become fairly inexpensive to try all combinations
+of shards, and obtain all the encrypted keys for further cracking. So it's
+important that there not be any checksum or header in addition to the AES
+encrypted data. (AES encrypted data cannot be distinguised from random
+garbage except by block size.) Get that right, and with N keysafe users, an
+attacker would need to try 2^(N-1) combinations of shards to find one on
+average, and would need to brute force the password of each combination.
+With only 20 keysafe users, assuming all users have super-weak passwords,
+this attack takes 13107200 years of CPU work (2^19*25) to crack one. With
+50 users, this jumps to quadrillions of years of CPU work.
 
 Colluding servers can try to correlate related objects based on access
 patterns and recombine pairs of those, and then brute force the password.
 The correlation needs to be very fine-grained for this to work.
 If 15 users' objects are all bucketed together by the correlation,
 then the attacker has 16384 combinations to try on average before
-finding the right one. Multiply by 5 years for cracking only super-weak
-passwords.
+finding a correct combination. Multiply by 5 years CPU work for cracking
+only super-weak passwords.
 
-Colluding servers who want to target a particular person with a known keyid
+Colluding servers who want to target a particular person
 can guess their N1-N3, check if those objects exist on the server, and
 begin brute-forcing the password. This is not much cheaper than the same
 attack performed by a third-party attacker, except that the attacker
@@ -147,9 +153,9 @@ attacks involving correlation because the server operators should not be
 retaining the data needed for correlation). Of course, they probably have
 many more resources to throw at the problem. But with only 50 keysafe
 users, recombining shards and trying super-weak passwords would be
-prohibitively expensive (562 trillion CPU years). So, a state-level entity
-will probably only find it feasible to target particular people with known
-keyids. Since such an attack can be performed by anyone as discussed above,
+prohibitively expensive as detailed above. So, a state-level entity
+will probably only find it feasible to target particular people.
+Since such an attack can be performed by anyone as discussed above,
 there seems to actually be no incentive for a state-level to subpoena data.
 
 A state-level entity's best bet at getting lots of keys is probably to use

Added a comment: Great!!
diff --git a/blog/entry/git-annex_v6/comment_2_4ab849a23713470fb99e4bd688056d8b._comment b/blog/entry/git-annex_v6/comment_2_4ab849a23713470fb99e4bd688056d8b._comment
new file mode 100644
index 0000000..9732dbb
--- /dev/null
+++ b/blog/entry/git-annex_v6/comment_2_4ab849a23713470fb99e4bd688056d8b._comment
@@ -0,0 +1,10 @@
+[[!comment format=mdwn
+ username="Oliver@5ecb9875ed5bbd2b3e48407518c07a27d754571c"
+ nickname="Oliver"
+ subject="Great!!"
+ date="2016-08-15T10:22:08Z"
+ content="""
+Wow, I've been folowing git-annex from the beginning. First I thought it is way to complicated. Thus I tried to find a different way to solve my needs. After thinking about it really hard I came to the concolusion that a system that solve all my needs has to be as complicated as git annex. Now I just discovered version 6 and largefiles with mimetype support (https://git-annex.branchable.com/tips/largefiles/). This solution still fullfills all my needs and now it is easy to use, too. Just great! Thank you very much! You really superseeded git lfs.
+Best regards
+Oliver
+"""]]

add news item for moreutils 0.60
diff --git a/code/moreutils/news/version_0.55.mdwn b/code/moreutils/news/version_0.55.mdwn
deleted file mode 100644
index dfe7d60..0000000
--- a/code/moreutils/news/version_0.55.mdwn
+++ /dev/null
@@ -1,6 +0,0 @@
-moreutils 0.55 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * parallel: serialise output through internal pipe. Closes: #[704125](http://bugs.debian.org/704125)
-     Thanks, Nicolas Schier.
-   * sponge: add append option '-a'. Closes: #[623197](http://bugs.debian.org/623197)
-     Thanks, Nicolas Schier."""]]
\ No newline at end of file
diff --git a/code/moreutils/news/version_0.60.mdwn b/code/moreutils/news/version_0.60.mdwn
new file mode 100644
index 0000000..51cfb60
--- /dev/null
+++ b/code/moreutils/news/version_0.60.mdwn
@@ -0,0 +1,16 @@
+moreutils 0.60 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * New implementation of isutf8 by Julien Palard.
+     - Noncharacters (ending with 0xFFFF and 0xFFFE) were considered
+       invalid when encoded in utf8, according to the unicode standard
+       they are valid: "However, they are not illegal in interchange, nor
+       does their presence cause Unicode text to be ill-formed."
+     - \xf4\xbf\xbf\xbf was considered valid UTF8, which is not: after
+       0xF4 the following byte should be between 80 and 8F.
+     - This implementation does not try to decode the stream, so it checks
+       it faster.
+     - Add --list option. Closes: #[691330](http://bugs.debian.org/691330)
+   * Support bullding in Cygwin.
+     Thanks, StalkR
+   * OSX build fix.
+     Thanks, Tony Kelman."""]]
\ No newline at end of file

put P in the salt
name is pretty low entropy, so putting P there will make rainbow
tables 256 times as expensive.
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 0cf1782..dbc8e4e 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -54,7 +54,7 @@ and the password.
 * Generate N by argon2(name, salt=keyid), tuned to take 10 minutes.
 * Generate N1-N3 by sha256 of N+1,2,3
 * Generate decryption puzzle P, a byte chosen at random.
-* Generate K by argon2(password+P, salt=name), tuned to take 0.195 minutes.
+* Generate K by argon2(password, salt=name+P), tuned to take 0.195 minutes.
 * AES encrypt (data + checksum) with K as the key.
 * Shamir the encrypted key with N=2, M=3, yeilding S1-S3.
 * Servers reject attempts to store an object under a name that is
@@ -74,7 +74,7 @@ So, storing a key takes 10 minutes.
 * Request N1-N3 from servers until two objects are available.
 * Shamir recombine the objects.
 * Guess a value for P.
-* Generate K by argon2(password+P, salt=name)
+* Generate K by argon2(password, salt=name+P)
 * AES decrypt
 * Repeat with new P until checksum verifies.
 
@@ -87,7 +87,7 @@ average of 35 minutes.
 * Assume we know the name.
 * Guess a password.
 * For each possible value of P, AES decrypt with
-  argon2(password+P, salt=name), and check if checksum verifies.
+  argon2(password, salt=name+P), and check if checksum verifies.
 * Repeat for next password
 
 So, for a password with N entropy, the number of years of work
@@ -340,7 +340,7 @@ Worth comparing the sharding approach with the most secure and simple
 non-sharded approach I can think of:
 
 * Generate decryption puzzle P, a byte chosen at random.
-* Generate K by argon2(password+P, salt=name), tuned to take 0.195 minutes.
+* Generate K by argon2(password, salt=name+P), tuned to take 0.195 minutes.
 * AES encrypt (data + checksum) with K as the key.
 * upload to diverse locations using the gpg keyid as a unique ID
   (with some complication to handle objects maliciously uploaded using

improved decryption puzzle approach
diff --git a/code.mdwn b/code.mdwn
index ee38075..ba9ad89 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -7,6 +7,7 @@ The stuff that's swapped into my local cache at the moment.
 
 [[git-annex]]
 [[propellor]]
+[[keysafe]]
 [[concurrent-output]]
 [[myrepos|mr]]
 [[etckeeper]]
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index adbe504..0cf1782 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -51,11 +51,11 @@ and the password.
 * Input password and name from user.
 * Get the keyid of the key. (This can be any a public value
   unique to the private key, eg a gpg keyid.)
-* Generate K by argon2(password, salt=name), tuned to take 10 minutes.
 * Generate N by argon2(name, salt=keyid), tuned to take 10 minutes.
 * Generate N1-N3 by sha256 of N+1,2,3
-* Generate random R
-* AES encrypt (data + checksum) with (K|R) as the key.
+* Generate decryption puzzle P, a byte chosen at random.
+* Generate K by argon2(password+P, salt=name), tuned to take 0.195 minutes.
+* AES encrypt (data + checksum) with K as the key.
 * Shamir the encrypted key with N=2, M=3, yeilding S1-S3.
 * Servers reject attempts to store an object under a name that is
   already in use.
@@ -65,37 +65,37 @@ and the password.
   If any of the uploads is rejected as name already in use, 
   ask user to enter a different name or password.
 
-R needs to be in a range tuned so that AES needs to decrypt data for
-at least 1 minute on a GPU. Hopefully on a CPU the decrypt time
-will be less than an hour.
-
-(Alternatively, use a tunable client puzzle to encode R.
-Store the puzzle alongside the encrypted data.
-Use Argon2, which is GPU and ASIC resistent.
-Probably more on the order of 10 minutes per CPU core for this approach.)
+So, storing a key takes 10 minutes.
 
 ## Recovering a key
 
 * Input password and name from user.
-* Generate K, N1-N3 as above.
+* Calculate N and N1-N2
 * Request N1-N3 from servers until two objects are available.
 * Shamir recombine the objects.
-* Guess R and AES decrypt, repeating until checksum verifies.
+* Guess a value for P.
+* Generate K by argon2(password+P, salt=name)
+* AES decrypt
+* Repeat with new P until checksum verifies.
+
+This takes 10 minutes to calculate N, plus on average 128 guesses of P.
+Total recovery time varies from 10 minutes to 60 minutes, with an
+average of 35 minutes.
 
 ## Difficulty of brute forcing a single encrypted key
 
 * Assume we know the name.
 * Guess a password.
-* K = argon2(password, salt=name) -- 10 minutes CPU work
-* AES decrypt with (K+R) forall R -- 1 minute GPU work
-* Repeat for next password.
+* For each possible value of P, AES decrypt with
+  argon2(password+P, salt=name), and check if checksum verifies.
+* Repeat for next password
 
-So, for password with N entropy, the number of years of work
-is: 2^(N-1)*11/60/24/365 (Not adjusted for moore's law.)
+So, for a password with N entropy, the number of years of work
+is: 2^(N-1)*50/60/24/365 (Not adjusted for moore's law.)
 
-* Strong password (50 entropy): 11781677107
-* Weak password (30 entropy): 11235
-* Super-weak password (19 entropy): 5 years
+* Strong password (50 entropy): 53553077761
+* Weak password (30 entropy): 51072
+* Super-weak password (19 entropy): 25
 
 ## Attack methods
 
@@ -306,86 +306,6 @@ merely the number of rounds, as that would allow an attacker to hash for
 each version's number of rounds in one pass. Instead, vary the hash
 memory parameter.
 
-## maybe use tunable work puzzles (instead of more expensive AES decryption)
-
-I stumbled upon this interesting paper on tunable proof of work puzzles
-that can expose information when solved:
-<https://www1.ericsson.com/res/docs/2015/random-access-procedure.pdf>  
-(With a low probabiliy of finding a bad solution.)
-
-That's effectively a way to encrypt data such that decryption takes a
-tunable amount of work.
-
-The puzzle is basically generated by:
-
-	F(k || d || r)
-
-Where F is a cryptographic function, k is a secret value, d is a difficutly
-bit string, and r is the result exposed by solving the puzzle.
-
-This could be used to encrypt shards. The decrypted 
-shard is r, and for k, use part of the password's entropy pool.
-
-The same k can be reused to encrypt *all* shards. So, the entropy pool
-is not split up between the shards.
-
-To decrypt a shard, keysafe would only need to solve the puzzle once,
-because it knows k. In the rare case when it finds a bad solution, it would
-notice when checking the validity of the combined shards, and it would
-then need to resume looking for a solution.
-
-A brute force shard decryption attack (that has not cracked the
-namesecret) would have to guess values for k (or guess passwords and
-derive k) and solve the puzzle repeatedly. The puzzle can be tuned so
-that this takes infeasibly long.
-
-An attacker who has already brute forced the namesecret can make
-educated guesses about the entropy pool, and k, so this
-won't slow them down as much.
-
-## more expensive AES decryption
-
-Idea from Anthony Towns
-
-> Hmm, interesting. Can you do this a bit more simply though? I'm
-> thinking:
-> 
->  * secret key is 16kB
->  * user decides "i'm willing to spend 1 hour of CPU on decryption"
->  * AES speed is ~110MB/second, so 360GB/hour which gives about 2**24
->    secret key decryptions
-
-(Really AES can be much faster, 3-7 GB/s on CPUs and there is GPU
-accelleration, so this needs tuning..)
-
->  * choose a random number 24 bit number, R, stored in a 64 bit unsigned
->    int
-> 
->  * set secret key,
->       S = sha256( R || slowhash( "ajt@debian.org" A B C X "gpg" ))
->  * encrypt the gpg secret key data as:
->       E_S( SHA256( data ); data )
->  * shard the encrypted gpg secret key data, etc
-> 
-> Then after reassembling the shards, and knowing A,B and X, but
-> bruteforcing each possible C, you not only have to run the slowhash, but
-> you have to do 360GB's of trial decryption as well.
-> 
-> The above has the drawback that if one of the shards is corrupted, you'll
-> have to do three hours of trial decryption to work out which one it was
-> though. You could mitigate that by adding a per-shard checksum:
-> 
->     ID_n = sha256( "name" CHK_n )
->     CHK_n = slowhash( "chk" A X "ajt@debian.org" "gpg" )
-> 
->     object_n = SHARD + HMAC( CHK_n, SHARD )
-> 
-> That avoids any increase in the setup time, means that you can only fake
-> the checksum by discovering A and X (and performing a slowhash on them)
-> or breaking sha256, and doesn't provide any easier ways to brute force
-> things than figuring out a preimage for the object id. So yeah, I think
-> that works.
-
 ## maybe use blind signatures
 
 > I think you could use [blind signatures](https://en.wikipedia.org/wiki/Blind_signature) 
@@ -419,24 +339,24 @@ Reading the key from gpg into locked memory is the other challenge.
 Worth comparing the sharding approach with the most secure and simple
 non-sharded approach I can think of:
 
-* Generate K by argon2(password, salt=name)
-* Generate random R (same method as in the sharded approach).
-* AES encrypt (data + checksum) with (K|R) as the key.
+* Generate decryption puzzle P, a byte chosen at random.
+* Generate K by argon2(password+P, salt=name), tuned to take 0.195 minutes.
+* AES encrypt (data + checksum) with K as the key.
 * upload to diverse locations using the gpg keyid as a unique ID
   (with some complication to handle objects maliciously uploaded using
   the same ID)
 
-The key encryption is the same in this approach, so the difficulty in brute
-forcing an encrypted key is the same as described above. Brute-forcing
-is only feasible for weak passwords.
+The key encryption is the same as keysafe in this approach, so the
+difficulty in brute forcing an encrypted key is the same as described
+above. Brute-forcing is only feasible for weak passwords.
 
-Brute forcing can start right away, and be performed by anyone,
+But brute forcing can start right away, and be performed by anyone,
 unlike with sharding where only two colluding servers can start brute
 forcing right away.
 

(Diff truncated)
Revert "puzzle IV"
This reverts commit aa44bcfc1a339ee904995e3e3a3ed2a7a567be63.
Not a good idea to use IV, because all the parts of the IV that are 0
will not obscure the data in the first block at all.
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index c0e4026..adbe504 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -54,11 +54,8 @@ and the password.
 * Generate K by argon2(password, salt=name), tuned to take 10 minutes.
 * Generate N by argon2(name, salt=keyid), tuned to take 10 minutes.
 * Generate N1-N3 by sha256 of N+1,2,3
-* Generate IV, which is an AES IV consisting of some number of random
-  bytes followed by NULLs. This should be tuned so that AES
-  needs to decrypt data for at least 1 minute on a GPU to guess it.
-  Hopefully on a CPU the decrypt time will be less than an hour.
-* AES encrypt (data + checksum) with K as the key.
+* Generate random R
+* AES encrypt (data + checksum) with (K|R) as the key.
 * Shamir the encrypted key with N=2, M=3, yeilding S1-S3.
 * Servers reject attempts to store an object under a name that is
   already in use.
@@ -68,10 +65,14 @@ and the password.
   If any of the uploads is rejected as name already in use, 
   ask user to enter a different name or password.
 
-(Alternatively, instead of a random IV, use a tunable client puzzle to
-encode K. Store the puzzle alongside the encrypted data. Use Argon2, which
-is GPU and ASIC resistent. Probably more on the order of 10 minutes per CPU
-core for this approach.)
+R needs to be in a range tuned so that AES needs to decrypt data for
+at least 1 minute on a GPU. Hopefully on a CPU the decrypt time
+will be less than an hour.
+
+(Alternatively, use a tunable client puzzle to encode R.
+Store the puzzle alongside the encrypted data.
+Use Argon2, which is GPU and ASIC resistent.
+Probably more on the order of 10 minutes per CPU core for this approach.)
 
 ## Recovering a key
 
@@ -385,11 +386,6 @@ accelleration, so this needs tuning..)
 > things than figuring out a preimage for the object id. So yeah, I think
 > that works.
 
-Now keysafe is using a simpler approach to the same idea: The IV used in AES
-encryption is not stored, and so must be guessed to decrypt data.
-The initial several bytes of the IV are random and the rest NULL,
-which allows tuning the amount of work that must be done.
-
 ## maybe use blind signatures
 
 > I think you could use [blind signatures](https://en.wikipedia.org/wiki/Blind_signature) 

puzzle IV
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index adbe504..c0e4026 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -54,8 +54,11 @@ and the password.
 * Generate K by argon2(password, salt=name), tuned to take 10 minutes.
 * Generate N by argon2(name, salt=keyid), tuned to take 10 minutes.
 * Generate N1-N3 by sha256 of N+1,2,3
-* Generate random R
-* AES encrypt (data + checksum) with (K|R) as the key.
+* Generate IV, which is an AES IV consisting of some number of random
+  bytes followed by NULLs. This should be tuned so that AES
+  needs to decrypt data for at least 1 minute on a GPU to guess it.
+  Hopefully on a CPU the decrypt time will be less than an hour.
+* AES encrypt (data + checksum) with K as the key.
 * Shamir the encrypted key with N=2, M=3, yeilding S1-S3.
 * Servers reject attempts to store an object under a name that is
   already in use.
@@ -65,14 +68,10 @@ and the password.
   If any of the uploads is rejected as name already in use, 
   ask user to enter a different name or password.
 
-R needs to be in a range tuned so that AES needs to decrypt data for
-at least 1 minute on a GPU. Hopefully on a CPU the decrypt time
-will be less than an hour.
-
-(Alternatively, use a tunable client puzzle to encode R.
-Store the puzzle alongside the encrypted data.
-Use Argon2, which is GPU and ASIC resistent.
-Probably more on the order of 10 minutes per CPU core for this approach.)
+(Alternatively, instead of a random IV, use a tunable client puzzle to
+encode K. Store the puzzle alongside the encrypted data. Use Argon2, which
+is GPU and ASIC resistent. Probably more on the order of 10 minutes per CPU
+core for this approach.)
 
 ## Recovering a key
 
@@ -386,6 +385,11 @@ accelleration, so this needs tuning..)
 > things than figuring out a preimage for the object id. So yeah, I think
 > that works.
 
+Now keysafe is using a simpler approach to the same idea: The IV used in AES
+encryption is not stored, and so must be guessed to decrypt data.
+The initial several bytes of the IV are random and the rest NULL,
+which allows tuning the amount of work that must be done.
+
 ## maybe use blind signatures
 
 > I think you could use [blind signatures](https://en.wikipedia.org/wiki/Blind_signature) 

typo
diff --git a/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment b/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
index 40bd9e3..395222b 100644
--- a/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
+++ b/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
@@ -10,7 +10,7 @@ I can only increment that number here by overwriting my original
 
 "mom123" was being used internally as an rough example of a 19 bit entropy
 password, calculated per Shannon, so without using a dictionary. It should
-not have leaked out into the user-visible part of the ocumentation.
+not have leaked out into the user-visible part of the documentation.
 
 And of course it's referring to the time needed to crack the password
 in the context of keysafe, not time to crack it in the context of having a

reword
diff --git a/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment b/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
index 937722f..40bd9e3 100644
--- a/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
+++ b/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
@@ -4,14 +4,13 @@
  date="2016-08-11T23:11:07Z"
  content="""
 @alkadim, I wonder what number of all the conversations that have
-included accusations have gone on to be constructive? I can only increment
-that number here by overwriting my original (predictively defensive)
-response.
+included accusations of snakeoil have gone on to be constructive?
+I can only increment that number here by overwriting my original
+(predictively defensive) response.
 
-"mom123" was being used internally as an example of a 19 bit entropy
-password, calculated per Shannon, so without using a dictionary.
-It should not have leaked out into the user-visible part of the
-ocumentation. Of course the document is a draft anyway.
+"mom123" was being used internally as an rough example of a 19 bit entropy
+password, calculated per Shannon, so without using a dictionary. It should
+not have leaked out into the user-visible part of the ocumentation.
 
 And of course it's referring to the time needed to crack the password
 in the context of keysafe, not time to crack it in the context of having a

improve password strengh descriptions
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 1d75fe3..adbe504 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -35,12 +35,13 @@ the key.
 
 A password is used to encrypt the key. Using a strong password is highly
 recommended, especially for well-known keys. Brute forcing a strong
-password is infeasible with keysafe. Weaker passwords still take years
-to brute force.
+password is infeasible with keysafe. Keysafe is designed so that
+even a well-chosen 8 letter long password protects a key for years. Basing
+passwords on dictionary words of course makes them much easier to crack.
 
 If your gpg key ID is not published to keyservers or elsewhere,
 it's very unlikely any attacker will find the encrypted key that keysafe
-stores, let alone devote years of work to crack this unknown key.
+stores, let alone devote years of work to cracking this unknown key.
 
 All you need to recover the key is the --name you used when backing it up,
 and the password.
@@ -92,8 +93,8 @@ Probably more on the order of 10 minutes per CPU core for this approach.)
 So, for password with N entropy, the number of years of work
 is: 2^(N-1)*11/60/24/365 (Not adjusted for moore's law.)
 
-* Strong password (50 entropy): 11781677107 years
-* Weak password (30 entropy): 11235 years
+* Strong password (50 entropy): 11781677107
+* Weak password (30 entropy): 11235
 * Super-weak password (19 entropy): 5 years
 
 ## Attack methods

tune down
diff --git a/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment b/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
index eb5197a..937722f 100644
--- a/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
+++ b/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
@@ -3,17 +3,18 @@
  subject="""comment 5"""
  date="2016-08-11T23:11:07Z"
  content="""
-@alkadim, of course it's referring to the time needed to crack the password
-in the context of keysafe. Ie, each try involves the expensive process of
-deriving an AES key (say 10 CPU-minutes), and once the key is derived it's
-also made expensive to use the key (say 1 GPU-minute).
+@alkadim, I wonder what number of all the conversations that have
+included accusations have gone on to be constructive? I can only increment
+that number here by overwriting my original (predictively defensive)
+response.
 
-Password entropy calculation is not a very exact science, so of
-course an example like "mom123" assumes "mom" and "123" are not in the
-dictionary. In which case I think its entropy would be somewhere around 19
-bits. Of course they are in the dictionary in real life. "9ibz02" would be
-a better example of a password that really probably has an entropy of ~15-19.
+"mom123" was being used internally as an example of a 19 bit entropy
+password, calculated per Shannon, so without using a dictionary.
+It should not have leaked out into the user-visible part of the
+ocumentation. Of course the document is a draft anyway.
 
-(Assusing in-progress design drafts of being snake oil is probably not the
-most constructuve look.)
+And of course it's referring to the time needed to crack the password
+in the context of keysafe, not time to crack it in the context of having a
+password file or something. The document explains why each password
+guess involves a 10 CPU-minute calculation and a 1 GPU-minute calculation.
 """]]

remove the mom123 example because it was too confusing
diff --git a/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment b/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
new file mode 100644
index 0000000..eb5197a
--- /dev/null
+++ b/blog/entry/keysafe/comment_5_5ea418b81e02998683f51da2bae91c08._comment
@@ -0,0 +1,19 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 5"""
+ date="2016-08-11T23:11:07Z"
+ content="""
+@alkadim, of course it's referring to the time needed to crack the password
+in the context of keysafe. Ie, each try involves the expensive process of
+deriving an AES key (say 10 CPU-minutes), and once the key is derived it's
+also made expensive to use the key (say 1 GPU-minute).
+
+Password entropy calculation is not a very exact science, so of
+course an example like "mom123" assumes "mom" and "123" are not in the
+dictionary. In which case I think its entropy would be somewhere around 19
+bits. Of course they are in the dictionary in real life. "9ibz02" would be
+a better example of a password that really probably has an entropy of ~15-19.
+
+(Assusing in-progress design drafts of being snake oil is probably not the
+most constructuve look.)
+"""]]
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index a6bee3c..1d75fe3 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -35,8 +35,8 @@ the key.
 
 A password is used to encrypt the key. Using a strong password is highly
 recommended, especially for well-known keys. Brute forcing a strong
-password is infeasible with keysafe. Even a weak password like
-"mom123" takes 1 year of GPU time to brute force.
+password is infeasible with keysafe. Weaker passwords still take years
+to brute force.
 
 If your gpg key ID is not published to keyservers or elsewhere,
 it's very unlikely any attacker will find the encrypted key that keysafe
@@ -94,7 +94,7 @@ is: 2^(N-1)*11/60/24/365 (Not adjusted for moore's law.)
 
 * Strong password (50 entropy): 11781677107 years
 * Weak password (30 entropy): 11235 years
-* Super-weak password (19 entropy) (eg "mom123"): 5 years
+* Super-weak password (19 entropy): 5 years
 
 ## Attack methods
 

more on attacks
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index 36150cb..a6bee3c 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -102,10 +102,7 @@ is: 2^(N-1)*11/60/24/365 (Not adjusted for moore's law.)
 
 An attacker who wants to target a particular person with a known keyid can
 guess their N1-N3, download two of S1-S3 and start brute forcing the
-encryption soon after the object is stored. However, it's hard for an
-attacker to discover all objects stored on a server. This protects
-uninteresting users who used weak passwords, because they are unlikely to
-become a target for cracking.
+password soon after the object is stored.
 
 If a gpg key is not published to keyservers, the attacker is unlikely to
 know its keyid, and so this method skips over such keys. And if the name
@@ -116,23 +113,51 @@ The sharding prevents a single malicious server from blindly
 guessing weak passwords across its entire collection of objects.
 
 Two servers can collude to recombine shards. If recombining two shards
-yields data which can be checked to see if it's valid, then
-it becomes fairly inexpensive to try all combinations of shards, and
+yielded data which can be checked to see if it's valid, then
+it would become fairly inexpensive to try all combinations of shards, and
 obtain all the encrypted keys for further cracking. So it's important that
-there not be any checksum or header in addition to the AES encrypted data
+there not be any checksum or header in addition to the AES encrypted data.
 (AES encrypted data cannot be distinguised from random garbage except by
-block size.)
-
-Or colluding servers can try to likely correlate related objects and
-recombine pairs of those. The more users use keysafe, the harder
-this becomes.
-
-(Note that it's easy to determine an object's shard number,
-which reduces the difficulty of a recombination attack by 2^3.)
+block size.) Get that right, and with N keysafe users, an attacker
+would need to try 2^(N-1) combinations of shards to find one on average,
+and would need to brute force the password of each combination. With only
+20 keysafe users, even if all users have super-weak passwords,
+this attack takes 2621440 years of CPU work to crack one.
+
+Colluding servers can try to correlate related objects based on access
+patterns and recombine pairs of those, and then brute force the password.
+The correlation needs to be very fine-grained for this to work.
+If 15 users' objects are all bucketed together by the correlation,
+then the attacker has 16384 combinations to try on average before
+finding the right one. Multiply by 5 years for cracking only super-weak
+passwords.
+
+Colluding servers who want to target a particular person with a known keyid
+can guess their N1-N3, check if those objects exist on the server, and
+begin brute-forcing the password. This is not much cheaper than the same
+attack performed by a third-party attacker, except that the attacker
+doesn't need to wait for an object to download from the server to check if
+it exists.
+
+A state-level entity may try to subpoena the entire contents of keysafe
+servers. Once 2 servers are compromised, the state-level entity can try the
+same attacks that colluding servers can use (but probably cannot use
+attacks involving correlation because the server operators should not be
+retaining the data needed for correlation). Of course, they probably have
+many more resources to throw at the problem. But with only 50 keysafe
+users, recombining shards and trying super-weak passwords would be
+prohibitively expensive (562 trillion CPU years). So, a state-level entity
+will probably only find it feasible to target particular people with known
+keyids. Since such an attack can be performed by anyone as discussed above,
+there seems to actually be no incentive for a state-level to subpoena data.
+
+A state-level entity's best bet at getting lots of keys is probably to use
+their resources to compromise keysafe servers, and modify them to log data.
+Then a correlation attack can be done as discussed above.
 
 A different kind of attack: Legal/extralegal action to get a 
 particular person's key removed from storage servers to try to
-deny them access to it.
+deny them access to it. Or, to entirely take down storage servers.
 
 ### Malicious data attack
 
@@ -218,8 +243,9 @@ Ways the server could draw correlations include:
   (Avoid by waiting some period of time between retrieving shards.
   Although, this makes key recovery take longer, which could be
   frustrating..)
-* Any user ID associated with the data.  
-  (Avoid by allowing anyone to store data and don't associate data with any user ID.)
+* A user ID associated with the data.  
+  (Avoid by allowing anyone to store data and don't associate data with
+  any user ID.)
 * Same sized objects may be related shares.  
   (Avoid by making all objects stored be a standard size.)
 

Added a comment: Brute-forcing-related claims
diff --git a/blog/entry/keysafe/comment_4_3cc9b708e48c3cb660037478cb738990._comment b/blog/entry/keysafe/comment_4_3cc9b708e48c3cb660037478cb738990._comment
new file mode 100644
index 0000000..701eeba
--- /dev/null
+++ b/blog/entry/keysafe/comment_4_3cc9b708e48c3cb660037478cb738990._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="alkadim@16dbdbfdb5d7aee5bbfeaa6d1a393f900cd6b341"
+ nickname="alkadim"
+ subject="Brute-forcing-related claims"
+ date="2016-08-11T19:07:37Z"
+ content="""
+I was surprised to read the following snake-oily statement:
+
+> Even a weak password like \"mom123\" takes 1 year of GPU time to brute force.
+
+Upon reading that I thought that maybe you were referring not to the weak password, but to the derived key itself (though, that didn't make that much sense either).
+
+But then I saw this:
+
+> Super-weak password (19 entropy) (eg \"mom123\"): 5 years
+
+Excuse me, but \"19 entropy\"? 19 bogons of entropy perhaps. Because \"mom123\" sure as hell does not have anywhere near 19 bits of entropy. In particular, for the case in question, that of password-cracking, it's much closer to 0. Also, things like that are in every dictionary and dictionary generator out there. So making claims about brute-force-resistance based on some foobar entropy count make no sense in my opinion.
+"""]]

update
diff --git a/code/keysafe.mdwn b/code/keysafe.mdwn
index c7b59d7..36150cb 100644
--- a/code/keysafe.mdwn
+++ b/code/keysafe.mdwn
@@ -49,10 +49,10 @@ and the password.
 
 * Input password and name from user.
 * Get the keyid of the key. (This can be any a public value
-  unique to the private key.)
+  unique to the private key, eg a gpg keyid.)
 * Generate K by argon2(password, salt=name), tuned to take 10 minutes.
-* Generate N1-N3 by argon2(name, salt=I+keyid), tuned to take 10 minutes.
-  (Where I is 1,2,3)
+* Generate N by argon2(name, salt=keyid), tuned to take 10 minutes.
+* Generate N1-N3 by sha256 of N+1,2,3
 * Generate random R
 * AES encrypt (data + checksum) with (K|R) as the key.
 * Shamir the encrypted key with N=2, M=3, yeilding S1-S3.
@@ -410,3 +410,8 @@ forcing right away.
 So, this isn't too bad, but for all the users who use weak passwords
 (you know who you are (yes, you)), it's not as good a choice as sharding.
 At worst, sharding degrades to being as secure as this approach.
+
+## Thanks
+
+Thanks to Anthony Towns for his help reviewing the security properties of
+keysafe.