one_pass 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7774961c176b2d6ebc5729b68030132c93d9d9df
4
+ data.tar.gz: 1e670ffa2e34cd27a9db1b1b947eac101a67763a
5
+ SHA512:
6
+ metadata.gz: 1026704202367e43c49d6da76355dc65c48b5559b17097ab39482b60d7c99fe7bdc2556878a32021f81831cb946e91d6c7f211d38ca45629bc3e6ea0b4e10c37
7
+ data.tar.gz: 9c5d4b84d154cb5013b1839b946665c1dd445be8b379ad294922c4879b038acb5cff4845a12300922506c596b75ca10bdb6c111091644b2aeec0696f098c012f
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.0
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'pry'
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ one_pass (0.1.0)
5
+ dispel (~> 0.0)
6
+ thor (~> 0.19)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ bump (0.5.3)
12
+ coderay (1.1.1)
13
+ curses (1.0.2)
14
+ diff-lcs (1.2.5)
15
+ dispel (0.0.7)
16
+ curses
17
+ method_source (0.8.2)
18
+ pry (0.10.3)
19
+ coderay (~> 1.1.0)
20
+ method_source (~> 0.8.1)
21
+ slop (~> 3.4)
22
+ rake (10.5.0)
23
+ rspec (3.4.0)
24
+ rspec-core (~> 3.4.0)
25
+ rspec-expectations (~> 3.4.0)
26
+ rspec-mocks (~> 3.4.0)
27
+ rspec-core (3.4.4)
28
+ rspec-support (~> 3.4.0)
29
+ rspec-expectations (3.4.0)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.4.0)
32
+ rspec-mocks (3.4.1)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.4.0)
35
+ rspec-support (3.4.1)
36
+ slop (3.6.0)
37
+ thor (0.19.1)
38
+
39
+ PLATFORMS
40
+ ruby
41
+
42
+ DEPENDENCIES
43
+ bump (~> 0.5)
44
+ bundler (~> 1.11)
45
+ one_pass!
46
+ pry
47
+ rake (~> 10.0)
48
+ rspec (~> 3.0)
49
+
50
+ BUNDLED WITH
51
+ 1.11.2
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Seth Voltz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,28 @@
1
+ # OnePass
2
+
3
+ 1Password command line client
4
+
5
+ ## Installation
6
+
7
+
8
+ ```ruby
9
+ gem install one_pass
10
+ ```
11
+
12
+ ## Usage
13
+
14
+
15
+ ## Development
16
+
17
+ 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.
18
+
19
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
20
+
21
+ ## Contributing
22
+
23
+ Bug reports and pull requests are welcome on GitHub at https://github.com/sethvoltz/one_pass.
24
+
25
+
26
+ ## License
27
+
28
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "bump/tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "OnePass"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ Secure Delete Variable in Memory
2
+ ================================
3
+
4
+ ```
5
+ pass = ""
6
+ $stdin.sysread(256, pass) # assuming a line-buffered terminal
7
+ io = StringIO.new("\0" * pass.bytesize)
8
+ io.read(pass.bytesize, pass)
9
+ ```
10
+
11
+ _Must_ use sysread as userspace buffering will likely leak one or more additional copies of the string.
data/exe/one-pass ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
3
+
4
+ require 'OnePass'
5
+ require 'OnePass/cli'
6
+
7
+ app = OnePass::CLI.start ARGV
data/lib/OnePass.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'OnePass/version'
2
+ require 'OnePass/op_vault'
@@ -0,0 +1,146 @@
1
+ require 'dispel'
2
+
3
+ module OnePass
4
+ # OnePass Application
5
+ class Application
6
+ CONFIG_PATH='~/.one_pass'
7
+
8
+ def initialize(vault_path = nil)
9
+ @vault_path = get_vault vault_path
10
+ @vault = OpVault.new @vault_path
11
+
12
+ @vault.unlock password_entry
13
+ @vault.load_items
14
+ end
15
+
16
+ def password_entry
17
+ accumulator = []
18
+ Dispel::Screen.open do |screen|
19
+ map = Dispel::StyleMap.new(screen.lines)
20
+ config = {
21
+ map: map,
22
+ width: screen.columns,
23
+ height: screen.lines,
24
+ mode: :password
25
+ }
26
+ screen.draw *draw_password_box(accumulator.length, config)
27
+
28
+ Dispel::Keyboard.output do |key|
29
+ case key
30
+ when :enter
31
+ case config[:mode]
32
+ when :cancel
33
+ raise 'Cancel'
34
+ else
35
+ break
36
+ end
37
+ when :backspace
38
+ accumulator.pop
39
+ when :down
40
+ config[:mode] = config[:mode] == :password ? :ok : config[:mode]
41
+ when :up
42
+ config[:mode] = :password
43
+ when :left
44
+ config[:mode] = config[:mode] == :password ? config[:mode] : :ok
45
+ when :right
46
+ config[:mode] = config[:mode] == :password ? config[:mode] : :cancel
47
+ else
48
+ accumulator.push key if config[:mode] == :password
49
+ end
50
+ screen.draw *draw_password_box(accumulator.length, config)
51
+ end
52
+ end
53
+ accumulator.join
54
+ end
55
+
56
+ def draw_password_box(pw_length, config)
57
+ message = 'Please enter your 1Password master password for the following vault:'
58
+ min_width = [message, @vault_path].max_by(&:length).length
59
+ prefix = 'Master Password: '
60
+
61
+ offset_left = (config[:width] - (min_width + 4)) / 2
62
+ offset_top = (config[:height] - 8) / 2
63
+ left = ' ' * offset_left
64
+ third = min_width / 3
65
+
66
+ password_string = ("*" * pw_length).ljust(min_width - prefix.length, '_')
67
+ buttons = '<OK>'.center(third) + ' ' * (min_width - (third * 2)) + '<Cancel>'.center(third)
68
+
69
+ box = ("\n" * offset_top)
70
+ box += "#{left}┏#{'━' * (min_width + 2)}┓\n"
71
+ box += "#{left}┃ #{message.ljust(min_width)} ┃\n"
72
+ box += "#{left}┃ #{@vault_path.ljust(min_width)} ┃\n"
73
+ box += "#{left}┃ #{' ' * min_width} ┃\n"
74
+ box += "#{left}┃ #{prefix}#{password_string} ┃\n"
75
+ box += "#{left}┃#{' ' * (min_width + 2)}┃\n"
76
+ box += "#{left}┃ #{buttons} ┃\n"
77
+ box += "#{left}┗#{'━' * (min_width + 2)}┛\n"
78
+
79
+ cursor_top = offset_top + (config[:mode] == :password ? 4 : 6)
80
+ cursor_left = offset_left
81
+ case config[:mode]
82
+ when :ok
83
+ cursor_left += third / 2
84
+ when :cancel
85
+ cursor_left += min_width - third + third / 2 - 2
86
+ else
87
+ cursor_left += prefix.length + pw_length + 2
88
+ end
89
+
90
+ [box, config[:map], [cursor_top, cursor_left]]
91
+ end
92
+
93
+ def get_vault(vault_path = nil)
94
+ return vault_path if vault_path
95
+ path = File.expand_path CONFIG_PATH
96
+ raise 'Config file missing, please log in' unless File.exist? path
97
+
98
+ config = File.read path
99
+ raise 'Config file error' unless config.start_with? 'path='
100
+ config[5..-1].strip
101
+ end
102
+
103
+ def show(query, reply_type)
104
+ item = @vault.find(/#{query}/i).first
105
+ data = @vault.item_overview item
106
+ unless %i( uuid url title ).include? reply_type
107
+ data.merge!(@vault.item_detail item)
108
+ end
109
+
110
+ case reply_type
111
+ when *%i( uuid url title )
112
+ data[reply_type.to_s]
113
+ when :username
114
+ data['fields'].find({}) { |field| field['designation'] == 'username' }['value']
115
+ when :password
116
+ data['fields'].find({}) { |field| field['designation'] == 'password' }['value']
117
+ else
118
+ data
119
+ end
120
+ end
121
+
122
+ def search(query)
123
+ @vault.find(/#{query}/i).collect do |item|
124
+ data = (@vault.item_overview item).merge(@vault.item_detail item)
125
+ {
126
+ uuid: data['uuid'],
127
+ title: data['title'],
128
+ username: data['fields'].find({}) { |field| field['designation'] == 'username' }['value']
129
+ }
130
+ end
131
+ end
132
+
133
+ def self.save(vault_path = nil)
134
+ app = self.new vault_path # if succeeds, path & pw is good
135
+ path = File.expand_path CONFIG_PATH
136
+ File.open path, File::CREAT|File::TRUNC|File::RDWR do |file|
137
+ file.write "path=#{File.expand_path vault_path}\n"
138
+ end
139
+ end
140
+
141
+ def self.forget
142
+ path = File.expand_path CONFIG_PATH
143
+ File.delete path if File.exist? path
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,56 @@
1
+ require 'io/console'
2
+ require 'thor'
3
+
4
+ require 'OnePass/application'
5
+
6
+ module OnePass
7
+ # OnePass CLI
8
+ class CLI < Thor
9
+ SHOW_OPTIONS = %w( all username password url uuid title )
10
+
11
+ desc 'login', 'Save a 1Password vault and verify password'
12
+ option :vault, aliases: '-v', type: :string, banner: 'Specify a vault path'
13
+ def login
14
+ OnePass::Application.save options.vault
15
+ end
16
+
17
+ desc 'logout', 'Forget any saved 1Password vault'
18
+ def logout
19
+ OnePass::Application.forget
20
+ end
21
+
22
+ desc 'show [type] {NAME|UUID}', 'Get a single item from your vault, use only one type'
23
+ option :clip, aliases: '-c', type: :boolean, banner: 'Copy value to clipboard instead of stdout'
24
+ SHOW_OPTIONS.each do |switch|
25
+ option switch.to_sym, type: :boolean
26
+ end
27
+ def show(name)
28
+ # Check for multiple mutex args
29
+ type = SHOW_OPTIONS.each_with_object(Hash.new) do |k, hash|
30
+ hash[k] = options[k] if options.has_key?(k)
31
+ end
32
+ if type.length > 1
33
+ puts "Use only one of #{SHOW_OPTIONS.collect { |switch| '--' + switch }.join ', '}"
34
+ exit 1
35
+ end
36
+
37
+ # TODO: Check if name looks like a UUID
38
+ # otherwise, search for title by substring, return first
39
+ app = OnePass::Application.new
40
+ reply_type = type.keys.first.to_sym
41
+ reply = app.show name, reply_type
42
+ puts reply_type == :all ? JSON.pretty_generate(reply) : reply
43
+ end
44
+
45
+ desc 'search QUERY', 'Perform fuzzy search for items in your vault, shows uuid, title and username'
46
+ def search(query)
47
+ app = OnePass::Application.new
48
+ puts JSON.pretty_generate(app.search query)
49
+ end
50
+
51
+ map ls: :list
52
+ desc 'list FOLDER', 'List the contents of a folder, shows title and username'
53
+ def list(folder)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,166 @@
1
+ # STD Libs
2
+ require 'base64'
3
+ require 'openssl'
4
+ require 'json'
5
+
6
+ module OnePass
7
+ # Handle all the 1Password OpVault operations
8
+ class OpVault
9
+ FIELD_TYPES = {
10
+ password: 'P',
11
+ text: 'T',
12
+ email: 'E',
13
+ number: 'N',
14
+ radio: 'R',
15
+ telephone: 'TEL',
16
+ checkbox: 'C',
17
+ url: 'U'
18
+ }
19
+
20
+ DESIGNATION_TYPES = {
21
+ username: 'username',
22
+ password: 'password',
23
+ none: ''
24
+ }
25
+
26
+ def initialize(vault_path)
27
+ check_and_set_vault vault_path
28
+ check_and_set_profile File.join(@vault_path, 'default', 'profile.js')
29
+ @items = {}
30
+ @item_index = {}
31
+ end
32
+
33
+ def check_and_set_vault(vault_path)
34
+ @vault_path = File.expand_path(vault_path)
35
+ unless File.exist? @vault_path
36
+ raise ArgumentError.new, 'Vault file does not exist'
37
+ end
38
+ end
39
+
40
+ def check_and_set_profile(profile_path)
41
+ unless File.exist? profile_path
42
+ raise ArgumentError.new, 'Vault profile does not exist'
43
+ end
44
+
45
+ profile = File.read profile_path
46
+ unless profile.start_with?('var profile=') && profile.end_with?(';')
47
+ raise 'Vault profile format incorrect'
48
+ end
49
+
50
+ @profile = JSON.parse profile[12..-2]
51
+ rescue
52
+ raise 'Unable to parse vault profile'
53
+ end
54
+
55
+ def unlock(master_password = nil)
56
+ master_password = yield if block_given?
57
+
58
+ salt = Base64.decode64(@profile['salt'])
59
+ iterations = @profile['iterations']
60
+ key, mac_key = derive_keys master_password, salt, iterations
61
+ @master_key, @master_mac_key = master_keys key, mac_key
62
+ @overview_key, @overview_mac_key = overview_keys key, mac_key
63
+ rescue
64
+ raise 'Incorrect password'
65
+ end
66
+
67
+ def lock
68
+ @master_key = @master_mac_key = nil
69
+ end
70
+
71
+ def check_hmac(data, hmac_key, desired_hmac)
72
+ digest = OpenSSL::Digest::SHA256.new
73
+ computed_hmac = OpenSSL::HMAC.digest digest, hmac_key, data
74
+ raise ArgumentError.new, 'Invalid HMAC' if computed_hmac != desired_hmac
75
+ end
76
+
77
+ def load_items
78
+ file_glob = File.join(@vault_path, 'default', 'band_*.js')
79
+ Dir.glob(file_glob) do |file|
80
+ band = JSON.parse File.read(file)[3..-3]
81
+ @items.merge! band
82
+ end
83
+
84
+ @items.each_pair do |uuid, item|
85
+ overview = item_overview item
86
+ @item_index[overview['title']] = uuid
87
+ end
88
+ end
89
+
90
+ def find(search)
91
+ @items.values_at *@item_index.values_at(*@item_index.keys.grep(search))
92
+ end
93
+
94
+ def decrypt_data(key, iv, data)
95
+ cipher = OpenSSL::Cipher::AES256.new(:CBC).decrypt
96
+ cipher.key = key
97
+ cipher.iv = iv
98
+ cipher.padding = 0
99
+ cipher.update(data) + cipher.final
100
+ end
101
+
102
+ def decrypt_opdata(cipher_text, cipher_key, cipher_mac_key)
103
+ key_data = cipher_text[0..-33]
104
+ mac_data = cipher_text[-32..-1]
105
+
106
+ check_hmac key_data, cipher_mac_key, mac_data
107
+ plaintext = decrypt_data cipher_key, key_data[16..31], key_data[32..-1]
108
+
109
+ plaintext_size = key_data[8..15].unpack('Q')[0]
110
+ plaintext[-plaintext_size..-1]
111
+ end
112
+
113
+ def derive_keys(master_password, salt, iterations)
114
+ digest = OpenSSL::Digest::SHA512.new
115
+ derived_key = OpenSSL::PKCS5.pbkdf2_hmac(
116
+ master_password, salt, iterations, digest.digest_length, digest
117
+ )
118
+
119
+ # => key, hmac
120
+ [derived_key[0..31], derived_key[32..63]]
121
+ end
122
+
123
+ def master_keys(derived_key, derived_mac_key)
124
+ encrypted = Base64.decode64(@profile['masterKey'])
125
+ decrypt_keys encrypted, derived_key, derived_mac_key
126
+ end
127
+
128
+ def overview_keys(derived_key, derived_mac_key)
129
+ encrypted = Base64.decode64(@profile['overviewKey'])
130
+ decrypt_keys encrypted, derived_key, derived_mac_key
131
+ end
132
+
133
+ def decrypt_keys(encrypted_key, derived_key, derived_mac_key)
134
+ key_base = decrypt_opdata encrypted_key, derived_key, derived_mac_key
135
+ keys = OpenSSL::Digest::SHA512.new.digest key_base
136
+
137
+ # => key, hmac
138
+ [keys[0..31], keys[32..63]]
139
+ end
140
+
141
+ def item_keys(item)
142
+ item_key = Base64.decode64 item['k']
143
+ key_data = item_key[0..-33]
144
+ key_hmac = item_key[-32..-1]
145
+
146
+ check_hmac key_data, @master_mac_key, key_hmac
147
+ plaintext = decrypt_data @master_key, key_data[0..15], key_data[16..-1]
148
+
149
+ # => key, hmac
150
+ [plaintext[0..31], plaintext[32..63]]
151
+ end
152
+
153
+ def item_overview(item)
154
+ data = Base64.decode64(item['o'])
155
+ overview = decrypt_opdata data, @overview_key, @overview_mac_key
156
+ { 'uuid' => item['uuid'] }.merge JSON.parse overview
157
+ end
158
+
159
+ def item_detail(item)
160
+ data = Base64.decode64(item['d'])
161
+ item_key, item_mac_key = item_keys item
162
+ detail = decrypt_opdata data, item_key, item_mac_key
163
+ { 'uuid' => item['uuid'] }.merge JSON.parse detail
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,3 @@
1
+ module OnePass
2
+ VERSION = '0.1.0'.freeze
3
+ end
data/one_pass.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'OnePass/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "one_pass"
8
+ spec.version = OnePass::VERSION
9
+ spec.authors = ["Seth Voltz"]
10
+ spec.email = ["seth@designgods.net"]
11
+
12
+ spec.summary = "A simple command line client for your 1Password vault"
13
+ spec.description = "Retrieve passwords from your 1Password OpVault-encoded vault via the command line"
14
+ spec.homepage = "https://sethvoltz.github.com/one_pass"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
+ # delete this section to allow pushing this gem to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ # end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_runtime_dependency "dispel", "~> 0.0"
31
+ spec.add_runtime_dependency "thor", "~> 0.19"
32
+
33
+ spec.add_development_dependency "bundler", "~> 1.11"
34
+ spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "rspec", "~> 3.0"
36
+ spec.add_development_dependency "bump", "~> 0.5"
37
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: one_pass
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Seth Voltz
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dispel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.19'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.19'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.11'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bump
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.5'
97
+ description: Retrieve passwords from your 1Password OpVault-encoded vault via the
98
+ command line
99
+ email:
100
+ - seth@designgods.net
101
+ executables:
102
+ - one-pass
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - ".ruby-version"
109
+ - ".travis.yml"
110
+ - Gemfile
111
+ - Gemfile.lock
112
+ - LICENSE.txt
113
+ - README.markdown
114
+ - Rakefile
115
+ - bin/console
116
+ - bin/setup
117
+ - doc/notes.markdown
118
+ - exe/one-pass
119
+ - lib/OnePass.rb
120
+ - lib/OnePass/application.rb
121
+ - lib/OnePass/cli.rb
122
+ - lib/OnePass/op_vault.rb
123
+ - lib/OnePass/version.rb
124
+ - one_pass.gemspec
125
+ homepage: https://sethvoltz.github.com/one_pass
126
+ licenses:
127
+ - MIT
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.5.1
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: A simple command line client for your 1Password vault
149
+ test_files: []