HOWTO: Create a Warrant Canary, or NSL Dead Man’s Switch
Thanks Slashdot for carrying your users over to my blog this morning!
The rsync team has been doing this for quite awhile, and I had an idea. Why not share this more broadly?
So I created a quick little script to generate my own “warrant canary”. Instructions follow below.
Note: Based on the direct emails from Slashdot users, I’ll update this post with more information in the coming days/weeks to keep this current.
#!/usr/bin/perl use warnings; use strict; use LWP::Simple; # Fetch the remote feed via HTTP use XML::RSS; # Parse the RSS feed into tree and DOM elements use HTML::Strip; # Clean up bad tags, HTML, CDATA in RSS feeds use File::Slurp; # Easily read/write files to the filesystem use Crypt::GPG; # Call out to gpg for signing the canary # Pick an RSS news source that is current, updated, and neutral if possible: my $url = "http://www.npr.org/rss/rss.php?id=1001"; # my $url = 'http://feeds.bbci.co.uk/news/world/rss.xml'; binmode(STDOUT, ":utf8"); my $hs = HTML::Strip->new(); my $gpg = new Crypt::GPG; my @newscanary = ''; my $rss = XML::RSS->new(); my $data = get($url); $rss->parse($data); my $channel = $rss->{channel}; foreach my $item (@{ $rss->{items}}) { my $title = $item->{title}; my $date = $item->{pubDate}; my $desc = $hs->parse($item->{description}); # Word wrap the output at 70 characters $desc =~ s/(.{70}[^\s]*)\s+/$1\n/xg; push @newscanary, "$title\n$date\n" . "-"x70 . "\n$desc\n\n\n"; } write_file('canary.txt', @newscanary) ; my $boilerplate = read_file('boilerplate.txt', {binmode => ':raw'}); my $newscanary = read_file('canary.txt', {binmode => ':raw'}); print $boilerplate, $newscanary; $hs->eof;
Now you create a file called ‘boilerplate.txt’, which includes the header you want to show up at the top of your canary, such as this example (nicked and modified from the rsync canary):
Existing and proposed laws, especially as relate to the US Patriot Act, etc., provide for secret warrants, searches and seizures of data, such as library records. Some such laws provide for criminal penalties for revealing the warrant, search or seizure, disallowing the disclosure of events that would materially affect the users of a service such as those provided by YOUR_COMPANY and subsidiary domains and services. YOUR_COMPANY and its principals and employees will in fact comply with such warrants and their provisions for secrecy as legally prescribed by US law. YOUR_COMPANY will also make available, hourly, a "warrant canary" in the form of a cryptographically signed message containing the following: - a declaration that, up to that point, no warrants have been served, nor have any searches or seizures taken place - a cut and paste headline from a major news source, establishing date Special note should be taken if these messages ever cease being updated, or are removed from this page. The current message is here:
I’ll leave it as an exercise to the reader how to sign the output of that with GNU Privacy Guard (hint: gpg –clearsign), and how to protect that key and copy the completed canary.txt over to your webserver (hint: use rsync).
Set that up in an hourly cron job, and you should be all set.