keepasshttp 0.1.1 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8babaeef8f439832b4219ddf366386242ede64d42fd74b204e658dcd7c61d983
4
- data.tar.gz: 4e9f8f1badad0824bb1ed6c67be75b03b31f0b3524be2287d89f7c794e572e93
3
+ metadata.gz: 2f07357cd21290bc9cdc42bbf6b12060a890d499e33a27dbf7e9278391862c6d
4
+ data.tar.gz: 3f4659d7322951be51501b5c95880a734b75152f4a9780847572e707d3d69609
5
5
  SHA512:
6
- metadata.gz: 339f9ac3d4e43896db11340e56aa021d4ce47044abcb8f573bb7028dfab6801a6f78a4c39ad4daed26c2c0863e6db394bed1f6471494371babfed9c7b1eca82a
7
- data.tar.gz: cc40c75b8f751b11026cd1420c4486e5b56c8e294dbb41971cf18e470f3eea9022e0899f15e452b1606f84405eafab6ddad5613e815e48f8d7cc2d229342c0d2
6
+ metadata.gz: c96c8c638dcab3ba57830b466f3c3dbab439100f4d54399f3497fe98538def7e35e5ecca2d8c44b8da7f3e6020f59ee565be482ce1968102b3f89039fe8df410
7
+ data.tar.gz: bcc493cf7281c03d75cf168466b009edb07338d63186ca4f3a6c467ca33f76f96930e08411176cd11b4f992ee1a810556a910f90015a6a977602d2cb89eedf50
@@ -2,4 +2,10 @@ AllCops:
2
2
  TargetRubyVersion: 2.5
3
3
 
4
4
  Naming/UncommunicativeMethodParamName:
5
- AllowedNames: [ iv ]
5
+ AllowedNames:
6
+ - iv
7
+ - id
8
+
9
+ Metrics/BlockLength:
10
+ Exclude:
11
+ - spec/*_spec.rb
data/Gemfile CHANGED
@@ -4,5 +4,8 @@ source 'https://rubygems.org'
4
4
 
5
5
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
6
 
7
+ # Optional depdendency
8
+ gem 'net-ssh'
9
+
7
10
  # Specify your gem's dependencies in keepasshttp.gemspec
8
11
  gemspec
@@ -1,12 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- keepasshttp (0.1.1)
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 'keepass'
23
+ ```ruby
24
+ require 'keepasshttp'
25
25
 
26
- keep = Keepass.connect
26
+ keep = Keepasshttp.connect
27
27
 
28
- keep.password_for('http://example.com')
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.
@@ -4,5 +4,34 @@
4
4
  require 'bundler/setup'
5
5
  require 'keepasshttp'
6
6
  require 'json'
7
+ require 'optparse'
7
8
 
8
- puts Keepasshttp.connect.password_for(ARGV[0]).to_json
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
@@ -17,23 +17,34 @@ class Keepasshttp
17
17
  end
18
18
  using Base64Helper
19
19
 
20
- VERSION = '0.1.1'
20
+ VERSION = '0.2.0'
21
21
 
22
- def self.connect(port: 19_455)
23
- kee = new(port: port)
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 password_for(url)
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.1.1
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-09-25 00:00:00.000000000 Z
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