keybase-core 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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