Recent changes to this wiki:

add news item for keysafe 0.20170811
diff --git a/doc/news/version_0.20170811.mdwn b/doc/news/version_0.20170811.mdwn
new file mode 100644
index 0000000..814ab10
--- /dev/null
+++ b/doc/news/version_0.20170811.mdwn
@@ -0,0 +1,3 @@
+keysafe 0.20170811 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Updated to http-client 0.5.3, servant 0.11, and stackage lts-9.0."""]]
\ No newline at end of file

add sig
diff --git a/doc/todo/back_up_only_chosen_subkeys.mdwn b/doc/todo/back_up_only_chosen_subkeys.mdwn
index 55e841e..17a4b4b 100644
--- a/doc/todo/back_up_only_chosen_subkeys.mdwn
+++ b/doc/todo/back_up_only_chosen_subkeys.mdwn
@@ -1 +1,2 @@
-I'm a DD, so I don't want keysafe to ever back up my signing subkey nor my master key.  But I'd like it to back up my encryption subkey, so that I don't lose access to (e.g.) git-annex special remotes encrypted against that key.  It would be good if keysafe asked me which subkeys I want to back up.
+I'm a DD, so I don't want keysafe to ever back up my signing subkey nor my master key.  But I'd like it to back up my encryption subkey, so that I don't lose access to (e.g.) git-annex special remotes encrypted against that key.  It would be good if keysafe asked me which subkeys I want to back up.  --spwhitton
+ 

feature request
diff --git a/doc/todo/back_up_only_chosen_subkeys.mdwn b/doc/todo/back_up_only_chosen_subkeys.mdwn
new file mode 100644
index 0000000..55e841e
--- /dev/null
+++ b/doc/todo/back_up_only_chosen_subkeys.mdwn
@@ -0,0 +1 @@
+I'm a DD, so I don't want keysafe to ever back up my signing subkey nor my master key.  But I'd like it to back up my encryption subkey, so that I don't lose access to (e.g.) git-annex special remotes encrypted against that key.  It would be good if keysafe asked me which subkeys I want to back up.

an idea
This commit was sponsored by Ole-Morten Duesund on Patreon.
diff --git a/doc/serverless.mdwn b/doc/serverless.mdwn
new file mode 100644
index 0000000..555bbfb
--- /dev/null
+++ b/doc/serverless.mdwn
@@ -0,0 +1,129 @@
+idea, unfinished and unreviewed
+
+Storage:
+
+* 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).
+* Generate N by argon2(name), tuned to take 10 minutes.
+* Generate list I by sha256 of N+1,2,3.. , hashes truncated to 10 bytes.
+* Generate P, a byte chosen at random.
+* Generate K by argon2(password+name, salt=P), tuned to take 0.195 (50/256)
+  minutes.
+* Generate padding to obscure the length of the data. For example,
+  pad all keys to be as long as a rsa4096 gpg secret key as exported by
+  paperkey (2724 bytes), to prevent targeting types of keys by size.
+* AES encrypt (length + checksum + data + padding) with K as the key,
+  generating D.
+* Split D into 70 byte chunks, call this list C.
+* Generate 36 item list T of 80 byte values
+  (size of bitcoin's `OP_RETURN`), by concating I[x] with D[x].
+* Generate 36 bitcoin transactions storing list T in `OP_RETURN`
+* Store the transactions in bitcoin blockchain.
+
+Retrieval:
+
+* Input password and name from user.
+* Generate N by argon2(name) (takes 10 minutes)
+* Generate list I by sha256 of N+1,2,3.. , hashes truncated to 10 bytes.
+* Begin retrieving transactions from bitcoin blockchain, looking for ones
+  with `OP_RETURN` starting with values from I. Extract the 70 byte
+  chunks from the `OP_RETURN`, generating ordered list C.
+* At the same time, generate K by argon2(password+name, salt=p), guessing
+  values for P until the right one is found (takes 25 minutes on average)
+* Once K and C are available, decrypt (concat C) with K and verify
+  checksum.
+
+Password guessing:
+
+Password guessing cost is unchanged from original keysafe. Eg, 25 CPU-years
+for a super-weak 19 entropy password.
+
+Before password guessing can begin, the keysafe transactions for a key
+need to be found in the blockchain.
+
+The attacker can assume that transactions from around the same time are
+grouped together. But, the attacker needs to order the transactions
+correctly to recover D. If they get the order wrong, their password
+cracking will never succeed. With 36 transactions, and 36 factorial possible
+combinations, guessing the right order is infeasible. So, grouping
+transactions does not benefit an attacker. The attacker needs to guess the
+name and generate I to find the right ordering.
+
+Each guess of a name takes 10 minutes CPU work. This is the same attack
+cost as guessing names to download shares from keysafe servers, and a
+name that attackers are unlikely to guess prevents this attack, and so
+prevents password cracking from starting.
+
+(keysafe servers also impose a proof of work when lots of requests for
+shares are being made, which adds to the cost. That PoW is capped at 8
+minutes per request. This new design doesn't have that so is somewhat weaker.
+To get equal strength as original keysafe, could increase the
+work needed to guess a name to 18 minutes?)
+
+Storage servers:
+
+A storage server can be sent the bitcoin transactions, 
+and broadcast them to the bitcoin network. This way keysafe does not
+need to run a full bitcoin node. It may be possible to use eg, electrum
+servers as keysafe storage servers.
+
+Keysafe would need to verify that the transactions reached the
+network (by querying retrieval servers).
+
+Retrieval servers:
+
+Retrieval could download the entire bitcoin blockchain and scan it, but
+that would be gigabytes of download and take probably days. So instead,
+there can be retrieval servers, which the user connects to via tor and
+requests keysafe transactions tagged with I.
+
+Retrieval servers learn which transactions contain keys with still active
+users who have needed to restore their key. These might be more interesting
+transations to try to guess the passwords of. For example, if people are
+using keysafe to safely transit borders with their gpg keys, a government
+might focus on transactions retrieved soon after a person of interest
+crossed a border.
+
+Retrieval servers could provide innaccurate or slow results, or too many
+transactions, to try to prevent key restore. But keysafe can know about a
+lot of retrieval servers, and query several at once. Get a list of
+transaction ids from each, and then go through all the lists in parallel
+and request transactions from each server until it has retrieved enough.
+
+Storage cost:
+
+Current cost per bitcoin transaction is $1, so storing a key in keysafe
+would cost $36.
+
+Of course, keysafe could also use a blockchain other than bitcoin, eg
+lightcoin or dodgecoin have much smaller transaction fees. Using those
+would allow storing the whole gpg public+private key, not only the paperkey
+minimised private key.
+
+The risk is that all copies of a less widely used blockchain could be lost,
+preventing restore of a gpg key. Litecoin is probably big enough and
+dodgecoin amusing enough to avoid such a fate for long enough for keysafe
+backups to be useful.
+
+Name collisions:
+
+If an attacker can guess the name that a user used with keysafe, and their
+password, then as well as decrypting their gpg key, they can add new
+transactions using the same name and encrypred with the same password.
+Keysafe won't be able to tell which to use, and so the user might restore
+a gpg key controlled by the attacker.
+
+Keysafe could prevent this by preferring earlier bitcoin transactions to
+later ones.
+
+On the other hand, a user might reuse a name and password when storing an
+updated/new gpg key. Then they might expect keysafe to restore the newest
+version of the key they stored. 
+
+Keysafe might want to try to retrieve old transactions when storing a key,
+to detect if the user is doing that. It could tell the user they need to
+pick a different name if it finds any transactions using the name they
+chose. This would also guard against several of users picking the same name,
+which could otherwise make keysafe restore need to download a lot of
+transactions.

sidebar not enabled
diff --git a/doc/comments.mdwn b/doc/comments.mdwn
index e19962b..3da643b 100644
--- a/doc/comments.mdwn
+++ b/doc/comments.mdwn
@@ -1,9 +1,7 @@
-[[!sidebar content="""
 [[!inline pages="comment_pending(*)" feedfile=pendingmoderation
 description="comments pending moderation" show=-1]]
 Comments in the [[!commentmoderation desc="moderation queue"]]:
 [[!pagecount pages="comment_pending(*)"]]
-"""]]
 
 Recent comments posted to this site:
 [[!inline pages="comment(*)" template="comment"]]

add
diff --git a/doc/comments.mdwn b/doc/comments.mdwn
new file mode 100644
index 0000000..e19962b
--- /dev/null
+++ b/doc/comments.mdwn
@@ -0,0 +1,9 @@
+[[!sidebar content="""
+[[!inline pages="comment_pending(*)" feedfile=pendingmoderation
+description="comments pending moderation" show=-1]]
+Comments in the [[!commentmoderation desc="moderation queue"]]:
+[[!pagecount pages="comment_pending(*)"]]
+"""]]
+
+Recent comments posted to this site:
+[[!inline pages="comment(*)" template="comment"]]

todo
diff --git a/doc/todo/use_cryptohash_argon2.mdwn b/doc/todo/use_cryptohash_argon2.mdwn
new file mode 100644
index 0000000..61670a2
--- /dev/null
+++ b/doc/todo/use_cryptohash_argon2.mdwn
@@ -0,0 +1,2 @@
+cryptohash includes argon2 now, so it could be used instead of the separate
+argon2 library. --[[Joey]]

really close
diff --git a/doc/todo/Move_the_project_to_notabug.org.mdwn b/doc/todo/Move_the_project_to_notabug.org.mdwn
index 3172c7d..faec65a 100644
--- a/doc/todo/Move_the_project_to_notabug.org.mdwn
+++ b/doc/todo/Move_the_project_to_notabug.org.mdwn
@@ -6,4 +6,4 @@ So I'd like to propose moving the Keysafe project to [https://notabug.org](https
 
 If [https://notabug.org](https://notabug.org ) won't suit our needs, could find another alternative allowing easy public discussion of enhancements/bugs of Keysafe and a nicely visible progress overview?
 
-[!tag done]]
+[[done]]

close
diff --git a/doc/todo/Move_the_project_to_notabug.org.mdwn b/doc/todo/Move_the_project_to_notabug.org.mdwn
index 26db45a..3172c7d 100644
--- a/doc/todo/Move_the_project_to_notabug.org.mdwn
+++ b/doc/todo/Move_the_project_to_notabug.org.mdwn
@@ -5,3 +5,5 @@ So I'd like to propose moving the Keysafe project to [https://notabug.org](https
 [https://notabug.org](https://notabug.org ) is running [Gogs](https://gogs.io), which is a SW providing a centralized web interface for a great amount of git projects [https://notabug.org](https://notabug.org ) can be seen as an alternative GitHub, but with good Terms of Service and not the GitHub's ToS which basically say among other things that "you're fully responsible for anything we do in your country/land/region").
 
 If [https://notabug.org](https://notabug.org ) won't suit our needs, could find another alternative allowing easy public discussion of enhancements/bugs of Keysafe and a nicely visible progress overview?
+
+[!tag done]]
diff --git a/doc/todo/Move_the_project_to_notabug.org/comment_1_a1e7094aa456b5ff6a6fb5adcc34fcab._comment b/doc/todo/Move_the_project_to_notabug.org/comment_1_a1e7094aa456b5ff6a6fb5adcc34fcab._comment
new file mode 100644
index 0000000..02bc5ca
--- /dev/null
+++ b/doc/todo/Move_the_project_to_notabug.org/comment_1_a1e7094aa456b5ff6a6fb5adcc34fcab._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2017-04-04T16:58:17Z"
+ content="""
+I have nothing against notabug, but I prefer to use my own tools and keep
+everything in a git repository (not some sql-based wrapper around a git
+repository). So I don't think I'll be doing that.
+
+People generally don't seem to find it impossible to use ikiwiki,
+which is what we're using here, for public discussion, to refer to solved
+issues, to see what's going on, etc.
+"""]]

typo
diff --git a/doc/todo.mdwn b/doc/todo.mdwn
index da08157..bc643b4 100644
--- a/doc/todo.mdwn
+++ b/doc/todo.mdwn
@@ -3,4 +3,4 @@ Link items to [[todo/done]] when done.
 
 [[!inline pages="./todo/* and !./todo/done and !link(done) and
 !./todo/important
-and !*/Discussion" actions=yes postform=yes show=0 archive=yes template=buglist]]
+and !*/Discussion" actions=yes postform=yes show=0 archive=yes template=todolist]]

add tags to todo list
diff --git a/doc/templates/todolist.tmpl b/doc/templates/todolist.tmpl
new file mode 100644
index 0000000..a5d93e9
--- /dev/null
+++ b/doc/templates/todolist.tmpl
@@ -0,0 +1,25 @@
+<div class="archivepage">
+<TMPL_IF PERMALINK>
+<a href="<TMPL_VAR PERMALINK>"><TMPL_VAR TITLE></a>
+<TMPL_ELSE>
+<a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a>
+</TMPL_IF>
+<TMPL_IF TAGS>
+<TMPL_LOOP TAGS>
+ [<TMPL_VAR LINK>]
+</TMPL_LOOP>
+</TMPL_IF>
+<br />
+<span class="archivepagedate">
+Posted <TMPL_VAR CTIME>
+<TMPL_IF AUTHOR>
+by <span class="author">
+<TMPL_IF AUTHORURL>
+<a href="<TMPL_VAR AUTHORURL>"><TMPL_VAR AUTHOR></a>
+<TMPL_ELSE>
+<TMPL_VAR AUTHOR>
+</TMPL_IF>
+</span>
+</TMPL_IF>
+</span>
+</div>
diff --git a/doc/todo.mdwn b/doc/todo.mdwn
index 7144497..da08157 100644
--- a/doc/todo.mdwn
+++ b/doc/todo.mdwn
@@ -3,4 +3,4 @@ Link items to [[todo/done]] when done.
 
 [[!inline pages="./todo/* and !./todo/done and !link(done) and
 !./todo/important
-and !*/Discussion" actions=yes postform=yes show=0 archive=yes]]
+and !*/Discussion" actions=yes postform=yes show=0 archive=yes template=buglist]]

fix tile name
diff --git a/doc/todo/set_up_--check-servers_in_cron_job.mdwn b/doc/todo/set_up_--check-servers_in_cron_job.mdwn
new file mode 100644
index 0000000..311ae71
--- /dev/null
+++ b/doc/todo/set_up_--check-servers_in_cron_job.mdwn
@@ -0,0 +1,3 @@
+So I know when servers go down. --[[Joey]]
+
+[[!tag important]]
diff --git a/doc/todo/set_up_--check-servers_in_cron_job.mdwna b/doc/todo/set_up_--check-servers_in_cron_job.mdwna
deleted file mode 100644
index 311ae71..0000000
--- a/doc/todo/set_up_--check-servers_in_cron_job.mdwna
+++ /dev/null
@@ -1,3 +0,0 @@
-So I know when servers go down. --[[Joey]]
-
-[[!tag important]]

add tag
diff --git a/doc/todo.mdwn b/doc/todo.mdwn
index cb54209..7144497 100644
--- a/doc/todo.mdwn
+++ b/doc/todo.mdwn
@@ -1,5 +1,6 @@
 This is keysafe's todo list. Please feel free to post ideas here.
 Link items to [[todo/done]] when done.
 
-[[!inline pages="./todo/* and !./todo/done and !link(done)
+[[!inline pages="./todo/* and !./todo/done and !link(done) and
+!./todo/important
 and !*/Discussion" actions=yes postform=yes show=0 archive=yes]]
diff --git a/doc/todo/important.mdwn b/doc/todo/important.mdwn
new file mode 100644
index 0000000..46d2b49
--- /dev/null
+++ b/doc/todo/important.mdwn
@@ -0,0 +1,4 @@
+important [[todo]] items.
+
+[[!inline pages="./* and link(./important) and !*/Discussion" sort=mtime show=10
+archive=yes]]

move TODO to doc/todo, expand a few items
diff --git a/Storage.hs b/Storage.hs
index feb5791..88e6ae5 100644
--- a/Storage.hs
+++ b/Storage.hs
@@ -73,9 +73,6 @@ problemStoringIn (StorageLocations locs) tunables
 --
 -- If a server is not currently accessible, it will be queued locally.
 -- If any uploads are queued, returns True.
---
--- TODO: Add shuffling and queueing/chaffing to prevent
--- correlation of related shares.
 storeShares :: StorageLocations -> ShareIdents -> [S.Set Share] -> UpdateProgress -> IO (StoreResult, Bool, [Storage])
 storeShares (StorageLocations locs) allsis shares updateprogress = do
 	((r, anyqueued), usedlocs) <- go allsis shares [] False
diff --git a/TODO b/TODO
deleted file mode 100644
index 83f153b..0000000
--- a/TODO
+++ /dev/null
@@ -1,71 +0,0 @@
-Soon:
-
-* Finish vetting 2 servers to Recommended.
-* Set up --check-servers in a cron job, so I know when servers are down.
-* Remove gpg key passohrase from gpg keys that keysafe backs up.
-  The reason for this is that the user may well forget their gpg key
-  passphrase, and it's *weird* to restore a key with keysafe's password
-  and then have it passphrase protected.
-  The gpg key passphrase is intended only to keep a key from being used
-  for a short period of time (a week or so) when the device holding it 
-  is known to have been compromised, so the key can be revoked.
-  This doesn't really apply to keys backed up with keysafe -- if they get
-  compromised somehow, the user won't know, and cracking the gpg passphrase
-  should be almost trivial to an attacker who was able to break keysafe's
-  password.
-  paperkey can remove gpg key passphrases. Is there any better way?
-  It might make sense for keysafe to prompt for a new gpg passphrase
-  when restoring.
-
-Later:
-
-* The attack cost display can lead to a false sense of security if the user
-  takes it as gospel. It needs to be clear that it's an estimate. This and
-  other parts of the keysafe UI need usability testing.
-* Make --gui password entry fields longer, so user does not feel they need
-  to make password short. (zenity may not allow configuring this)
-* improve restore progress bar points (update after every hash try)
-* If we retrieved enough shares successfully, but decrypt failed, must
-  be a wrong password, so prompt for re-entry and retry with those shares.
-* --no-jargon which makes the UI avoid terms like "secret key" and "crack
-  password". Do usability testing!
-* --key-value=$N which eliminates the question about password value,
-  and rejects passwords that would cost less than $N to crack at current
-  rates. This should add a combo box to the password entry form in the
-  GUI to let the user adjust the $N there.
-* In backup, only upload to N-1 servers immediately, and delay the rest
-  for up to several days, with some uploads of chaff, to prevent
-  collaborating evil servers from correlating related shards.
-* Add some random padding to http requests and responses, to make it
-  harder for traffic analysis to tell that given TOR traffic is
-  keysafe traffic.
-
-Wishlist:
-
-* Custom GUI, instead of zenity. Allows:
-  - Fewer screens by consolidating multiple prompts.
-  - Check same password entered second time and don't allow continuing
-    if not.
-  - Password strengh display, and don't allow continuing if password is too
-    weak.
-* Keep secret keys in locked memory until they're encrypted.
-  (Raaz makes this possible to do.)
-  Would be nice, but not super-important, since gpg secret keys
-  are passphrase protected anyway..
-
-Encryption tunables changes:
-
-* Argon2d is more resistent to GPU/ASIC attack optimisation.
-  Switching from Argon2i would require new tunables, and delay restores
-  (of keys backed up using the old tunables, and when the user provides the
-  wrong name) by ~10 minutes, so deferred for now
-  until there's some other reason to change the tunables.
-* The ShareIdents derivation currently appends a number and sha256 hashes
-  to generate a stream of values. Ben M points out that HMAC is a more
-  typical way to do such a thing. Even better, a HKDF-Expand
-  (RFC5869) can generate a stream which can then be chunked up into values.  
-  Either of these would avoid a full pre-image attack on SHA-2 breaking
-  keysafe. Of course, such an SHA-2 attack would be a general security
-  disaster. HKDF may prove more robust in the face of partial SHA-2 breaks.
-  Deferred for now until tthere's some other reason to change keysafe's
-  tunables.
diff --git a/doc/todo/add_--key-value_option.mdwn b/doc/todo/add_--key-value_option.mdwn
new file mode 100644
index 0000000..bd6e918
--- /dev/null
+++ b/doc/todo/add_--key-value_option.mdwn
@@ -0,0 +1,5 @@
+--key-value=$N which eliminates the question about password value,
+and rejects passwords that would cost less than $N to crack at current
+rates. This should add a combo box to the password entry form in the
+GUI to let the user adjust the $N there.
+
diff --git a/doc/todo/custom_gui.mdwn b/doc/todo/custom_gui.mdwn
new file mode 100644
index 0000000..c2863f6
--- /dev/null
+++ b/doc/todo/custom_gui.mdwn
@@ -0,0 +1,10 @@
+Custom GUI, instead of zenity. Allows:
+
+* Fewer screens by consolidating multiple prompts.
+* Check same password entered second time and don't allow continuing
+  if not.
+* Password strengh display, and don't allow continuing if password is too
+  weak.
+* Make --gui password entry fields longer, so user does not feel they
+  need to make password short. (zenity does not seem to allow configuring
+  this.)
diff --git a/doc/todo/delay_some_uploads_to_prevent_correlation.mdwn b/doc/todo/delay_some_uploads_to_prevent_correlation.mdwn
new file mode 100644
index 0000000..5b9e324
--- /dev/null
+++ b/doc/todo/delay_some_uploads_to_prevent_correlation.mdwn
@@ -0,0 +1,19 @@
+In backup, only upload to some servers immediately, and delay the rest
+for up to several days, with some uploads of chaff, to prevent
+collaborating evil servers from correlating related shards.
+
+How many servers should be uploaded to immediately? The safe answer is at least
+M (--neededshares); that way the secret key does get backed up immediately.
+
+Uploading to less would be more secure, but risks the user thinking it
+finished backing up the key, and eg, wiping their laptop. So careful
+messaging would be needed in this case.
+
+Might just upload M-1 shares immediatly, and show a dialog saying, the
+backup will be completed next Wednesday, or click here to finish it now.
+
+----
+
+Also, when there are multiple chunks, they are currently uploaded in order.
+That could easily be shuffled, with server A getting its share of chunk 2
+first, server B its share of chunk 3 first, etc.
diff --git a/doc/todo/detect_bad_password_on_restore_and_re-prompt.mdwn b/doc/todo/detect_bad_password_on_restore_and_re-prompt.mdwn
new file mode 100644
index 0000000..f010676
--- /dev/null
+++ b/doc/todo/detect_bad_password_on_restore_and_re-prompt.mdwn
@@ -0,0 +1,2 @@
+If we retrieved enough shares successfully, but decrypt failed, must
+be a wrong password, so prompt for re-entry and retry with those shares.
diff --git a/doc/todo/future_encryption_tunables_changes.mdwn b/doc/todo/future_encryption_tunables_changes.mdwn
new file mode 100644
index 0000000..8a9b29d
--- /dev/null
+++ b/doc/todo/future_encryption_tunables_changes.mdwn
@@ -0,0 +1,18 @@
+If switching any of the encryption tunables for some reason,
+consider making these changes all at once:
+
+* Argon2d is more resistent to GPU/ASIC attack optimisation.
+  Switching from Argon2i would require new tunables, and delay restores
+  (of keys backed up using the old tunables, and when the user provides the
+  wrong name) by ~10 minutes, so deferred for now
+  until there's some other reason to change the tunables.
+* The ShareIdents derivation currently appends a number and sha256 hashes
+  to generate a stream of values. Ben M points out that HMAC is a more
+  typical way to do such a thing. Even better, a HKDF-Expand
+  (RFC5869) can generate a stream which can then be chunked up into values.
+  Either of these would avoid a full pre-image attack on SHA-2 breaking
+  keysafe. Of course, such an SHA-2 attack would be a general security
+  disaster. HKDF may prove more robust in the face of partial SHA-2 breaks.
+  Deferred for now until tthere's some other reason to change keysafe's
+  tunables.
+* Perhaps use CHACHA2 instead of AES?
diff --git a/doc/todo/improve_restore_progress_bar.mdwn b/doc/todo/improve_restore_progress_bar.mdwn
new file mode 100644
index 0000000..5a6af76
--- /dev/null
+++ b/doc/todo/improve_restore_progress_bar.mdwn
@@ -0,0 +1 @@
+improve restore progress bar points (update after every hash try)
diff --git a/doc/todo/need_one_more_recommended_server.mdwn b/doc/todo/need_one_more_recommended_server.mdwn
new file mode 100644
index 0000000..a699643
--- /dev/null
+++ b/doc/todo/need_one_more_recommended_server.mdwn
@@ -0,0 +1,8 @@
+There is currently only 1 recommended server; keysafe needs one more before
+it can be used without warning that it's uploading 2 shares to
+not-recommended servers.
+
+Probably need a new recommended server. The existing non-recommended
+servers don't have warrant canaries for various reasons.
+
+[[!tag important]]
diff --git a/doc/todo/padding_to_prevent_traffic_analysis.mdwn b/doc/todo/padding_to_prevent_traffic_analysis.mdwn
new file mode 100644
index 0000000..c2aa3c1
--- /dev/null

(Diff truncated)
move item from TODO to doc/todo and reply
diff --git a/TODO b/TODO
index 7b56c90..83f153b 100644
--- a/TODO
+++ b/TODO
@@ -52,35 +52,6 @@ Wishlist:
   (Raaz makes this possible to do.)
   Would be nice, but not super-important, since gpg secret keys
   are passphrase protected anyway..
-* Don't require --totalshares and --neededshares on restore when unusual
-  values were used for backup. 
-
-  The difficulty is that the number of needed shares cannot be determined by
-  looking at shares, and guessing it wrong will result in combining
-  too few shares yielding garbage, which it will take up to an hour to
-  try to decrypt, before it can tell that more shares are needed.
-
-  This could be dealt with by including the number of needed shares in the
-  serialization of Share, but then an attacker could use it to partition
-  shares from servers. If only one person uses --neededshares=5,
-  the attacker can guess that all their shares go together.
-
-  What about including the number of needed shares in the name? Since that's
-  hashed, it's not visible to an attacker. Keysafe would need to try names
-  with 2 shares, then 3, etc, and once it found shares, it would know the
-  number needed. It should also be possible to avoid breaking backwards
-  compatability, by only including the number of shares in the name when
-  it's not the standard number. To avoid needing to re-run argon2 for each
-  try, the argon2 hash of the name could be calculated first, and then the
-  number of needed shares appended before the final sha256 hash is
-  generated.
-  
-  If an attacker is able to guess the name, and a nonstandard number of
-  shares was used, the attacker could upload other objects where they would
-  be found before the real objects. This could be used to prevent
-  restore from working. (It also makes a malicious data attack (as described
-  in https://keysafe.branchable.com/details/) possible by attackers who do not
-  control the servers.
 
 Encryption tunables changes:
 
diff --git a/doc/todo.mdwn b/doc/todo.mdwn
index 6fa6e18..cb54209 100644
--- a/doc/todo.mdwn
+++ b/doc/todo.mdwn
@@ -1,4 +1,5 @@
-This is keysafe's todo list. Link items to [[todo/done]] when done.
+This is keysafe's todo list. Please feel free to post ideas here.
+Link items to [[todo/done]] when done.
 
 [[!inline pages="./todo/* and !./todo/done and !link(done)
 and !*/Discussion" actions=yes postform=yes show=0 archive=yes]]
diff --git a/doc/todo/Make_the_number_of_shard_servers_configurable/comment_1_4416f7495e2a34a3cdb6f5106beaf582._comment b/doc/todo/Make_the_number_of_shard_servers_configurable/comment_1_4416f7495e2a34a3cdb6f5106beaf582._comment
new file mode 100644
index 0000000..1a2871f
--- /dev/null
+++ b/doc/todo/Make_the_number_of_shard_servers_configurable/comment_1_4416f7495e2a34a3cdb6f5106beaf582._comment
@@ -0,0 +1,20 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2017-04-04T16:19:10Z"
+ content="""
+You can use --totalshares and --neededshares to configure how many shares
+keysafe splits the key into. See also
+[[detect_number_of_required_shares_on_restore]].
+
+Bear in mind that colluding servers still have to guess the name used to
+find the shares to combine, and even then they still have the expensive
+work of cracking the password ahead. Splitting the secret across servers is
+only an initial line of defense.
+
+It's debatable whether having a lot of servers would add much security.
+
+But, keysafe needs more servers in any case. With more than 3 servers,
+splits like 3-of-4 and 2-of-4 become usable; these and other parameters are
+probably useful in some cases.
+"""]]
diff --git a/doc/todo/detect_number_of_required_shares_on_restore.mdwn b/doc/todo/detect_number_of_required_shares_on_restore.mdwn
new file mode 100644
index 0000000..4bfa080
--- /dev/null
+++ b/doc/todo/detect_number_of_required_shares_on_restore.mdwn
@@ -0,0 +1,34 @@
+When --totalshares and --neededshares were used to back up a key,
+those options (well at least --neededshares) 
+also have to be provided at restore time to make it try to find 
+enough shares to restore.
+
+It would be good to detect the number of required shares so the user does
+not need to remember to do that.
+
+The difficulty is that the number of needed shares cannot be determined by
+looking at shares, and guessing it wrong will result in combining
+too few shares yielding garbage, which it will take up to an hour to
+try to decrypt, before it can tell that more shares are needed.
+
+This could be dealt with by including the number of needed shares in the
+serialization of Share, but then an attacker could use it to partition
+shares from servers. If only one person uses --neededshares=5,
+the attacker can guess that all their shares go together.
+
+What about including the number of needed shares in the name? Since that's
+hashed, it's not visible to an attacker. Keysafe would need to try names
+with 2 shares, then 3, etc, and once it found shares, it would know the
+number needed. It should also be possible to avoid breaking backwards
+compatability, by only including the number of shares in the name when
+it's not the standard number. To avoid needing to re-run argon2 for each
+try, the argon2 hash of the name could be calculated first, and then the
+number of needed shares appended before the final sha256 hash is
+generated.
+
+Problem with this: If an attacker is able to guess the name, and a
+nonstandard number of shares was used, the attacker could upload other
+objects where they would be found before the real objects. This could be
+used to prevent restore from working. (It also makes a malicious data
+attack (as described in https://keysafe.branchable.com/details/) possible
+by attackers who do not control the servers.

diff --git a/doc/todo/Make_the_number_of_shard_servers_configurable.mdwn b/doc/todo/Make_the_number_of_shard_servers_configurable.mdwn
new file mode 100644
index 0000000..d9ebe32
--- /dev/null
+++ b/doc/todo/Make_the_number_of_shard_servers_configurable.mdwn
@@ -0,0 +1,3 @@
+Currently 3 shard servers are used for saving the key and either two of them are required to reconstruct the key.
+
+In my opinion it's too easy for any two subjects to cooperate when it comes to key reconstruction. I'd like to therefore have the number of shard servers configurable (with possibly hundreds of shard servers). This implies also having configurable also the minimum number of servers needed for key reconstruction (with possibly hundreds of required pieces of the key).

diff --git a/doc/todo/Move_the_project_to_notabug.org.mdwn b/doc/todo/Move_the_project_to_notabug.org.mdwn
new file mode 100644
index 0000000..26db45a
--- /dev/null
+++ b/doc/todo/Move_the_project_to_notabug.org.mdwn
@@ -0,0 +1,7 @@
+Currently it's difficult to discuss anything publicly, refer to solved issues, get a fresh overview of the project's progress, etc.
+
+So I'd like to propose moving the Keysafe project to [https://notabug.org](https://notabug.org ). They're very open, they respect (in fact require) Free Software and they're pretty stable (I'm following them for about 2 years and they're meticulously publicly documenting what is going on) and legally OK.
+
+[https://notabug.org](https://notabug.org ) is running [Gogs](https://gogs.io), which is a SW providing a centralized web interface for a great amount of git projects [https://notabug.org](https://notabug.org ) can be seen as an alternative GitHub, but with good Terms of Service and not the GitHub's ToS which basically say among other things that "you're fully responsible for anything we do in your country/land/region").
+
+If [https://notabug.org](https://notabug.org ) won't suit our needs, could find another alternative allowing easy public discussion of enhancements/bugs of Keysafe and a nicely visible progress overview?

add
diff --git a/doc/todo/done.mdwn b/doc/todo/done.mdwn
new file mode 100644
index 0000000..e7c9808
--- /dev/null
+++ b/doc/todo/done.mdwn
@@ -0,0 +1,4 @@
+recently fixed [[todo]] items.
+
+[[!inline pages="./* and link(./done) and !*/Discussion" sort=mtime show=10
+archive=yes]]

close
diff --git a/doc/todo/Fix_compiler_errors_in_HEAD.mdwn b/doc/todo/Fix_compiler_errors_in_HEAD.mdwn
index d712ad0..08dbdc8 100644
--- a/doc/todo/Fix_compiler_errors_in_HEAD.mdwn
+++ b/doc/todo/Fix_compiler_errors_in_HEAD.mdwn
@@ -73,3 +73,6 @@ index 61bdbfd..12a8f26 100644
 -- 
 2.12.1
 ```
+
+> Thanks for the patch; I applied essentially these fixes although
+> untangled the unrelated issues. [[done]] --[[Joey]]

diff --git a/doc/todo/Fix_compiler_errors_in_HEAD.mdwn b/doc/todo/Fix_compiler_errors_in_HEAD.mdwn
index 12b148d..d712ad0 100644
--- a/doc/todo/Fix_compiler_errors_in_HEAD.mdwn
+++ b/doc/todo/Fix_compiler_errors_in_HEAD.mdwn
@@ -1,3 +1,4 @@
+```
 From e1fee7bb9dd508b9bef420fd76292f91bb151c8c Mon Sep 17 00:00:00 2001
 From: Mitchell Rosen <mitchellwrosen@gmail.com>
 Date: Sat, 1 Apr 2017 14:39:41 -0400
@@ -71,4 +72,4 @@ index 61bdbfd..12a8f26 100644
  serverStorage :: Maybe LocalStorageDirectory -> Storage
 -- 
 2.12.1
-
+```

diff --git a/doc/todo/Fix_compiler_errors_in_HEAD.mdwn b/doc/todo/Fix_compiler_errors_in_HEAD.mdwn
new file mode 100644
index 0000000..12b148d
--- /dev/null
+++ b/doc/todo/Fix_compiler_errors_in_HEAD.mdwn
@@ -0,0 +1,74 @@
+From e1fee7bb9dd508b9bef420fd76292f91bb151c8c Mon Sep 17 00:00:00 2001
+From: Mitchell Rosen <mitchellwrosen@gmail.com>
+Date: Sat, 1 Apr 2017 14:39:41 -0400
+Subject: [PATCH 1/1] Fix compiler errors
+
+---
+ HTTP/ProofOfWork.hs | 8 ++++----
+ HTTP/Server.hs      | 3 ++-
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/HTTP/ProofOfWork.hs b/HTTP/ProofOfWork.hs
+index 0237347..9a10d39 100644
+--- a/HTTP/ProofOfWork.hs
++++ b/HTTP/ProofOfWork.hs
+@@ -16,7 +16,7 @@ import ByteStrings
+ import GHC.Generics
+ import qualified Data.Text as T
+ import qualified Data.ByteString as B
+-import Data.Text.Encoding (encodeUtf8)
++import Data.Text.Encoding (decodeUtf8, encodeUtf8)
+ import Raaz.Core.Encode
+ import qualified Raaz
+ import Data.BloomFilter.Hash
+@@ -55,7 +55,7 @@ instance Hashable RequestID where
+ 	hashIO64 = hashIO64 . hashRequestID
+ 
+ hashRequestID :: RequestID -> B.ByteString
+-hashRequestID rid = encodeUtf8 (fromRandomSalt (randomSalt rid)) 
++hashRequestID rid = encodeUtf8 (fromRandomSalt (randomSalt rid))
+ 	<> ":" <> encodeUtf8 (requestHMAC rid)
+ 
+ -- | Using Text and not ByteString so that ProofOfWorkRequirement can have a
+@@ -80,7 +80,7 @@ maxProofOfWork = Seconds (16*60)
+ -- on the very first try. On average, the client will need to work for half
+ -- as long as the returned number of Seconds.
+ generationTime :: ProofOfWorkRequirement -> Seconds
+-generationTime req = 
++generationTime req =
+ 	let UseArgon2 (CPUCost (Seconds s) _) _ = proofOfWorkHashTunable (addedArgon2Iterations req)
+ 	in Seconds ((2^(leadingZeros req)) * s)
+ 
+@@ -109,7 +109,7 @@ mkRequestID secret = mkRequeestID' secret <$> mkRandomSalt
+ mkRequeestID' :: RequestIDSecret -> RandomSalt -> RequestID
+ mkRequeestID' (RequestIDSecret key) salt =
+ 	let hmac = Raaz.hmacSha256 key (encodeUtf8 $ fromRandomSalt salt)
+-	in RequestID salt $ T.toByteString (Raaz.encode hmac :: Base16)
++	in RequestID salt $ decodeUtf8 $ Raaz.toByteString (Raaz.encode hmac :: Base16)
+ 
+ validRequestID :: RequestIDSecret -> RequestID -> Bool
+ validRequestID secret rid =
+diff --git a/HTTP/Server.hs b/HTTP/Server.hs
+index 61bdbfd..12a8f26 100644
+--- a/HTTP/Server.hs
++++ b/HTTP/Server.hs
+@@ -18,6 +18,7 @@ import CmdLine (ServerConfig(..))
+ import Storage.Local
+ import Serialization ()
+ import Servant
++import Network.Wai (Application)
+ import Network.Wai.Handler.Warp
+ import Control.Monad.IO.Class
+ import Control.Concurrent
+@@ -51,7 +52,7 @@ runServer d cfg = do
+ 	_ <- forkIO $ obscurerThread st
+ 	runSettings settings (app st)
+   where
+-	settings = setHost host $ setPort (serverPort cfg) $ defaultSettings 
++	settings = setHost host $ setPort (serverPort cfg) $ defaultSettings
+ 	host = fromString (serverAddress cfg)
+ 
+ serverStorage :: Maybe LocalStorageDirectory -> Storage
+-- 
+2.12.1
+

add https git clone url
diff --git a/doc/index.mdwn b/doc/index.mdwn
index 873eb35..5c0c670 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -57,7 +57,8 @@ Install it from there, or from source.
 
 ## Git repository
 
-`git clone git://keysafe.branchable.com/ keysafe`
+`git clone git://keysafe.branchable.com/ keysafe` or
+`git clone https://git.joeyh.name/git/keysafe.git/`
 
 All tags and commits in this repository are gpg signed, and you should
 verify the signature before using it.
diff --git a/doc/servers.mdwn b/doc/servers.mdwn
index 3e82c7e..d190603 100644
--- a/doc/servers.mdwn
+++ b/doc/servers.mdwn
@@ -178,7 +178,8 @@ source of disk IO.
 
 It's early days still, but keysafe's server code works well enough.
 
-* `git clone git://keysafe.branchable.com/ keysafe`
+* `git clone git://keysafe.branchable.com/ keysafe` or
+  `git clone https://git.joeyh.name/git/keysafe.git/`
 * 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.

add news item for keysafe 0.20170303
diff --git a/doc/news/version_0.20170303.mdwn b/doc/news/version_0.20170303.mdwn
new file mode 100644
index 0000000..6d412d4
--- /dev/null
+++ b/doc/news/version_0.20170303.mdwn
@@ -0,0 +1,3 @@
+keysafe 0.20170303 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Updated to use raaz-0.1.1."""]]
\ No newline at end of file

releasing package keysafe version 0.20170303
diff --git a/CHANGELOG b/CHANGELOG
index 786943d..60167a0 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,8 +1,8 @@
-keysafe (0.20170123) UNRELEASED; urgency=medium
+keysafe (0.20170303) unstable; urgency=medium
 
   * Updated to use raaz-0.1.1.
 
- -- Joey Hess <id@joeyh.name>  Fri, 03 Mar 2017 15:41:36 -0400
+ -- Joey Hess <id@joeyh.name>  Fri, 03 Mar 2017 16:15:47 -0400
 
 keysafe (0.20170122) unstable; urgency=medium
 
diff --git a/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__.mdwn b/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__.mdwn
index 4bc825a..c05748c 100644
--- a/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__.mdwn
+++ b/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__.mdwn
@@ -6,3 +6,5 @@ but hope fully good ones.
 Ref.
 
 https://github.com/raaz-crypto/raaz/issues/278
+
+> [[done]] --[[Joey]]
diff --git a/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__/comment_2_06f4ff0c86aa877656cee67ff054e9b1._comment b/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__/comment_2_06f4ff0c86aa877656cee67ff054e9b1._comment
new file mode 100644
index 0000000..eb8a106
--- /dev/null
+++ b/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__/comment_2_06f4ff0c86aa877656cee67ff054e9b1._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 2"""
+ date="2017-03-03T20:15:04Z"
+ content="""
+Tested restore of key backed up with a previous keysafe release; still
+works after this conversion.
+"""]]
diff --git a/keysafe.cabal b/keysafe.cabal
index ebac775..42e95fd 100644
--- a/keysafe.cabal
+++ b/keysafe.cabal
@@ -1,5 +1,5 @@
 Name: keysafe
-Version: 0.20170122
+Version: 0.20170303
 Cabal-Version: >= 1.8
 Maintainer: Joey Hess <joey@kitenet.net>
 Author: Joey Hess

Updated to use raaz-0.1.1.
This commit was sponsored by John Peloquin on Patreon.
diff --git a/ByteStrings.hs b/ByteStrings.hs
index cecf617..90b42f0 100644
--- a/ByteStrings.hs
+++ b/ByteStrings.hs
@@ -1,5 +1,3 @@
-{-# OPTIONS_GHC -fno-warn-orphans #-}
-
 {- Copyright 2016 Joey Hess <id@joeyh.name>
  -
  - Licensed under the GNU AGPL version 3 or higher.
@@ -9,8 +7,6 @@ module ByteStrings where
 
 import qualified Data.ByteString as B
 import qualified Raaz
-import Control.Monad
-import Data.Word
 
 allByteStringsOfLength :: Int -> [B.ByteString]
 allByteStringsOfLength = go []
@@ -34,9 +30,8 @@ chunkByteString n = go []
 			let (h, t) = B.splitAt n b
 			in go (h:cs) t
 
-instance Raaz.Random Word8
-
-randomByteStringOfLength :: Int -> Raaz.SystemPRG -> IO B.ByteString
-randomByteStringOfLength n prg = B.pack <$> replicateM n randbyte
+randomByteStringOfLength :: Int -> IO B.ByteString
+randomByteStringOfLength n = Raaz.securely gen
   where
-	randbyte = Raaz.random prg :: IO Word8
+	gen :: Raaz.RandM B.ByteString
+	gen = Raaz.randomByteString (Raaz.BYTES n)
diff --git a/CHANGELOG b/CHANGELOG
index 8d8036b..786943d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+keysafe (0.20170123) UNRELEASED; urgency=medium
+
+  * Updated to use raaz-0.1.1.
+
+ -- Joey Hess <id@joeyh.name>  Fri, 03 Mar 2017 15:41:36 -0400
+
 keysafe (0.20170122) unstable; urgency=medium
 
   * Adjust cabal bounds to allow building with ghc 8.0.
diff --git a/Encryption.hs b/Encryption.hs
index 880095d..3e085a0 100644
--- a/Encryption.hs
+++ b/Encryption.hs
@@ -32,10 +32,9 @@ encrypt :: Tunables -> KeyEncryptionKey -> SecretKey -> EncryptedSecretKey
 encrypt tunables kek (SecretKey secret) = 
 	EncryptedSecretKey (chunkByteString (objectSize tunables) b) (keyBruteForceCalc kek)
   where
-	-- Raaz does not seem to provide a high-level interface
-	-- for AES encryption, so use unsafeEncrypt. The use of 
-	-- EncryptableBytes makes sure it's provided with a 
-	-- multiple of the AES block size.
+	-- Raaz does not provide a high-level interface for AES encryption,
+	-- so we use unsafeEncrypt. The use of EncryptableBytes makes
+	-- sure it's provided with a  multiple of the AES block size.
 	b = Raaz.unsafeEncrypt cipher (keyEncryptionKey kek, keyEncryptionIV kek) $
 		getEncryptableBytes $ encodeEncryptableBytes tunables secret
 
@@ -104,8 +103,7 @@ instance HasDecryptionCost (Candidates a) where
 -- run the hash repeatedly.
 genKeyEncryptionKey :: Tunables -> Name -> Password -> IO KeyEncryptionKey
 genKeyEncryptionKey tunables name password = do
-	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG
-	saltprefix <- genRandomSaltPrefix prg tunables
+	saltprefix <- genRandomSaltPrefix tunables
 	return $ head $
 		genKeyEncryptionKeys [saltprefix] tunables name password
 
@@ -144,12 +142,12 @@ genIV (Name name) =
 		Raaz.fromByteString $ B.take ivlen $
 			Raaz.toByteString $ Raaz.sha256 name
   where
-	ivlen = fromIntegral $ Raaz.byteSize (undefined :: Raaz.IV)
+	ivlen = fromIntegral $ Raaz.sizeOf (undefined :: Raaz.IV)
 
 type SaltPrefix = B.ByteString
 
-genRandomSaltPrefix :: Raaz.SystemPRG -> Tunables -> IO SaltPrefix
-genRandomSaltPrefix prg tunables = randomByteStringOfLength n prg
+genRandomSaltPrefix :: Tunables -> IO SaltPrefix
+genRandomSaltPrefix tunables = randomByteStringOfLength n
   where
 	n = randomSaltBytes $ keyEncryptionKeyTunable tunables
 
@@ -164,7 +162,7 @@ hashToAESKey (ExpensiveHash _ t) =
 	fromMaybe (error "hashToAESKey fromByteString failed") $
 		Raaz.fromByteString b
   where
-	b = B.take (fromIntegral $ Raaz.byteSize (undefined :: AesKey)) $
+	b = B.take (fromIntegral $ Raaz.sizeOf (undefined :: AesKey)) $
 		Raaz.toByteString $ Raaz.sha256 (E.encodeUtf8 t)
 
 -- | A bytestring that can be AES encrypted.
diff --git a/HTTP/ProofOfWork.hs b/HTTP/ProofOfWork.hs
index a94b19b..61fea20 100644
--- a/HTTP/ProofOfWork.hs
+++ b/HTTP/ProofOfWork.hs
@@ -95,10 +95,13 @@ mkProofOfWorkRequirement (Seconds n)
 
 newtype RequestIDSecret = RequestIDSecret (Raaz.Key (Raaz.HMAC Raaz.SHA256))
 
+-- | Random data is generated insecurely, eg not locked in memory because
+-- this is a transient secret.
 newRequestIDSecret :: IO RequestIDSecret
-newRequestIDSecret = do
-	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG
-	RequestIDSecret <$> Raaz.random prg
+newRequestIDSecret = RequestIDSecret <$> Raaz.insecurely gen
+  where
+	gen :: Raaz.RandM (Raaz.Key (Raaz.HMAC Raaz.SHA256))
+	gen = Raaz.random
 
 mkRequestID :: RequestIDSecret -> IO RequestID
 mkRequestID secret = mkRequeestID' secret <$> mkRandomSalt
@@ -113,11 +116,15 @@ validRequestID secret rid =
 	let rid' = mkRequeestID' secret (randomSalt rid)
 	in requestHMAC rid == requestHMAC rid'
 
+-- | Random data is generated insecurely, eg not locked in memory because
+-- this is a transient secret.
 mkRandomSalt :: IO RandomSalt
 mkRandomSalt = do
-	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG
-	rs <- replicateM 16 (Raaz.random prg :: IO Word8)
+	rs <- Raaz.insecurely $ replicateM 16 gen
 	return $ RandomSalt $ T.pack $ concatMap show rs
+  where
+	gen :: Raaz.RandM Word8
+	gen = Raaz.random
 
 class POWIdent p where
 	getPOWIdent :: p -> B.ByteString
diff --git a/HTTP/Server.hs b/HTTP/Server.hs
index 6fd570d..61bdbfd 100644
--- a/HTTP/Server.hs
+++ b/HTTP/Server.hs
@@ -18,7 +18,6 @@ import CmdLine (ServerConfig(..))
 import Storage.Local
 import Serialization ()
 import Servant
-import Network.Wai
 import Network.Wai.Handler.Warp
 import Control.Monad.IO.Class
 import Control.Concurrent
diff --git a/Storage.hs b/Storage.hs
index c481d77..feb5791 100644
--- a/Storage.hs
+++ b/Storage.hs
@@ -26,7 +26,6 @@ import Control.Concurrent.Async
 import qualified Data.Set as S
 import System.Random
 import System.Random.Shuffle
-import qualified Raaz
 
 networkStorageLocations :: Maybe LocalStorageDirectory -> StorageLocations
 networkStorageLocations = StorageLocations . serverList
@@ -171,25 +170,24 @@ storeChaff :: HostName -> Port -> Maybe Seconds -> IO ()
 storeChaff hn port delayseconds = forever $ do
 	say $ "Sending chaff to " ++ hn ++ " (press ctrl-c to stop)"
 	say "Legend: + = successful upload, ! = upload failure"
-	prg <- Raaz.newPRG () :: IO Raaz.SystemPRG
-	randomname <- randomByteStringOfLength 128 prg
+	randomname <- randomByteStringOfLength 128
 	-- It's ok the use the testModeTunables here because
 	-- the randomname is not something that can be feasibly guessed.
 	-- Prefix "random chaff" to the name to avoid ever using a name
 	-- that a real user might want to use.
 	let sis = shareIdents testModeTunables (Name $ "random chaff:" <> randomname) AnyGpgKey
-	mapConcurrently (go sis prg)
+	mapConcurrently (go sis)
 		[1..totalObjects (shareParams testModeTunables)]
   where
 	server = networkStorage Untrusted Nothing $ 
 		Server (ServerName hn) [ServerAddress hn port] "chaff server"
 	objsize = objectSize defaultTunables * shareOverhead defaultTunables
 	maxmsdelay = ceiling $ 1000000 * fromMaybe 0 delayseconds
-	go sis prg n = do
+	go sis n = do
 		msdelay <- getStdRandom (randomR (0, maxmsdelay))
 		delay msdelay
 
-		b <- randomByteStringOfLength objsize prg
+		b <- randomByteStringOfLength objsize
 		let share = Share 0 (StorableObject b)
 		let (is, sis') = nextShareIdents sis
 		let i = S.toList is !! (n - 1)
@@ -197,7 +195,7 @@ storeChaff hn port delayseconds = forever $ do
 		case r of
 			StoreSuccess -> progress "+"
 			_ -> progress "!"
-		go sis' prg n
+		go sis' n
 

(Diff truncated)
diff --git a/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__.mdwn b/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__.mdwn
new file mode 100644
index 0000000..4bc825a
--- /dev/null
+++ b/doc/todo/Update_to_new_version_of_raaz___40__0.1.1__41__.mdwn
@@ -0,0 +1,8 @@
+New version of raaz is released and will hopefully end up in debian expt. soon. 
+It would be good if we can get keysafe to use the new interface as there is some breakage
+but hope fully good ones.
+
+
+Ref.
+
+https://github.com/raaz-crypto/raaz/issues/278

avoid stack install keysafe
stack does not look at stack.yaml when run that way. So annoying..
diff --git a/doc/index.mdwn b/doc/index.mdwn
index 407cb41..873eb35 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -69,9 +69,9 @@ libraries, and zenity. For example, on a Debian system:
 
 	sudo apt-get install haskell-stack libreadline-dev libargon2-0-dev zenity
 
-Then to build and install keysafe:
+Then to build and install keysafe, cd into its source tree and run:
 
-	stack install keysafe
+	stack install
 
 Note that there is a manpage, but stack doesn't install it yet.
 

add better object-id derivation idea
diff --git a/TODO b/TODO
index c018dc8..7b56c90 100644
--- a/TODO
+++ b/TODO
@@ -39,11 +39,6 @@ Later:
 * Add some random padding to http requests and responses, to make it
   harder for traffic analysis to tell that given TOR traffic is
   keysafe traffic.
-* Argon2d is more resistent to GPU/ASIC attack optimisation.
-  Switching from Argon2i would require new tunables, and delay restores
-  (of keys backed up using the old tunables, and when the user provides the
-  wrong name) by ~10 minutes, so deferred for now
-  until there's some other reason to change the tunables.
 
 Wishlist:
 
@@ -86,3 +81,20 @@ Wishlist:
   restore from working. (It also makes a malicious data attack (as described
   in https://keysafe.branchable.com/details/) possible by attackers who do not
   control the servers.
+
+Encryption tunables changes:
+
+* Argon2d is more resistent to GPU/ASIC attack optimisation.
+  Switching from Argon2i would require new tunables, and delay restores
+  (of keys backed up using the old tunables, and when the user provides the
+  wrong name) by ~10 minutes, so deferred for now
+  until there's some other reason to change the tunables.
+* The ShareIdents derivation currently appends a number and sha256 hashes
+  to generate a stream of values. Ben M points out that HMAC is a more
+  typical way to do such a thing. Even better, a HKDF-Expand
+  (RFC5869) can generate a stream which can then be chunked up into values.  
+  Either of these would avoid a full pre-image attack on SHA-2 breaking
+  keysafe. Of course, such an SHA-2 attack would be a general security
+  disaster. HKDF may prove more robust in the face of partial SHA-2 breaks.
+  Deferred for now until tthere's some other reason to change keysafe's
+  tunables.
diff --git a/doc/details.mdwn b/doc/details.mdwn
index e0f85e5..b014b2b 100644
--- a/doc/details.mdwn
+++ b/doc/details.mdwn
@@ -363,3 +363,37 @@ This could be used in several ways:
   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.
+
+### Better object-id derivation
+
+An idea from Ben M:
+
+> I was the fellow who mentioned using an HMAC instead of
+> append-index-and-hash to generate the object-ids in keysafe.
+> 
+> That's probably an okay approach if you need to bind the output to a
+> particular input string, but on reflection (unless I missed something)
+> it would be equivalent for keysafe to take a stream and chop it up, then
+> just "number" the chunks sequentially.
+> 
+> In that case, the "most correct" choice would probably be HKDF (RFC5869
+> [1]).  Specifically, the second part of HKDF -- "HKDF-Expand".
+> 
+> (The first part, HKDF-Extract, is appropriate to apply /before/ key
+> stretching, but stretching itself serves much the same purpose --
+> removing "structure" from the input key.  Especially given that Argon2
+> is designed specifically to handle user passwords, I expect that
+> HKDF-Extract is entirely unnecessary here.)
+> 
+> HKDF is what TLS 1.3 will use to expand its per-session master keys into
+> individual keys for encryption and MACing [2], and AFAIK is generally
+> considered The Right Way to generate a stream of distinct keys from a
+> master key, where the compromise of any key should not permit derivation
+> of the others.
+> 
+> So, um.  Pretend I never mentioned HMAC, but spruiked HKDF instead :)
+> 
+> (Of course, this is pretty much bikeshedding.  A first pre-image attack
+> on SHA-2 in the near term would be a rude shock, and a full break would
+> break HKDF too.  But HKDF may prove more robust in the face of partial
+> breaks, giving more time to move everyone to a new hash or scheme.)

link to instructions: how to use debian experimental
diff --git a/doc/index.mdwn b/doc/index.mdwn
index 8f8275a..407cb41 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -52,8 +52,8 @@ Here's a video explaining keysafe:
 
 ## Installation
 
-Keysafe is now available in Debian experimental. Install it from there, or
-from source.
+Keysafe is now available in [Debian experimental](https://wiki.debian.org/DebianExperimental).
+Install it from there, or from source.
 
 ## Git repository
 

add LCA talk
diff --git a/doc/index.mdwn b/doc/index.mdwn
index 1aab4d5..8f8275a 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -40,6 +40,12 @@ 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]].
 
+Here's a video explaining keysafe:
+
+<html>
+<video controls width=400 src="http://mirror.linux.org.au/pub/linux.conf.au/2017/securely_backing_up_gpg_private_keys_to_the_cloud.webm"></video>
+</html>
+
 ## News
 
 [[!inline pages="news/* and !*/Discussion" show="3"]]

remove
diff --git a/doc/news/version_0.20161006.mdwn b/doc/news/version_0.20161006.mdwn
deleted file mode 100644
index 2758b34..0000000
--- a/doc/news/version_0.20161006.mdwn
+++ /dev/null
@@ -1,10 +0,0 @@
-keysafe 0.20161006 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * New --add-storage-directory and --add-server options, which can be used
-     to make keysafe backup/restore using additional locations.
-   * Removed --store-local option; use --add-storage-directory instead.
-   * Fix bugs with entry of gpg keyid in the keysafe.log.
-   * Fix bug in --autostart that caused the full gpg keyid to be
-     used to generate object names, which made restores would only work
-     when --gpgkeyid was specifid.
-   * Remove embedded copy of argon2 binding, depend on fixed version of package."""]]
\ No newline at end of file
diff --git a/doc/news/version_0.20161007.mdwn b/doc/news/version_0.20161007.mdwn
deleted file mode 100644
index a7e8468..0000000
--- a/doc/news/version_0.20161007.mdwn
+++ /dev/null
@@ -1,9 +0,0 @@
-keysafe 0.20161007 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Check if --store-local directory is writable.
-   * Removed dependency on crypto-random.
-   * Added a LSB init script, for non-systemd systems.
-     (It currently uses Debian's start-stop-daemon, so would need porting
-     for other distributions.)
-   * /etc/default/keysafe is read by both the systemd service file and the
-     init script, and contains configuration for the keysafe server."""]]
\ No newline at end of file
diff --git a/doc/news/version_0.20161022.mdwn b/doc/news/version_0.20161022.mdwn
deleted file mode 100644
index e54f26e..0000000
--- a/doc/news/version_0.20161022.mdwn
+++ /dev/null
@@ -1,12 +0,0 @@
-keysafe 0.20161022 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Add keywords to desktop file.
-     Thanks, Sean Whitton
-   * Fix use of .IP macro in manpage.
-     Thanks, Sean Whitton
-   * Fix some mispellings.
-     Thanks, Sean Whitton
-   * Makefile: Propagate LDFLAGS, CFLAGS, and CPPFLAGS through ghc.
-   * Makefile: Allow setting BUILDER=./Setup to build w/o cabal or stack.
-   * Makefile: Allow setting BUILDEROPTIONS=-j1 to avoid concurrent
-     build, which should make build reproducible."""]]
\ No newline at end of file
diff --git a/doc/news/version_0.20161107.mdwn b/doc/news/version_0.20161107.mdwn
deleted file mode 100644
index d98987e..0000000
--- a/doc/news/version_0.20161107.mdwn
+++ /dev/null
@@ -1,14 +0,0 @@
-keysafe 0.20161107 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * The third keysafe server is now available, provided by Purism.
-   * Purism's keysafe server has been vetted to Recommended level!
-   * Change default for --port to 4242.
-   * Fix --check-server to not fail when the server has not had anything
-     stored on it yet.
-   * --upload-queued: Exit nonzero if unable to upload all queued objects.
-   * --autostart: If unable to upload all queued objects initially,
-     delay between 1 and 2 hours and try again.
-   * Better suggestion when user is having difficulty thinking of a strong
-     enough password.
-   * Defer requesting secret key from gpg until just before backup, so the
-     user knows why gpg is asking for this secret key to be backed up."""]]
\ No newline at end of file

fix news feed
diff --git a/doc/index.mdwn b/doc/index.mdwn
index e0cda48..1aab4d5 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -42,7 +42,7 @@ Also, there's a [[FAQ]].
 
 ## News
 
-[[!inline pages="code/keysafe/news/* and !*/Discussion" show="3"]]
+[[!inline pages="news/* and !*/Discussion" show="3"]]
 
 ## Installation
 

add news item for keysafe 0.20170122
diff --git a/doc/news/version_0.20160927.mdwn b/doc/news/version_0.20160927.mdwn
deleted file mode 100644
index 1787aa5..0000000
--- a/doc/news/version_0.20160927.mdwn
+++ /dev/null
@@ -1,20 +0,0 @@
-keysafe 0.20160927 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * Makefile: Avoid rebuilding on make install, so that sudo make install works.
-   * Added --chaff-max-delay option for slower chaffing.
-   * Fix embedded copy of Argon2 to not use Word64, fixing build on 32 bit
-     systems.
-   * Randomize the server list.
-   * Don't upload more than neededshares-1 shares to Alternate servers
-     without asking the user if they want to do this potentially dangerous
-     action.
-   * Added a second keysafe server to the server list. It's provided
-     by Marek Isalski at Faelix. Currently located in UK, but planned move
-     to CH. Currently at Alternate level until verification is complete.
-   * Server: --motd can be used to provide a Message Of The Day.
-   * Added --check-servers mode, which is useful both at the command line
-     to see what servers keysafe knows about, and as a cron job.
-   * Server: Round number of objects down to the nearest thousand, to avoid
-     leaking too much data about when objects are uploaded to servers.
-   * Filter out escape sequences and any other unusual characters when
-     writing all messages to the console."""]]
\ No newline at end of file
diff --git a/doc/news/version_0.20170122.mdwn b/doc/news/version_0.20170122.mdwn
new file mode 100644
index 0000000..de03c93
--- /dev/null
+++ b/doc/news/version_0.20170122.mdwn
@@ -0,0 +1,8 @@
+keysafe 0.20170122 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * Adjust cabal bounds to allow building with ghc 8.0.
+     However, the stack.yaml is still using an old LTS version
+     to avoid polynomial's failure to build with ghc 8.0
+     (https://github.com/mokus0/polynomial/issues/8)
+   * Clarify that dollars in cost estimates are USD.
+   * Keysafe has a new website, https://keysafe.branchable.com/"""]]
\ No newline at end of file

debian experimental
diff --git a/doc/index.mdwn b/doc/index.mdwn
index 722a0e4..e0cda48 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -44,6 +44,11 @@ Also, there's a [[FAQ]].
 
 [[!inline pages="code/keysafe/news/* and !*/Discussion" show="3"]]
 
+## Installation
+
+Keysafe is now available in Debian experimental. Install it from there, or
+from source.
+
 ## Git repository
 
 `git clone git://keysafe.branchable.com/ keysafe`
@@ -51,7 +56,7 @@ Also, there's a [[FAQ]].
 All tags and commits in this repository are gpg signed, and you should
 verify the signature before using it.
 
-## Installation
+## Building from source
 
 You should first install Haskell's stack tool, the readline and argon2
 libraries, and zenity. For example, on a Debian system:

link to new todo page
diff --git a/doc/index.mdwn b/doc/index.mdwn
index d96bf9c..722a0e4 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -66,7 +66,7 @@ Note that there is a manpage, but stack doesn't install it yet.
 
 ## Reporting bugs
 
-Email <id@joeyh.name>
+Post to [[todo]] or email <id@joeyh.name>
 
 ## Servers
 

Keysafe has a new website, https://keysafe.branchable.com/
diff --git a/CHANGELOG b/CHANGELOG
index 5baf899..d5feb76 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -5,6 +5,7 @@ keysafe (0.20161108) UNRELEASED; urgency=medium
     to avoid polynomial's failure to build with ghc 8.0
     (https://github.com/mokus0/polynomial/issues/8)
   * Clarify that dollars in cost estimates are USD.
+  * Keysafe has a new website, https://keysafe.branchable.com/
 
  -- Joey Hess <id@joeyh.name>  Tue, 29 Nov 2016 22:27:01 -0400
 
diff --git a/TODO b/TODO
index e0190cc..18426bf 100644
--- a/TODO
+++ b/TODO
@@ -70,5 +70,5 @@ Wishlist:
   shares was used, the attacker could upload other objects where they would
   be found before the real objects. This could be used to prevent
   restore from working. (It also makes a malicious data attack (as described
-  in https://joeyh.name/keysafe/details/) possible by attackers who do not
+  in https://keysafe.branchable.com/details/) possible by attackers who do not
   control the servers.
diff --git a/doc/details.mdwn b/doc/details.mdwn
new file mode 100644
index 0000000..e0f85e5
--- /dev/null
+++ b/doc/details.mdwn
@@ -0,0 +1,365 @@
+[[!toc]]
+
+## 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 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 proof of work the servers require.
+
+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. 
+
+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 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
+
+Servers run exclusively as tor hidden services. This prevents them from
+finding out the IP addresses of clients, as well as providing transport
+level encryption.
+
+Servers should avoid keeping any logs, and should santize
+the timestamps of any files stored on them. (Eg set back to epoch
+and store on filesystem mounted with noatime.)
+
+Only small objects are accepted to be stored. This is to prevent this from
+being used as a general purpose data storage system, and only be useful

(Diff truncated)