-
-
Save jswanner/b7bfec2f9404a550617e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# https://blog.spideroak.com/20140814060007-status-reports-transparency-overall-safety | |
# https://spideroak.com/canary | |
# https://en.wikipedia.org/wiki/Warrant_canary | |
# https://www.eff.org/deeplinks/2014/04/warrant-canary-faq | |
# https://en.wikipedia.org/wiki/National_security_letter | |
# | |
# SpiderOak now maintains a warrant canary so they can passively let their users know | |
# if they have been served a National Security Letter or other legal tool which | |
# prevents them from actively disclosing to their users that they are being coerced | |
# or forced into compromising the security or privacy of their userbase. | |
# | |
# If the canary has not been killed and you can still trust their service then you will | |
# be able to verify 3 valid PGP signatures against their canary. | |
# | |
# The signatures will be made every six months between: | |
# August 10 - August 15 | |
# February 10 - February 15 | |
# | |
# The default signing keys are listed below however they may be replaced or updated | |
# if one of the default signers goes rogue or leaves SpiderOak. | |
# | |
# Key ID: 0x1712D3E36F2F0403 | |
# Primary key fingerprint: 0DAB 1518 36A3 CBBA 0362 FC17 1712 D3E3 6F2F 0403 | |
# | |
# Key ID: 0xE435F15CA6B145F8 | |
# Primary key fingerprint: B411 3438 B56B D51C D208 E17E E435 F15C A6B1 45F8 | |
# | |
# Key ID: 0x132B9F2251131E5C | |
# Primary key fingerprint: DC1E FB15 4444 E4B5 2726 8430 132B 9F22 5113 1E5C | |
# | |
# Example output: | |
# | |
# Chip Black (SpiderOak Canary) <[email protected]> signed canary on August 11 2014 with key: 0DAB 1518 36A3 CBBA 0362 FC17 1712 D3E3 6F2F 0403 | |
# Frank Sievertsen <[email protected]> signed canary on August 12 2014 with key: B411 3438 B56B D51C D208 E17E E435 F15C A6B1 45F8 | |
# Tomas Touceda (SpiderOak canary) <[email protected]> signed canary on August 13 2014 with key: DC1E FB15 4444 E4B5 2726 8430 132B 9F22 5113 1E5C | |
# SpiderOak's Canary is alive and well! | |
# | |
# NOTE: This needs to have error handling added in various places, communicating with the network | |
# running GPG commands, handling if you actually do trust the signing keys, and the date ranges | |
# for the signature checking needs to be made more generic and the code should be refactored | |
# but its a start. | |
require 'open3' | |
require 'open-uri' | |
require 'tempfile' | |
class SpiderOakCanary | |
CANARY_URL = 'https://spideroak.com/canary' | |
DELIMITER = "-----BEGIN PGP SIGNATURE-----\n" | |
DEFAULT_KEYS = [ | |
'0DAB 1518 36A3 CBBA 0362 FC17 1712 D3E3 6F2F 0403', | |
'B411 3438 B56B D51C D208 E17E E435 F15C A6B1 45F8', | |
'DC1E FB15 4444 E4B5 2726 8430 132B 9F22 5113 1E5C' | |
] | |
def verify(out_stream) | |
lines = open(CANARY_URL).readlines | |
chunk_idx = 0 | |
chunks = lines.chunk { |line| | |
DELIMITER == line ? chunk_idx+=1 : chunk_idx | |
}.map { |chunk| | |
chunk.last.join | |
} | |
canary, signatures = chunks.shift, chunks | |
expected_signatures = {} | |
canary_file = Tempfile.new('') | |
canary_file.write(canary) | |
canary_file.close | |
signatures.each do |signature| | |
command = "gpg --verify - #{canary_file.to_path}" | |
stdin, stdout, stderr = Open3.popen3(command) | |
stdin.puts signature | |
stdin.close | |
output = stderr.readlines | |
signature_date = DateTime.parse(output[0][/made (.*) using/, 1]) | |
signer = output[1][/Good signature from \"(.*)\"/, 1] | |
primary_key = output.select { |line| line.include?('Primary key') }.first | |
key_fingerprint = primary_key[/fingerprint: (.*)/, 1] | |
expected_signatures[key_fingerprint] = signature_date | |
out_stream.puts "#{signer} signed canary on #{signature_date.strftime('%B %d %Y')} " + | |
"with key: #{key_fingerprint}" | |
end | |
valid_signatures = DEFAULT_KEYS.select do |key| | |
signature_date = expected_signatures[key] | |
# | |
# TODO: Automatically determine the appropriate date range of signatures | |
# to check based on the current date or a passed in date. | |
# Remove hardcoded date range below. | |
# | |
#current_month = Date.today.month | |
#current_year = Date.today.year | |
#start_date = DateTime.parse("10-#{current_month}-#{current_year}") | |
#start_date = DateTime.parse("16-#{current_month}-#{current_year}") | |
start_date = DateTime.parse("August 10, 2014") | |
end_date = DateTime.parse("August 16, 2014") | |
(start_date...end_date).cover? signature_date | |
end.count | |
if valid_signatures == 3 | |
out_stream.puts "SpiderOak's Canary is alive and well!" | |
else | |
out_stream.puts "Hrmmm SpiderOak's Canary seems to have died, consider your options." | |
end | |
canary_file.unlink | |
end | |
end | |
# Run program if this file was executed, | |
# but not if file was just required | |
if $0 == __FILE__ | |
SpiderOakCanary.new.verify(STDOUT) | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'stringio' | |
require 'vcr' | |
require_relative 'canary' | |
VCR.configure do |c| | |
c.cassette_library_dir = '.' | |
c.hook_into :webmock | |
end | |
describe SpiderOakCanary, '#verify' do | |
let(:output) { <<-OUTPUT } | |
Chip Black (SpiderOak Canary) <[email protected]> signed canary on August 11 2014 with key: 0DAB 1518 36A3 CBBA 0362 FC17 1712 D3E3 6F2F 0403 | |
Frank Sievertsen <[email protected]> signed canary on August 12 2014 with key: B411 3438 B56B D51C D208 E17E E435 F15C A6B1 45F8 | |
Tomas Touceda (SpiderOak canary) <[email protected]> signed canary on August 13 2014 with key: DC1E FB15 4444 E4B5 2726 8430 132B 9F22 5113 1E5C | |
SpiderOak's Canary is alive and well! | |
OUTPUT | |
it 'writes output' do | |
strio = StringIO.new | |
VCR.use_cassette('spideroak') { described_class.new.verify(strio) } | |
expect(strio.string).to eq output | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
http_interactions: | |
- request: | |
method: get | |
uri: https://spideroak.com/canary | |
body: | |
encoding: US-ASCII | |
string: '' | |
headers: | |
Accept-Encoding: | |
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
Accept: | |
- "*/*" | |
User-Agent: | |
- Ruby | |
response: | |
status: | |
code: 200 | |
message: OK | |
headers: | |
Server: | |
- nginx | |
Date: | |
- Wed, 10 Sep 2014 06:37:46 GMT | |
Content-Type: | |
- text/plain; charset=utf8 | |
Content-Length: | |
- '2376' | |
Last-Modified: | |
- Sun, 07 Sep 2014 19:58:37 GMT | |
Connection: | |
- keep-alive | |
Expires: | |
- Wed, 24 Sep 2014 06:37:46 GMT | |
Cache-Control: | |
- max-age=1209600 | |
Set-Cookie: | |
- uid=AAAAKlQP8bqZBDEMEIazAg==; expires=Thu, 10-Sep-15 06:37:46 GMT; path=/ | |
Accept-Ranges: | |
- bytes | |
body: | |
encoding: ASCII-8BIT | |
string: !binary |- | |
ZW46IEV2ZXJ5dGhpbmcncyBnb2luZyBzbW9vdGhseSBzbyBmYXIuCmRlOiBC | |
aXNoZXIgbMOkdWZ0IGFsbGVzIHByb2JsZW1sb3MuCmVzOiBUb2RvIHZhIGJp | |
ZW4gcG9yIGFob3JhLgoKSGF3YWlpYW4gR292ZXJub3IgTG9zZXMgUHJpbWFy | |
eSBieSBXaWRlIE1hcmdpbjsgU2VuYXRlIFJhY2UgSXMgVW5kZWNpZGVkIC0g | |
QXVnLiAxMCwgMjAxNCAtIFRoZSBOZXcgWW9yayB0aW1lcwoKYXVndXN0IDEw | |
LCAyMDE0Ci0tLS0tQkVHSU4gUEdQIFNJR05BVFVSRS0tLS0tClZlcnNpb246 | |
IEdudVBHIHYxLjQuMTMgKE9wZW5CU0QpCgppUUdjQkFBQkNnQUdCUUpUNk9m | |
ckFBb0pFQmNTMCtOdkx3UUR3RmtNQUk3MkFMWGswc3pxaUVhUlpiRGZIQ2l0 | |
CkZ4V05xQzlpMHk1akQ3bnNGUmtHOEVZaDJVdW85bEZrMWRRbG5qeFlqTGlu | |
c3R2NHorcDU3c1JmUHllWlpHNHIKZTZxZ3dwcUxyZzQvMDVlcndseVY4a2Vw | |
ZHAwdm9MdzlRbk9kbHl2REd5TmgrNGIxQ3duNU1pa044R1lseE5jVQpjV1J6 | |
VzI0SEJ0R2xHUlVhUVMxSUh6WEJhbjhHUU5GK2tNa1YzbnU0eVFoMXZxbFgw | |
K1NyeGtlUGJnbjJsOXVzClFmbGYxdnQza1JhRTBDRnZDZjU2Z2NWWTRRUzRL | |
ZERGVzFldllnbUdwMkRBblRXc2dLeC9pYU9STWt0ZkkxMEoKTzIvOGEvd2I4 | |
aVhsdUdOZjFZRmt0VXZtNllKblUybVJRRWRaSHZQTVphckFFTjRYTG5yK1dM | |
WGNWK0w3YzV3dgpNYjMvOFN6RXdIZ0RFRjhNTXludldZcmMyLzBFT3l4cU5i | |
L1M5a0JGMFhyNzdoRDdqU2RNMFVXZU51V2lKMlNlCndiUzJtWEJ3UDFjaTh3 | |
NDVxZlpNNXFNcWJDRlc4aExYcnMyb3dhYlRKZWc5OEp3em1QQ2pQblQ5dTJZ | |
RGttYTIKUEQ2RW0zemkzYlpiMHBnY1Nld2FEeFRUY1NDMlpCQlFBRnNXV3hR | |
R0NRPT0KPVRRQ3oKLS0tLS1FTkQgUEdQIFNJR05BVFVSRS0tLS0tCi0tLS0t | |
QkVHSU4gUEdQIFNJR05BVFVSRS0tLS0tClZlcnNpb246IEdudVBHIHYxCgpp | |
UUljQkFBQkNnQUdCUUpUNnBSQ0FBb0pFT1ExOFZ5bXNVWDRNZzRRQUk2VFFV | |
OGVUQW04VFRrKzhuOFFkVDUwCmZ6cXM2czNJaWp5SUU0UzR1Z1o4QjN2ZGIx | |
LysrR1VPL2ZXRGNZQXo0ZWFybGRUYTAxQWRxSTJuaUtDS0hqZEkKKzRMeTBs | |
dE9zZVN4cTJjeTFiWkl6Wlh3TEVuR3M4TXZObFBCd1pVeXlmYmFpeE16aGF0 | |
cTZ6cHZPSW9yVnRqYwpDeUlwQ0xwVEYxWDM2cUlQbmNwTURRY3owMFFGNFBP | |
N3VTRnJld3ZiYWRBaldaT3dncW80OW1yNW8yRlJKK1ZUCkpZV1IwbHNuVEor | |
OGhhbFJtTTZISFl6cWtVay8xTWVtOXJNN01NQ2FLVlBRNXYyOWIwNG8xL0Nv | |
dzE4TDd4MkwKODlQTzdPb2o2eXVyYkdFVERpQURSTElZc0xXTGxCZzFBVDZk | |
Z3Z4WHY5UnJQTXltRW1kRWRTbzJPUzByTjJPMgpKc2JEajArTHArcWdoc2Z2 | |
VlRBTVYrR3BsRXRWZzV1Q0grUFhoVG9mYmxLWEpERmtDK2dpR2hLTWNudlFD | |
aGM5Cm00c0wxUExxWTZzS3ozSUFwY0QwNnNBY0RNQzQzLzRZV1Axa081aEEz | |
bnBYcUFEZks0cnNxQnFuMWRSdUhxL0sKQTFVTzlqTEg2OVEwNHpyVUp3NlFS | |
WW0rWk1OK3BGTFpSREJiVFpUQm4yL3d4QkZCSkErVVBwbTVoSU1PalkvRwpi | |
dHFGYzI3cjZkWVZWOUYrZEVFOERNYnAvYjhLNUhySzJVbWZScDM1RUZaSUdT | |
ckk5dFlXSXhqQVIwVlk4eWVLCk9mTWFwRmsxaC9URlJ6cGpFTDNCcnNYUjNt | |
Slc1VGlndnQxV0xTTlQzMysvR1F0Qm9oRjBzQzRMdEgrZDBPUTEKZnJ6SzBk | |
L09xWWhmek1uZVVLeFcKPXUrMGcKLS0tLS1FTkQgUEdQIFNJR05BVFVSRS0t | |
LS0tCi0tLS0tQkVHSU4gUEdQIFNJR05BVFVSRS0tLS0tClZlcnNpb246IEdu | |
dVBHIHYxLjQuMTQgKERhcndpbikKCmlRR2NCQUFCQ2dBR0JRSlQ2MllTQUFv | |
SkVHUW10R1pxSnA4MXRwTUwvM3RkUXBCLzFWTVlGTTZDNFFLbC9RU0wKeXNs | |
ZWdLZXNhanc3S0dlMVFvS1B1enVobFp1QU1ETnYvSzQyZEVwNHR2N1BVbVlm | |
dFg4ZGpuYVN4bFQ4V1ZaSwp2ZWUvUmEycVV1UjBsbTZaUm94dDQwSDBiL2lO | |
ZGpwbHQzSEJSbUI4VUtMUTROWUZ4aStNazhBc3VGVFFyaGM3CktzTG11bzIz | |
anBONmU0dmVTTGwxWU1hWVI1TisvcEhTaDdCYVNSeVFEZitUdTZFSXR0ZExr | |
YzhuYlJ6RU9lbEMKQmtRWi9TQWN0YmR6elZyNG84TVVKaitZZzFZQ29tUlZF | |
TTVSUzc2WnNQZWRTUEJrWkUyMTRXYk9BMEZnTWx4NApGVkhxQkRTYndPUmdI | |
NW1EaFluaU43T1pxWXhta3pUVXdiaFA3eXVZekpUWi9GZUNGeG50TmRBSHdq | |
amFYWG54CjFLbm5NSmZ1Yk01WEtYbzJOTGxaZEFNRzVSYjVBcFV0b0hUQlN2 | |
Rjg3Z3BjZTFtS2l5aS9RSG1Zem5jcG11aXQKbElGVzdTVXViRnRrajRWOFR5 | |
NTlXNnB1TG5MbjhQZGFTSUk5RktXY3ZKMTU1UFBSTVNENG1SNlZ0QUJIQnAz | |
UgpZVWpPLy9paWFGMEJTOFErRXhUdUV5SmJLYlpUOGluWWI0b3hTeGxnM0E9 | |
PQo9L1gzdAotLS0tLUVORCBQR1AgU0lHTkFUVVJFLS0tLS0K | |
http_version: | |
recorded_at: Wed, 10 Sep 2014 06:37:46 GMT | |
recorded_with: VCR 2.9.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment