An unofficial, mostly Bitwarden-compatible API server written in Ruby (Sinatra and ActiveRecord)
1require_relative "spec_helper.rb"
2
3describe "User" do
4 USER_EMAIL = "user@example.com"
5 USER_PASSWORD = "p4ssw0rd"
6
7 before do
8 User.all.delete_all
9 Rubywarden::Test::Factory.create_user email: USER_EMAIL, password: USER_PASSWORD
10 end
11
12 it "should compare a user's hash" do
13 u = User.find_by_email(USER_EMAIL)
14 u.email.must_equal USER_EMAIL
15 u.has_password_hash?(
16 Bitwarden.hashPassword(USER_PASSWORD, USER_EMAIL,
17 User::DEFAULT_KDF_TYPE,
18 Bitwarden::KDF::DEFAULT_ITERATIONS[User::DEFAULT_KDF_TYPE])).must_equal true
19
20 u.has_password_hash?(
21 Bitwarden.hashPassword(USER_PASSWORD, USER_EMAIL + "2",
22 User::DEFAULT_KDF_TYPE,
23 Bitwarden::KDF::DEFAULT_ITERATIONS[User::DEFAULT_KDF_TYPE])).wont_equal true
24 end
25
26 it "encrypts and decrypts user's ciphers" do
27 u = User.find_by_email(USER_EMAIL)
28
29 mk = Bitwarden.makeKey(USER_PASSWORD, USER_EMAIL,
30 User::DEFAULT_KDF_TYPE,
31 Bitwarden::KDF::DEFAULT_ITERATIONS[User::DEFAULT_KDF_TYPE])
32
33 c = Cipher.new
34 c.user_uuid = u.uuid
35 c.type = Cipher::TYPE_LOGIN
36
37 cdata = {
38 "Name" => u.encrypt_data_with_master_password_key("some name", mk).to_s
39 }
40
41 c.data = cdata.to_json
42 c.migrate_data!.must_equal true
43
44 c = Cipher.where(:uuid => c.uuid).first
45 u.decrypt_data_with_master_password_key(c.to_hash["Name"], mk).
46 must_equal "some name"
47 end
48
49 it "supports changing a master password" do
50 u = User.find_by_email(USER_EMAIL)
51
52 mk = Bitwarden.makeKey(USER_PASSWORD, USER_EMAIL,
53 User::DEFAULT_KDF_TYPE,
54 Bitwarden::KDF::DEFAULT_ITERATIONS[User::DEFAULT_KDF_TYPE])
55
56 c = Cipher.new
57 c.user_uuid = u.uuid
58 c.type = Cipher::TYPE_LOGIN
59
60 cdata = {
61 "Name" => u.encrypt_data_with_master_password_key("some name", mk).to_s
62 }
63 c.data = cdata.to_json
64 c.migrate_data!.must_equal true
65
66 u.update_master_password(USER_PASSWORD, USER_PASSWORD + "2")
67 u.save.must_equal true
68
69 post "/identity/connect/token", {
70 :grant_type => "password",
71 :username => USER_EMAIL,
72 :password => Bitwarden.hashPassword(USER_PASSWORD + "2", USER_EMAIL,
73 User::DEFAULT_KDF_TYPE,
74 Bitwarden::KDF::DEFAULT_ITERATIONS[User::DEFAULT_KDF_TYPE]),
75 :scope => "api offline_access",
76 :client_id => "browser",
77 :deviceType => 3,
78 :deviceIdentifier => SecureRandom.uuid,
79 :deviceName => "firefox",
80 :devicePushToken => ""
81 }
82 last_response.status.must_equal 200
83
84 mk = Bitwarden.makeKey(USER_PASSWORD + "2", USER_EMAIL,
85 User::DEFAULT_KDF_TYPE,
86 Bitwarden::KDF::DEFAULT_ITERATIONS[User::DEFAULT_KDF_TYPE])
87
88 c = Cipher.find_by_uuid(c.uuid)
89 u.decrypt_data_with_master_password_key(c.to_hash["Name"], mk).
90 must_equal "some name"
91 end
92end