keepassxc 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +41 -0
- data/exe/keepassxc-rb +17 -0
- data/keepassxc.gemspec +24 -0
- data/lib/keepassxc.rb +14 -0
- data/lib/keepassxc/client.rb +100 -0
- data/lib/keepassxc/helper.rb +11 -0
- data/lib/keepassxc/key_store.rb +50 -0
- data/lib/keepassxc/version.rb +3 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6c60203ef5b9cdcd3cbabce41a9712e62d35793cbc5f5a3cb40070a45acee25d
|
4
|
+
data.tar.gz: e23b41982c3bec59afff4a50230fa31e00172c51949749e9ac27d3477a94a434
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8737d87a03efbcb532f225cee2eb22ead55449944fc0c5b53b366b8bf922a4fb8197834e4d520061e0bfca1bda19b634de87bedda13df56fb789ad4a8edc213c
|
7
|
+
data.tar.gz: a2be3cf5b98ed7e63c65097882b391dd3faef90d0ee3345b6389575412ce70770bb561d79e37f91bce162fb323682047ab247cea4bb72601776a3a7fd55dfaf7
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# KeypassXC Ruby binding
|
2
|
+
|
3
|
+
You want to fetch login data as the browsers do. Then this is for you.
|
4
|
+
Similar to my https://github.com/Kjarrigan/keepasshttp-ruby repo.
|
5
|
+
|
6
|
+
## Work in progress
|
7
|
+
|
8
|
+
A coworker just asked me wether I have use the keepassxc-cli but it requires
|
9
|
+
to enter a password every time which is annoying and then I remembered my
|
10
|
+
keepasshttp-ruby binding and it turns out this is no longer the desired way
|
11
|
+
for KeepassXC. So why not make the new version work. Yay!
|
12
|
+
|
13
|
+
## Links
|
14
|
+
|
15
|
+
Some things have changed but the rough idea is the same. So I can probably copy
|
16
|
+
over quite a bit of context.
|
17
|
+
|
18
|
+
* [My HTTP Code](https://github.com/Kjarrigan/keepasshttp-ruby/blob/master/lib/keepasshttp.rb)
|
19
|
+
* [The official protocal docs](https://github.com/keepassxreboot/keepassxc-browser/blob/develop/keepassxc-protocol.md)
|
20
|
+
|
21
|
+
## Basic communication snippet
|
22
|
+
|
23
|
+
It is already working now! Altough some comfort is still missing, you can already register your client and
|
24
|
+
fetch logins. Yay!
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
load 'test.rb'
|
28
|
+
|
29
|
+
kpx = KeepassXC.new client_identifier: KEY_FROM_ASSOCIATE_OR_DB, client_name: ID_FROM_ASSOCIATE_OR_DB
|
30
|
+
kpx.change_public_keys
|
31
|
+
# kpx.associate
|
32
|
+
kpx.test_associate
|
33
|
+
p kpx.get_logins 'https://github.com'
|
34
|
+
```
|
35
|
+
|
36
|
+
You can check what clients are already registered in your DB via the GUI like this:
|
37
|
+
* Database
|
38
|
+
* Database-Settings
|
39
|
+
* Browser-Integration
|
40
|
+
|
41
|
+
Technically you could even re-use the Key/ID from your browser by just copying them from there.
|
data/exe/keepassxc-rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'keepassxc'
|
2
|
+
|
3
|
+
name = ARGV[1] || `hostname`.chomp
|
4
|
+
|
5
|
+
cfg = KeepassXC::KeyStore.find_or_create
|
6
|
+
kpx = KeepassXC::Client.new client_name: name
|
7
|
+
kpx.change_public_keys
|
8
|
+
if cfg.profiles[name]
|
9
|
+
kpx.client_identifier = cfg.profiles[name]
|
10
|
+
else
|
11
|
+
kpx.associate
|
12
|
+
cfg.profiles[name] = kpx.client_identifier
|
13
|
+
cfg.save
|
14
|
+
end
|
15
|
+
kpx.test_associate
|
16
|
+
|
17
|
+
puts kpx.get_logins(ARGV[0]).first['password']
|
data/keepassxc.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'lib/keepassxc/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'keepassxc'
|
5
|
+
spec.version = KeepassXC::VERSION
|
6
|
+
spec.authors = ['Holger Arndt']
|
7
|
+
spec.email = ['keepassxc-ruby@kjarrigan.de']
|
8
|
+
|
9
|
+
spec.summary = %q{Ruby bindings for the KeepassXC Browser API}
|
10
|
+
spec.description = %q{Ruby bindings for the KeepassXC Browser API}
|
11
|
+
spec.homepage = 'https://github.com/Kjarrigan/keepassxc-ruby'
|
12
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0')
|
13
|
+
|
14
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
15
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
16
|
+
spec.metadata['changelog_uri'] = spec.homepage
|
17
|
+
|
18
|
+
spec.files = Dir.chdir(__dir__) do
|
19
|
+
`git ls-files`.split("\n").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
|
+
end
|
21
|
+
spec.bindir = 'exe'
|
22
|
+
spec.executables = %w{keepassxc-rb}
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
end
|
data/lib/keepassxc.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
# TODO, replace this with openssl
|
5
|
+
require 'rbnacl'
|
6
|
+
|
7
|
+
module KeepassXC
|
8
|
+
class Error < StandardError; end
|
9
|
+
|
10
|
+
autoload :Client, 'keepassxc/client'
|
11
|
+
autoload :Helper, 'keepassxc/helper'
|
12
|
+
autoload :KeyStore, 'keepassxc/key_store'
|
13
|
+
autoload :VERSION, 'keepassxc/version'
|
14
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
module KeepassXC
|
4
|
+
class Client
|
5
|
+
include Helper
|
6
|
+
|
7
|
+
attr_accessor :client_id, :client_identifier, :client_name
|
8
|
+
|
9
|
+
def initialize(client_identifier: nil, client_name: nil)
|
10
|
+
@client_id = generate_nonce
|
11
|
+
user_id = `id -u`.chomp.to_i
|
12
|
+
@sock = UNIXSocket.new("/run/user/#{user_id}/org.keepassxc.KeePassXC.BrowserServer")
|
13
|
+
@private_key = RbNaCl::PrivateKey.generate
|
14
|
+
@client_identifier = client_identifier || to_b64(@private_key.public_key)
|
15
|
+
@client_name = client_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_nonce
|
19
|
+
to_b64 RbNaCl::Random.random_bytes
|
20
|
+
end
|
21
|
+
|
22
|
+
def change_public_keys
|
23
|
+
resp = send_msg(
|
24
|
+
action: 'change-public-keys',
|
25
|
+
publicKey: to_b64(@private_key.public_key),
|
26
|
+
nonce: generate_nonce,
|
27
|
+
clientID: @client_id
|
28
|
+
)
|
29
|
+
@session = RbNaCl::SimpleBox.from_keypair(resp['publicKey'].unpack1('m*'), @private_key)
|
30
|
+
|
31
|
+
resp
|
32
|
+
end
|
33
|
+
|
34
|
+
def associate
|
35
|
+
resp = send_encrypted_msg(
|
36
|
+
'action' => 'associate',
|
37
|
+
'key' => to_b64(@private_key.public_key),
|
38
|
+
'idKey' => @client_identifier
|
39
|
+
)
|
40
|
+
@client_name = resp['id']
|
41
|
+
|
42
|
+
resp
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_associate
|
46
|
+
send_encrypted_msg(
|
47
|
+
'action' => 'test-associate',
|
48
|
+
'key' => @client_identifier,
|
49
|
+
'id' => @client_name
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_logins(url)
|
54
|
+
send_encrypted_msg(
|
55
|
+
'action' => 'get-logins',
|
56
|
+
'url' => url,
|
57
|
+
'keys' => [
|
58
|
+
{
|
59
|
+
'id' => @client_name,
|
60
|
+
'key' => @client_identifier
|
61
|
+
}
|
62
|
+
]
|
63
|
+
)['entries']
|
64
|
+
end
|
65
|
+
|
66
|
+
def send_encrypted_msg(msg)
|
67
|
+
nonce, enc = encrypt(msg)
|
68
|
+
|
69
|
+
send_msg(
|
70
|
+
action: msg['action'],
|
71
|
+
message: to_b64(enc),
|
72
|
+
nonce: to_b64(nonce),
|
73
|
+
clientID: client_id
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
def encrypt(msg)
|
78
|
+
crypt = @session.box(JSON.dump(msg.transform_keys(&:to_s)))
|
79
|
+
nonce = crypt.slice!(0, RbNaCl::SecretBox.nonce_bytes)
|
80
|
+
|
81
|
+
[nonce, crypt]
|
82
|
+
end
|
83
|
+
|
84
|
+
def decrypt(msg, nonce:)
|
85
|
+
@session.decrypt(from_b64(nonce) + from_b64(msg))
|
86
|
+
end
|
87
|
+
|
88
|
+
def send_msg(msg)
|
89
|
+
@sock.send(JSON.dump(msg.transform_keys(&:to_s)), 0)
|
90
|
+
json = @sock.recvfrom(4096).first
|
91
|
+
resp = JSON.parse(json)
|
92
|
+
|
93
|
+
raise Error, resp['error'] if resp.key?('error')
|
94
|
+
resp = JSON.parse(decrypt(resp['message'], nonce: resp['nonce'])) if resp.key?('message')
|
95
|
+
binding.irb if resp['success'] != 'true'
|
96
|
+
|
97
|
+
resp
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module KeepassXC
|
5
|
+
class KeyStore
|
6
|
+
attr_reader :path
|
7
|
+
|
8
|
+
DEFAULT_PATH = File.join(Dir.home, '.config', 'keepassxc-rb')
|
9
|
+
def initialize(path: DEFAULT_PATH)
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
def create
|
14
|
+
unless exist?
|
15
|
+
FileUtils.mkdir_p File.dirname(path)
|
16
|
+
File.write(path, JSON.dump(profiles: {}))
|
17
|
+
end
|
18
|
+
File.chmod(0600, path) unless secure?
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.find_or_create(path: DEFAULT_PATH)
|
22
|
+
storage = new(path: path)
|
23
|
+
storage.create
|
24
|
+
storage
|
25
|
+
end
|
26
|
+
|
27
|
+
def raw
|
28
|
+
@raw ||= JSON.load_file(path)
|
29
|
+
rescue Errno::ENOENT
|
30
|
+
@raw = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def profiles
|
34
|
+
raw['profiles']
|
35
|
+
end
|
36
|
+
|
37
|
+
def save
|
38
|
+
create
|
39
|
+
File.write(path, JSON.dump(raw))
|
40
|
+
end
|
41
|
+
|
42
|
+
def secure?
|
43
|
+
File.stat(path).mode == 0600
|
44
|
+
end
|
45
|
+
|
46
|
+
def exist?
|
47
|
+
File.exist?(path)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: keepassxc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Holger Arndt
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-04-16 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Ruby bindings for the KeepassXC Browser API
|
14
|
+
email:
|
15
|
+
- keepassxc-ruby@kjarrigan.de
|
16
|
+
executables:
|
17
|
+
- keepassxc-rb
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- README.md
|
22
|
+
- exe/keepassxc-rb
|
23
|
+
- keepassxc.gemspec
|
24
|
+
- lib/keepassxc.rb
|
25
|
+
- lib/keepassxc/client.rb
|
26
|
+
- lib/keepassxc/helper.rb
|
27
|
+
- lib/keepassxc/key_store.rb
|
28
|
+
- lib/keepassxc/version.rb
|
29
|
+
homepage: https://github.com/Kjarrigan/keepassxc-ruby
|
30
|
+
licenses: []
|
31
|
+
metadata:
|
32
|
+
homepage_uri: https://github.com/Kjarrigan/keepassxc-ruby
|
33
|
+
source_code_uri: https://github.com/Kjarrigan/keepassxc-ruby
|
34
|
+
changelog_uri: https://github.com/Kjarrigan/keepassxc-ruby
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.7.0
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubygems_version: 3.1.2
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: Ruby bindings for the KeepassXC Browser API
|
54
|
+
test_files: []
|