keybase-core 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +19 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +2 -0
  6. data/Gemfile.lock +49 -0
  7. data/LICENSE +23 -0
  8. data/README.md +137 -0
  9. data/Rakefile +20 -0
  10. data/keybase.gemspec +25 -0
  11. data/lib/keybase.rb +49 -0
  12. data/lib/keybase/crypto.rb +20 -0
  13. data/lib/keybase/error.rb +37 -0
  14. data/lib/keybase/models/dump.rb +33 -0
  15. data/lib/keybase/models/user.rb +168 -0
  16. data/lib/keybase/request/base.rb +32 -0
  17. data/lib/keybase/request/dump/all.rb +10 -0
  18. data/lib/keybase/request/dump/latest.rb +10 -0
  19. data/lib/keybase/request/key/add.rb +13 -0
  20. data/lib/keybase/request/key/revoke.rb +14 -0
  21. data/lib/keybase/request/root/get_salt_and_login_session.rb +12 -0
  22. data/lib/keybase/request/root/login.rb +14 -0
  23. data/lib/keybase/request/sig/post_auth.rb +13 -0
  24. data/lib/keybase/request/user/lookup.rb +10 -0
  25. data/lib/keybase/response.rb +14 -0
  26. data/lib/keybase/token_store.rb +32 -0
  27. data/test/all.rb +6 -0
  28. data/test/fixtures/example_dump.json +9 -0
  29. data/test/fixtures/example_user.json +50 -0
  30. data/test/integration/dumps_test.rb +23 -0
  31. data/test/integration/keys_test.rb +26 -0
  32. data/test/integration/login_users_test.rb +18 -0
  33. data/test/integration/lookup_users_test.rb +42 -0
  34. data/test/integration_test_helper.rb +6 -0
  35. data/test/test_helper.rb +17 -0
  36. data/test/unit/lib/keybase/crypto_test.rb +45 -0
  37. data/test/unit/lib/keybase/error_test.rb +32 -0
  38. data/test/unit/lib/keybase/models/dump_test.rb +31 -0
  39. data/test/unit/lib/keybase/models/user_test.rb +136 -0
  40. data/test/unit/lib/keybase/requests/base_test.rb +60 -0
  41. data/test/unit/lib/keybase/requests/dump/all_test.rb +17 -0
  42. data/test/unit/lib/keybase/requests/dump/latest_test.rb +17 -0
  43. data/test/unit/lib/keybase/requests/key/add_test.rb +19 -0
  44. data/test/unit/lib/keybase/requests/key/revoke_test.rb +19 -0
  45. data/test/unit/lib/keybase/requests/root/get_salt_test.rb +23 -0
  46. data/test/unit/lib/keybase/requests/root/login_test.rb +19 -0
  47. data/test/unit/lib/keybase/requests/sig/post_auth_test.rb +19 -0
  48. data/test/unit/lib/keybase/requests/user/lookup_test.rb +17 -0
  49. data/test/unit/lib/keybase/response_test.rb +23 -0
  50. data/test/unit/lib/keybase/token_store_test.rb +25 -0
  51. data/test/unit/lib/keybase_test.rb +25 -0
  52. data/test/vcr_cassettes/dumps.yml +49418 -0
  53. data/test/vcr_cassettes/keys.yml +349 -0
  54. data/test/vcr_cassettes/user_login.yml +176 -0
  55. data/test/vcr_cassettes/user_lookup_foo.yml +89 -0
  56. data/test/vcr_cassettes/user_lookup_invalid.yml +52 -0
  57. data/test/vcr_cassettes/user_lookup_missing.yml +52 -0
  58. data/test/vcr_cassettes/user_lookup_not_found.yml +55 -0
  59. metadata +200 -0
@@ -0,0 +1,26 @@
1
+ require_relative '../test_helper'
2
+ require_relative '../integration_test_helper'
3
+
4
+ module Keybase
5
+ class KeysIntegrationTest < Minitest::Test
6
+
7
+ def setup
8
+ VCR.use_cassette('keys') do
9
+ @me = User.login('seanhandley', 'secret')
10
+ @public_key = @me.public_keys.primary.bundle
11
+ @private_key = @me.private_keys.primary.bundle
12
+ @old_public_kid = @me.public_keys.primary.kid
13
+ @old_private_kid = @me.private_keys.primary.kid
14
+
15
+ @me.revoke_key(@me.public_keys.primary.kid)
16
+ @public_kid = @me.add_public_key(@public_key)
17
+ @private_kid = @me.add_private_key(@private_key)
18
+ end
19
+ end
20
+
21
+ def test_kids_match
22
+ assert_equal @old_public_kid, @old_private_kid
23
+ assert_equal @public_kid, @private_kid
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ require_relative '../test_helper'
2
+ require_relative '../integration_test_helper'
3
+
4
+ module Keybase
5
+ class LoginUsersIntegrationTest < Minitest::Test
6
+
7
+ def test_login
8
+ VCR.use_cassette('user_login') do
9
+ user = User.login('seanhandley', 'secret')
10
+ assert_equal "secret", user.private_keys.primary.bundle
11
+ assert_equal "dude@testing.com", user.emails.primary.email
12
+ assert_equal 'lgHZIDA0MmNjYWYwMTMxZmZlZDNiZGE1MDAyM2M3ZGEzNzA4zlMxfzfOAAFRgMDEIPBYxx9HWUnY8GVK2rYzx29hOQW5DXDNkONntT1FjGxI', TokenStore.csrf
13
+ assert_equal 'guest=lgHZIGJkM2E1MGNmMjBjNmQ0MzQwMmFhMDI4Mjc4YzJiZjA4zlMxfzjOAAFRgMDEINQblgb3pKa15JV58bI2VqKfWGvPFe3qcLUuq153%2Be7C; Max-Age=604.8; Domain=.keybase.io; Path=/; Expires=Tue, 25 Mar 2014 13:16:04 GMT; HttpOnly; Secure, session=lgHZIGU3MjBmNWE0Y2NlOWM2MGY5NDUzOGQzMDk1OWU3MTAwzlMxfzjOAeEzgNkgODViZmU1ZGI4MzM3NzM4NDk2MDRmZGIzOWZkM2UxMDLEII%2B6%2FmdEgDo74uwb%2BQDMrDt6m06NFhs0eQjX9popcagO; Max-Age=31536000; Domain=.keybase.io; Path=/; Expires=Wed, 25 Mar 2015 13:06:00 GMT; HttpOnly; Secure', TokenStore.cookie
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,42 @@
1
+ require_relative '../test_helper'
2
+ require_relative '../integration_test_helper'
3
+
4
+ module Keybase
5
+ class LookupUsersIntegrationTest < Minitest::Test
6
+
7
+ def setup
8
+ VCR.use_cassette('user_lookup_foo') do
9
+ @user = Keybase.lookup("foo")
10
+ end
11
+ end
12
+
13
+ def test_user_object_has_expected_fields
14
+ assert @user.respond_to? :id
15
+ end
16
+
17
+ def test_user_not_found
18
+ VCR.use_cassette('user_lookup_not_found') do
19
+ assert_raises(Keybase::UserNotFoundError, 'user not found foofoofooofo') do
20
+ @user = User.lookup('foofoofooofo')
21
+ end
22
+ end
23
+ end
24
+
25
+ def test_username_missing
26
+ VCR.use_cassette('user_lookup_missing') do
27
+ assert_raises(Keybase::InputError, 'missing or invalid input. username: missing name') do
28
+ @user = User.lookup('')
29
+ end
30
+ end
31
+ end
32
+
33
+ def test_username_invalid
34
+ VCR.use_cassette('user_lookup_invalid') do
35
+ assert_raises(Keybase::InputError, 'missing or invalid input. username: invalid name') do
36
+ @user = User.lookup('d8dw9sfu83u39229i9fewdsi0-fdsii-i')
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ require 'vcr'
2
+
3
+ VCR.configure do |c|
4
+ c.cassette_library_dir = 'test/vcr_cassettes'
5
+ c.hook_into :webmock
6
+ end
@@ -0,0 +1,17 @@
1
+ if require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/test/'
4
+ end
5
+ end
6
+
7
+ require_relative '../lib/keybase'
8
+ EXAMPLE_USER_JSON = IO.read(File.expand_path('../fixtures/example_user.json', __FILE__))
9
+ EXAMPLE_USER = JSON.parse(EXAMPLE_USER_JSON)
10
+ EXAMPLE_DUMP_JSON = IO.read(File.expand_path('../fixtures/example_dump.json', __FILE__))
11
+ EXAMPLE_DUMP = JSON.parse(EXAMPLE_DUMP_JSON)
12
+
13
+ TEST_ENV = true
14
+
15
+ require 'rubygems'
16
+ gem "minitest"
17
+ require 'minitest/autorun'
@@ -0,0 +1,45 @@
1
+ module Keybase
2
+ require_relative '../../../test_helper'
3
+
4
+ class CryptoTest < Minitest::Test
5
+ def setup
6
+ @passphrase = "passphrase"
7
+ @salt = "salt"
8
+ @key = "key"
9
+ @data = "data"
10
+ @random = SecureRandom.random_bytes(224).bytes
11
+ end
12
+
13
+ def test_scrypt_passes_to_engine_and_truncates_result
14
+ args = lambda { |*args|
15
+ assert_equal @passphrase, args[0]
16
+ assert_equal [@salt].pack("H*"), args[1]
17
+ @random
18
+ }
19
+ SCrypt::Engine.stub(:scrypt, args) do
20
+ response = Crypto.scrypt(@passphrase, @salt)
21
+ assert_equal 32, response.size
22
+ end
23
+ end
24
+
25
+ def test_hmac_sha512_passes_to_openssl
26
+ args = lambda { |_, key, data|
27
+ assert_equal @key, key
28
+ assert_equal Base64.decode64(@data), data
29
+ nil
30
+ }
31
+ OpenSSL::HMAC.stub(:hexdigest, args) do
32
+ Crypto.hmac_sha512(@key, @data)
33
+ end
34
+ end
35
+
36
+ def test_defines_scrypt_vars
37
+ assert defined?(Crypto::SCRYPT_VARS)
38
+ end
39
+
40
+ def self.hmac_sha512(key, data)
41
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA512.new, key, data)
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,32 @@
1
+ module Keybase
2
+ require_relative '../../../test_helper'
3
+
4
+ class ErrorTest < Minitest::Test
5
+ def setup
6
+ @status = {'code' => 100, 'fields' => {'username' => 'dsay7984yfhuragh4u3q9fR^&%^%'}, 'desc' => 'Invalid username'}
7
+ @unknown = {'code' => 1337, 'fields' => {'foo' => 'bar'}, 'desc' => 'baz'}
8
+ end
9
+
10
+ def test_behaviour_with_known_error_code
11
+ assert_raises InputError do
12
+ begin
13
+ Error.raise_unless_successful(@status)
14
+ catch StandardError => e
15
+ assert_equal 'Invalid username. username: dsay7984yfhuragh4u3q9fR^&%^%', e.msg
16
+ raise
17
+ end
18
+ end
19
+ end
20
+
21
+ def test_behaviour_with_unknown_error_code
22
+ assert_raises Keybase::Error do
23
+ begin
24
+ Error.raise_unless_successful(@unknown)
25
+ catch StandardError => e
26
+ assert_equal 'Error 1337: baz. foo: bar', e.msg
27
+ raise
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ module Keybase
2
+
3
+ require_relative '../../../../test_helper'
4
+
5
+ class DumpTest < Minitest::Test
6
+ def setup
7
+ @dump = Dump.new(EXAMPLE_DUMP)
8
+ end
9
+
10
+ def test_unix_time_parsed_to_date
11
+ assert_equal "2014-02-24T18:46:31+00:00",
12
+ @dump.created_at.to_s
13
+ end
14
+
15
+ def test_dump_all
16
+ Request::Dump.stub :all, [{'dump_id' => 1, 'ctime' => 1393267591},
17
+ {'dump_id' => 2, 'ctime' => 1393267591}] do
18
+ dumps = Dump.all
19
+ assert_equal 1, dumps[0].id
20
+ assert_equal 2, dumps[1].id
21
+ end
22
+ end
23
+
24
+ def test_dump_latest
25
+ Request::Dump.stub :latest, {'dump_id' => 1, 'ctime' => 1393267591} do
26
+ assert_equal 1, Dump.latest.id
27
+ assert_equal '2014-02-24T18:46:31+00:00', Dump.latest.created_at.to_s
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,136 @@
1
+ module Keybase
2
+
3
+ require_relative '../../../../test_helper'
4
+
5
+ class UserTest < Minitest::Test
6
+ def setup
7
+ @user = User.new(EXAMPLE_USER)
8
+ @username = 'foo'
9
+ @salt = 'salt'
10
+ @login_session = 'login_session'
11
+ @passphrase = 'passphrase'
12
+ @pwh = "secret"
13
+ @kid = 123
14
+ end
15
+
16
+ def test_unix_times_parsed_to_dates_for_basics
17
+ assert_equal "2013-10-30T19:24:21+00:00",
18
+ @user.basics.created_at.to_s
19
+ assert_equal "2013-10-30T19:41:01+00:00",
20
+ @user.basics.updated_at.to_s
21
+ end
22
+
23
+ def test_unix_times_parsed_to_dates_for_profile
24
+ assert_equal "2013-10-31T19:22:19+00:00",
25
+ @user.profile.updated_at.to_s
26
+ end
27
+
28
+ def test_unix_times_parsed_to_dates_for_public_keys
29
+ assert_equal "2013-11-05T21:00:12+00:00",
30
+ @user.public_keys.primary.created_at.to_s
31
+ assert_equal "2013-11-05T21:00:12+00:00",
32
+ @user.public_keys.primary.updated_at.to_s
33
+ end
34
+
35
+ def test_unix_times_parsed_to_dates_for_private_keys
36
+ assert_equal "2013-11-05T21:00:12+00:00",
37
+ @user.private_keys.primary.created_at.to_s
38
+ assert_equal "2013-11-05T21:00:12+00:00",
39
+ @user.private_keys.primary.updated_at.to_s
40
+ end
41
+
42
+ def test_emails_set_correctly
43
+ assert_equal EXAMPLE_USER['emails']['primary']['email'], @user.emails.primary.email
44
+ assert_equal true, @user.emails.primary.is_verified?
45
+ assert_equal EXAMPLE_USER['emails']['secondary']['email'], @user.emails.secondary.email
46
+ assert_equal false, @user.emails.secondary.is_verified?
47
+ end
48
+
49
+ def test_user_lookup_loads_from_returned_hash
50
+ Request::User.stub :lookup, EXAMPLE_USER do
51
+ user = User.lookup('foo')
52
+ assert_equal EXAMPLE_USER['id'], user.id
53
+ end
54
+ end
55
+
56
+ def test_object_loads_when_data_missing
57
+ @empty = User.new({})
58
+ assert_nil @empty.basics
59
+ assert_nil @empty.profile
60
+ assert_nil @empty.emails
61
+ assert_nil @empty.public_keys
62
+ assert_nil @empty.private_keys
63
+ end
64
+
65
+ def test_login_calls_correct_methods
66
+ get_salt_args = lambda {|email_or_username|
67
+ assert_equal @username, email_or_username
68
+ [@salt, @login_session]
69
+ }
70
+ login_args = lambda {|email_or_username, hmac_pwh, login_session|
71
+ {'me' => EXAMPLE_USER}
72
+ }
73
+ scrypt_args = lambda {|passphrase, salt|
74
+ assert_equal @passphrase, passphrase
75
+ assert_equal @salt, salt
76
+ @pwh
77
+ }
78
+ hmac_sha512_args = lambda{|key, data|
79
+ assert_equal @login_session, data
80
+ assert_equal @pwh, key
81
+ }
82
+ Request::Root.stub(:get_salt_and_login_session, get_salt_args) do
83
+ Request::Root.stub(:login, login_args) do
84
+ Crypto.stub(:scrypt, scrypt_args) do
85
+ Crypto.stub(:hmac_sha512, hmac_sha512_args) do
86
+ me = User.login(@username, @passphrase)
87
+ assert_equal me.id, EXAMPLE_USER['id']
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ def test_post_auth_calls_correct_methods
95
+ args = lambda {|username, sig|
96
+ assert_equal @user.basics.username, username
97
+ assert_equal 'foo', sig
98
+ 'auth_token'
99
+ }
100
+ Request::Sig.stub(:post_auth, args) do
101
+ assert_equal 'auth_token', @user.post_auth('foo')
102
+ end
103
+ end
104
+
105
+ def test_add_public_key_calls_correct_methods
106
+ args = lambda {|params|
107
+ assert_equal 'foo', params[:public_key]
108
+ @kid
109
+ }
110
+ Request::Key.stub(:add, args) do
111
+ assert_equal @kid, @user.add_public_key('foo')
112
+ end
113
+ end
114
+
115
+ def test_add_private_key_calls_correct_methods
116
+ args = lambda {|params|
117
+ assert_equal 'foo', params[:private_key]
118
+ @kid
119
+ }
120
+ Request::Key.stub(:add, args) do
121
+ assert_equal @kid, @user.add_private_key('foo')
122
+ end
123
+ end
124
+
125
+ def test_revoke_key_calls_correct_methods
126
+ args = lambda {|kid|
127
+ assert_equal @kid, kid
128
+ true
129
+ }
130
+ Request::Key.stub(:revoke, args) do
131
+ assert @user.revoke_key(@kid)
132
+ end
133
+ end
134
+
135
+ end
136
+ end
@@ -0,0 +1,60 @@
1
+ module Keybase
2
+ require_relative '../../../../test_helper'
3
+
4
+ module Request
5
+ class RequestBaseTest < Minitest::Test
6
+ def setup
7
+ @server_response = Object.new
8
+ @conn = Faraday.new
9
+ @response = OpenStruct.new(body: true)
10
+ end
11
+
12
+ def test_get_returns_keybase_response
13
+ Base.stub :conn, @conn do
14
+ @conn.stub :get, nil do
15
+ Keybase::Response.stub :new, @response do
16
+ assert Base.get('foo', {})
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def test_get_passes_params
23
+ @mock = MiniTest::Mock.new
24
+ @mock.expect(:get, @response, ['foo', { 'bar' => 'baz'}])
25
+ Base.stub :conn, @mock do
26
+ Keybase::Response.stub :new, @response do
27
+ Base.get('foo', 'bar' => 'baz')
28
+ end
29
+ end
30
+ @mock.verify
31
+ end
32
+
33
+ def test_post_returns_keybase_response
34
+ Base.stub :conn, @conn do
35
+ @conn.stub :post, nil do
36
+ Keybase::Response.stub :new, @response do
37
+ assert Base.post('foo', {})
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ def test_post_passes_params
44
+ @mock = MiniTest::Mock.new
45
+ @mock.expect(:post, @response, ['foo', { 'bar' => 'baz'}])
46
+ Base.stub :conn, @mock do
47
+ Keybase::Response.stub :new, @response do
48
+ Base.post('foo', 'bar' => 'baz')
49
+ end
50
+ end
51
+ @mock.verify
52
+ end
53
+
54
+ def test_base_url_defined
55
+ assert defined?(API_BASE_URL)
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../../../../../test_helper'
2
+
3
+ module Keybase
4
+ module Request
5
+ class DumpAllTest < Minitest::Test
6
+ def setup
7
+ @response = { 'dumps' => [EXAMPLE_DUMP, EXAMPLE_DUMP] }
8
+ end
9
+
10
+ def test_all_returns_dumps
11
+ Base.stub :get, @response do
12
+ assert_equal 2, Request::Dump.all.count
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../../../../../test_helper'
2
+
3
+ module Keybase
4
+ module Request
5
+ class DumpLatestTest < Minitest::Test
6
+ def setup
7
+ @response = { 'dump' => EXAMPLE_DUMP }
8
+ end
9
+
10
+ def test_latest_returns_dump
11
+ Base.stub :get, @response do
12
+ assert_equal "472eba4586993583b395b00e", Request::Dump.latest['dump_id']
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end