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 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