keepasshttp 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -1
- data/Gemfile +3 -0
- data/Gemfile.lock +3 -1
- data/README.md +23 -5
- data/exe/keepasshttp +30 -1
- data/lib/keepasshttp.rb +29 -5
- data/lib/keepasshttp/key_store.rb +107 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f07357cd21290bc9cdc42bbf6b12060a890d499e33a27dbf7e9278391862c6d
|
4
|
+
data.tar.gz: 3f4659d7322951be51501b5c95880a734b75152f4a9780847572e707d3d69609
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c96c8c638dcab3ba57830b466f3c3dbab439100f4d54399f3497fe98538def7e35e5ecca2d8c44b8da7f3e6020f59ee565be482ce1968102b3f89039fe8df410
|
7
|
+
data.tar.gz: bcc493cf7281c03d75cf168466b009edb07338d63186ca4f3a6c467ca33f76f96930e08411176cd11b4f992ee1a810556a910f90015a6a977602d2cb89eedf50
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
keepasshttp (0.
|
4
|
+
keepasshttp (0.2.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
diff-lcs (1.3)
|
10
|
+
net-ssh (5.0.2)
|
10
11
|
rake (10.5.0)
|
11
12
|
rspec (3.8.0)
|
12
13
|
rspec-core (~> 3.8.0)
|
@@ -28,6 +29,7 @@ PLATFORMS
|
|
28
29
|
DEPENDENCIES
|
29
30
|
bundler (~> 1.16)
|
30
31
|
keepasshttp!
|
32
|
+
net-ssh
|
31
33
|
rake (~> 10.0)
|
32
34
|
rspec (~> 3.0)
|
33
35
|
|
data/README.md
CHANGED
@@ -20,14 +20,32 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
```
|
24
|
-
require '
|
23
|
+
```ruby
|
24
|
+
require 'keepasshttp'
|
25
25
|
|
26
|
-
keep =
|
26
|
+
keep = Keepasshttp.connect
|
27
27
|
|
28
|
-
keep.
|
28
|
+
keep.credentials_for('http://example.com')
|
29
29
|
```
|
30
30
|
|
31
|
+
### KeyStores
|
32
|
+
|
33
|
+
With the above code you'll be prompted by your Keepass to enter a label for the new key (because the tool generates a new key every time)
|
34
|
+
which is shorter that typing your password but still annoying. So I added a (session) key_store. At the moment you can choose between:
|
35
|
+
|
36
|
+
* :Plain - save your key in plaintext - maximum convienience, minimal security
|
37
|
+
```ruby
|
38
|
+
Keepasshttp.connect(key_store: :Plain)
|
39
|
+
```
|
40
|
+
* :SshAgent - (re)use your running ssh-agent session to encrypt your session key (and then save it to a file)
|
41
|
+
```ruby
|
42
|
+
Keepasshttp.connect(key_store: :SshAgent)
|
43
|
+
```
|
44
|
+
* { key:, id: } - Do the keymanagement yourself and just input the necessary keys as Hash.
|
45
|
+
```ruby
|
46
|
+
Keepasshttp.connect(key_store: { key: 'SECRET', id: 'Foo' })
|
47
|
+
```
|
48
|
+
|
31
49
|
## Development
|
32
50
|
|
33
51
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -37,7 +55,7 @@ To install this gem onto your local machine, run `bundle exec rake install`.
|
|
37
55
|
To see if it works run
|
38
56
|
|
39
57
|
```bash
|
40
|
-
$ keepasshttp URL_THAT_IS_IN_YOUR_KEEPASSDB
|
58
|
+
$ keepasshttp URL_THAT_IS_IN_YOUR_KEEPASSDB [OPTS]
|
41
59
|
```
|
42
60
|
|
43
61
|
If it works Keypass will prompt you for a label (which name you pick is irrelevant) and it should print you an json to the shell containing your data.
|
data/exe/keepasshttp
CHANGED
@@ -4,5 +4,34 @@
|
|
4
4
|
require 'bundler/setup'
|
5
5
|
require 'keepasshttp'
|
6
6
|
require 'json'
|
7
|
+
require 'optparse'
|
7
8
|
|
8
|
-
|
9
|
+
params = {}
|
10
|
+
|
11
|
+
ARGV.options do |opts|
|
12
|
+
opts.on('-p INTEGER', '--port', 'Use Keystore::Plain') do |val|
|
13
|
+
params[:port] = val.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
opts.on('--plain', 'Use Keystore::Plain') do
|
17
|
+
params[:key_store] = :Plain
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on('--ssh-agent', 'Use Keystore::SshAgent') do
|
21
|
+
params[:key_store] = :SshAgent
|
22
|
+
end
|
23
|
+
|
24
|
+
opts.on('--key STRING', 'Input your key directly') do |val|
|
25
|
+
params[:key_store] ||= {}
|
26
|
+
params[:key_store][:key] = val
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on('--id STRING', 'Input your id directly') do |val|
|
30
|
+
params[:key_store] ||= {}
|
31
|
+
params[:key_store][:id] = val
|
32
|
+
end
|
33
|
+
|
34
|
+
opts.parse!
|
35
|
+
end
|
36
|
+
|
37
|
+
puts Keepasshttp.connect(params).credentials_for(ARGV[0]).to_json
|
data/lib/keepasshttp.rb
CHANGED
@@ -17,23 +17,34 @@ class Keepasshttp
|
|
17
17
|
end
|
18
18
|
using Base64Helper
|
19
19
|
|
20
|
-
VERSION = '0.
|
20
|
+
VERSION = '0.2.0'
|
21
21
|
|
22
|
-
def self.connect(
|
23
|
-
kee = new(
|
22
|
+
def self.connect(**params)
|
23
|
+
kee = new(**params)
|
24
24
|
kee.login
|
25
25
|
kee
|
26
26
|
end
|
27
27
|
|
28
28
|
attr_accessor :port
|
29
29
|
attr_reader :session
|
30
|
+
attr_reader :id
|
31
|
+
autoload :KeyStore, 'keepasshttp/key_store'
|
30
32
|
|
31
|
-
def initialize(port: 19_455)
|
33
|
+
def initialize(port: 19_455, key_store: false)
|
32
34
|
@port = port
|
33
35
|
@session = false
|
36
|
+
init_keystore(key_store) if key_store
|
34
37
|
end
|
35
38
|
|
36
|
-
def
|
39
|
+
def init_keystore(key_store)
|
40
|
+
@key_store = if key_store.is_a?(Hash)
|
41
|
+
KeyStore::External.new(key_store)
|
42
|
+
else
|
43
|
+
KeyStore.const_get(key_store)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def credentials_for(url)
|
37
48
|
ping
|
38
49
|
|
39
50
|
enc_url = encrypt(url, iv: new_iv)
|
@@ -51,6 +62,9 @@ class Keepasshttp
|
|
51
62
|
|
52
63
|
@session = OpenSSL::Cipher.new('AES-256-CBC')
|
53
64
|
session.encrypt
|
65
|
+
|
66
|
+
return cached_login if @key_store&.available?
|
67
|
+
|
54
68
|
@key = session.random_key
|
55
69
|
new_iv
|
56
70
|
|
@@ -58,6 +72,16 @@ class Keepasshttp
|
|
58
72
|
return false unless json
|
59
73
|
|
60
74
|
@id = json['Id']
|
75
|
+
|
76
|
+
@key_store&.save(id: @id, key: @key)
|
77
|
+
end
|
78
|
+
|
79
|
+
def cached_login
|
80
|
+
cache = @key_store.load
|
81
|
+
@key = cache[:key]
|
82
|
+
@id = cache[:id]
|
83
|
+
new_iv
|
84
|
+
ping
|
61
85
|
end
|
62
86
|
|
63
87
|
def ping
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
class Keepasshttp
|
6
|
+
module KeyStore
|
7
|
+
# Input the key and the id directly into the client so you can take care
|
8
|
+
# of the storage yourself.
|
9
|
+
class External
|
10
|
+
def initialize(key:, id:)
|
11
|
+
@params = { key: key, id: id }
|
12
|
+
end
|
13
|
+
|
14
|
+
def save(*_args)
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def load
|
19
|
+
@params
|
20
|
+
end
|
21
|
+
|
22
|
+
def available?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# The most simple but unsecure way wo store your session key (so you don't
|
28
|
+
# have to reenter the label over and over again). Use this only for testing!
|
29
|
+
class Plain
|
30
|
+
# TODO, make the PATH adjustable
|
31
|
+
PATH = File.join(Dir.home, '.keepasshttp-ruby')
|
32
|
+
def self.save(params = {})
|
33
|
+
File.write(PATH, params.to_yaml)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.load
|
37
|
+
YAML.load_file(PATH)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.available?
|
41
|
+
File.exist?(PATH) && File.size(PATH).positive?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Use your running ssh-agent session to encrypt your session key
|
46
|
+
class SshAgent < Plain
|
47
|
+
class << self
|
48
|
+
def available?
|
49
|
+
require 'net/ssh'
|
50
|
+
|
51
|
+
super
|
52
|
+
rescue LoadError
|
53
|
+
raise LoadError, 'To use key_store: :SshAgent you have to install ' \
|
54
|
+
"the 'net-ssh' gem"
|
55
|
+
end
|
56
|
+
|
57
|
+
def save(params = {})
|
58
|
+
enc, iv = encrypt(params.delete(:key))
|
59
|
+
params[:key] = enc
|
60
|
+
params[:iv] = iv
|
61
|
+
super(params)
|
62
|
+
end
|
63
|
+
|
64
|
+
def load
|
65
|
+
params = super
|
66
|
+
params[:key] = decrypt(params[:key], iv: params.delete(:iv))
|
67
|
+
params
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def encrypt(string)
|
73
|
+
agent = Net::SSH::Authentication::Agent.connect
|
74
|
+
|
75
|
+
cip = OpenSSL::Cipher.new('AES-256-CBC')
|
76
|
+
cip.encrypt
|
77
|
+
iv = cip.random_iv
|
78
|
+
|
79
|
+
cip.key = agent.sign(identity(agent), iv)[-32..-1]
|
80
|
+
|
81
|
+
[cip.update(string) + cip.final, iv]
|
82
|
+
end
|
83
|
+
|
84
|
+
def decrypt(string, iv:)
|
85
|
+
agent = Net::SSH::Authentication::Agent.connect
|
86
|
+
|
87
|
+
cip = OpenSSL::Cipher.new('AES-256-CBC')
|
88
|
+
cip.decrypt
|
89
|
+
cip.iv = iv
|
90
|
+
|
91
|
+
cip.key = agent.sign(identity(agent), iv)[-32..-1]
|
92
|
+
|
93
|
+
cip.update(string) + cip.final
|
94
|
+
end
|
95
|
+
|
96
|
+
# TODO, make the key selectable
|
97
|
+
def identity(agent)
|
98
|
+
if agent.identities.empty?
|
99
|
+
raise 'No identity available. Run `ssh-add` and try again'
|
100
|
+
end
|
101
|
+
|
102
|
+
agent.identities.first
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: keepasshttp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Holger Arndt
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- exe/keepasshttp
|
75
75
|
- keepasshttp.gemspec
|
76
76
|
- lib/keepasshttp.rb
|
77
|
+
- lib/keepasshttp/key_store.rb
|
77
78
|
homepage: https://github.com/Kjarrigan/keepasshttp-ruby
|
78
79
|
licenses:
|
79
80
|
- MIT
|