yamp 0.0.5

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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/yamp +119 -0
  3. data/lib/yamp.rb +81 -0
  4. metadata +89 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 12d4147065962bc1538c030e019e60e3d0b7f6b0
4
+ data.tar.gz: e4d7a5c84938d78bc8b5256d35ce31596b8a331c
5
+ SHA512:
6
+ metadata.gz: 17ad410c73d0a142e8524b229871ae5411627908fbdd5ddddd044e7ddb877545f336539ffc7b23ffcbadefade141ed28d5c819c4443c88063630cc02657f0912
7
+ data.tar.gz: bd62ec4f70c9fdfb76f391f6e0de457aa48014b58f63ee14f76e5ef6f9f85475e1ae7038eb7a0898719d85909276f7b0e81ba049c0e3b25979f35fb6eeef694f
data/bin/yamp ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'io/console'
4
+ require 'clipboard'
5
+ require 'optparse'
6
+ require 'yamp'
7
+
8
+ trap "SIGINT" do puts "\nByeBye!"; exit(130) end
9
+
10
+ class String
11
+ def red; "\033[31m#{self}\033[0m" end
12
+ def green; "\033[32m#{self}\033[0m" end
13
+ def yellow; "\033[33m#{self}\033[0m" end
14
+ end
15
+
16
+ ARGV << '-h' if ARGV.empty?
17
+
18
+ vault = nil
19
+ options = {}
20
+ password_chars = [*'0'..'9', *'a'..'z',*'A'..'Z','#','!','?','$','/','(',')','[',']']
21
+
22
+ OptionParser.new do |opts|
23
+ opts.banner = %q(
24
+ Usage: yamp [options]
25
+
26
+ Examples:
27
+ yamp --add facebook --username johndoe@gmail.com --password abc123
28
+ yamp -a twitter
29
+ yamp --update twitter -n johndoe
30
+ yamp --get facebook
31
+ yamp -g twitter --to-clipboard
32
+ yamp --delete facebook
33
+ )
34
+ opts.on('-a', '--add ENTRY', 'create an entry') {|id| options[:add] = id}
35
+ opts.on('-g', '--get ENTRY', 'read an entry') {|id| options[:get] = id}
36
+ opts.on('-u', '--update ENTRY', 'update an entry') {|id| options[:upd] = id}
37
+ opts.on('-d', '--delete ENTRY', 'delete an entry') {|id| options[:del] = id}
38
+ opts.on('-p', '--password PWD', 'specify a password') {|pwd| options[:pwd] = pwd}
39
+ opts.on('-n', '--username USR', 'specify a username') {|usr| options[:usr] = usr}
40
+ opts.on('-l', '--list', 'list all entries') {options[:lst] = true}
41
+ opts.on('-c', '--to-clipboard', 'copy password to clipboard') {options[:clip] = true}
42
+ end.parse!
43
+
44
+ unless (options.keys & [:add, :del, :upd, :get, :lst]).size == 1
45
+ puts "please specifiy either --add, --delete, --update, --get or --list"
46
+ exit
47
+ end
48
+
49
+ print RUBY_PLATFORM =~ /darwin/ ? "🙈 " : ">"
50
+ master = STDIN.noecho(&:gets).chomp!; puts "\n"
51
+ begin
52
+ vault = YAMP::Vault.new master
53
+ rescue Exception => e
54
+ puts e.message
55
+ exit
56
+ end
57
+
58
+ if id = options[:add]
59
+ pwd = options[:pwd] ? options[:pwd] : 32.times.map {password_chars.sample}.join
60
+ unless vault.add id, pwd, options[:usr]
61
+ puts "entry already exists"
62
+ else
63
+ puts "+".green + " #{id}"
64
+ Clipboard.copy pwd if options[:clip]
65
+ end
66
+ exit
67
+ end
68
+
69
+ if id = options[:del]
70
+ unless vault.remove id
71
+ puts "no such entry"
72
+ else
73
+ puts "-".red + " #{id}"
74
+ end
75
+ exit
76
+ end
77
+
78
+ if id = options[:upd]
79
+ unless options[:pwd] || options[:usr]
80
+ puts "oops! did you forget something?"
81
+ exit
82
+ end
83
+ pwd_updated = false
84
+ usr_updated = false
85
+ if pwd = options[:pwd]
86
+ pwd_updated = vault.update id, :pwd, pwd
87
+ end
88
+ if usr = options[:usr]
89
+ usr_updated = vault.update id, :usr, usr
90
+ end
91
+ unless pwd_updated || usr_updated
92
+ puts "no such entry"
93
+ else
94
+ puts "*".yellow + " #{id}"
95
+ Clipboard.copy pwd if options[:clip]
96
+ end
97
+ exit
98
+ end
99
+
100
+ if id = options[:get]
101
+ password = vault.get id, :pwd
102
+ username = vault.get id, :usr
103
+ unless password || username
104
+ puts "no such entry"
105
+ else
106
+ puts username if username
107
+ unless options[:clip]
108
+ puts password
109
+ else
110
+ Clipboard.copy password
111
+ end
112
+ end
113
+ exit
114
+ end
115
+
116
+ if options[:lst]
117
+ puts vault.list.sort
118
+ exit
119
+ end
data/lib/yamp.rb ADDED
@@ -0,0 +1,81 @@
1
+
2
+ require 'redis'
3
+ require 'openssl'
4
+
5
+ module YAMP
6
+
7
+ class Vault
8
+
9
+ def initialize master, redis=Redis.new
10
+ @redis = redis
11
+ master_hash = redis.get "__mstr_h"
12
+ master_salt = redis.get "__mstr_s"
13
+ if master_hash && master_salt
14
+ @master_key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(master, master_salt, 10000, 32)
15
+ unless OpenSSL::Digest::SHA512.hexdigest(@master_key) == master_hash
16
+ raise ArgumentError, "access denied"
17
+ end
18
+ else
19
+ salt = OpenSSL::Random.random_bytes(32)
20
+ @master_key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(master, salt, 10000, 32)
21
+ redis.set "__mstr_h", OpenSSL::Digest::SHA512.hexdigest(@master_key)
22
+ redis.set "__mstr_s", salt
23
+ end
24
+ end
25
+
26
+ def add id, password, username=nil
27
+ return false if %w{__mstr_h __mstr_s}.include? id
28
+ return false unless @redis.hsetnx id, "pwd", encrypt(id, password)
29
+ @redis.hsetnx id, "usr", encrypt(id, username) if username
30
+ return true
31
+ end
32
+
33
+ def update id, key, value
34
+ return false if %w{__mstr_h __mstr_s}.include? id
35
+ return false unless [:pwd, :usr].include? key
36
+ @redis.hset id, key, encrypt(id, value)
37
+ end
38
+
39
+ def remove id
40
+ return false if %w{__mstr_h __mstr_s}.include? id
41
+ @redis.del id
42
+ end
43
+
44
+ def get id, key
45
+ return nil if %w{__mstr_h __mstr_s}.include? id
46
+ return nil unless [:pwd, :usr].include? key
47
+ return nil unless @redis.hexists id, key
48
+ decrypt id, @redis.hget(id, key)
49
+ end
50
+
51
+ def list
52
+ @redis.keys - %w{__mstr_h __mstr_s}
53
+ end
54
+
55
+ private
56
+
57
+ def encrypt id, data
58
+ cipher = OpenSSL::Cipher.new 'chacha20'
59
+ cipher.encrypt
60
+ iv = @redis.hget id, "__iv"
61
+ unless iv
62
+ iv = cipher.random_iv
63
+ @redis.hset id, "__iv", iv
64
+ else
65
+ cipher.iv = iv
66
+ end
67
+ cipher.key = @master_key
68
+ cipher.update(data) + cipher.final
69
+ end
70
+
71
+ def decrypt id, data
72
+ cipher = OpenSSL::Cipher.new 'chacha20'
73
+ cipher.decrypt
74
+ cipher.iv = @redis.hget id, "__iv"
75
+ cipher.key = @master_key
76
+ cipher.update(data) + cipher.final
77
+ end
78
+
79
+ end
80
+
81
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yamp
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Tobias Heilig
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-09-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: redis
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: openssl
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: clipboard
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
55
+ description: A minimal CLI-based password manager built upon redis-cache
56
+ email: holy708145@gmail.com
57
+ executables:
58
+ - yamp
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - bin/yamp
63
+ - lib/yamp.rb
64
+ homepage: http://rubygems.org/gems/yamp
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '2.0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements:
83
+ - redis, see https://redis.io
84
+ rubyforge_project:
85
+ rubygems_version: 2.6.13
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: yet another minimalistic passwordmanager
89
+ test_files: []