yamp 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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: []