chupacabra 0.0.0 → 0.0.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dfaa094a87841fef12866c5ce7a1fc975cb642f0
4
+ data.tar.gz: 7da4daa7002ce40c5053fad4d996aca648354927
5
+ SHA512:
6
+ metadata.gz: 9e0e18c05e3541a0d2c9f1ca95b8aca28e87e6535f0dcb32f4d11a26d182a463d4c21c7836705bd9b7b8177ff598185bd18c03221d34743955b29a2b08439712
7
+ data.tar.gz: 129adb2c4fb29a30e32db9a0430c140eb21bf54d52a7ebfdf4cfa12337a1911c45cd27e5d7a4b446350da068015bb77672d3045f85b254a51e798309972dfc2e
data/bin/chupacabra ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env ruby
2
+ require 'chupacabra'
3
+ require 'optparse'
4
+ require 'ostruct'
5
+
6
+
7
+ options = OpenStruct.new
8
+
9
+ # Defaults
10
+ options.verbose = false
11
+
12
+ OptionParser.new do |opts|
13
+ opts.banner = "Usage: chupacabra [options]"
14
+
15
+ opts.on("-v", "--verbose", "Prints password") do |port|
16
+ options.verbose = true
17
+ end
18
+
19
+ opts.on("-V", "--version", "Output version") do |address|
20
+ puts Chupacabra::VERSION
21
+ exit
22
+ end
23
+
24
+ opts.on_tail("-h", "--help", "Show this message") do
25
+ puts opts
26
+ exit
27
+ end
28
+ end.parse!(ARGV)
29
+
30
+ if options.verbose
31
+ puts Chupacabra.get_password
32
+ else
33
+ Chupacabra.get_password
34
+ end
data/lib/chupacabra.rb CHANGED
@@ -1,3 +1,31 @@
1
- class Chupacabra
1
+ require 'chupacabra/system'
2
+ require 'chupacabra/crypto'
3
+ require 'chupacabra/storage'
4
+ require 'chupacabra/version'
2
5
 
6
+ module Chupacabra
7
+ extend self
8
+ attr_accessor :env
9
+
10
+ def get_password
11
+ data = Storage.new(System.get_password)
12
+ key = System.get_clipboard
13
+ if data[key]
14
+ output(data[key])
15
+ else
16
+ data[key] = Crypto.generate_password
17
+ output(data[key])
18
+ end
19
+ end
20
+
21
+ def test?
22
+ env == 'test'
23
+ end
24
+
25
+ private
26
+
27
+ def output(text)
28
+ System.set_clipboard(text)
29
+ text
30
+ end
3
31
  end
@@ -0,0 +1,41 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+
4
+ module Chupacabra
5
+ module Crypto
6
+
7
+ class WrongPassword < StandardError; end
8
+
9
+ extend self
10
+ PASSWORD_LENGTH = 32
11
+
12
+ def encrypt(text, password)
13
+ encrypter = OpenSSL::Cipher::Cipher.new 'AES256'
14
+ encrypter.encrypt
15
+ encrypter.pkcs5_keyivgen password
16
+ Base64.encode64(encrypter.update(text) + encrypter.final).strip
17
+ end
18
+
19
+ def decrypt(text, password)
20
+ encrypted = Base64.decode64(text).strip
21
+ decrypter = OpenSSL::Cipher::Cipher.new 'AES256'
22
+ decrypter.decrypt
23
+ decrypter.pkcs5_keyivgen password
24
+ decrypter.update(encrypted) + decrypter.final
25
+
26
+ rescue OpenSSL::Cipher::CipherError
27
+ raise WrongPassword, 'Wrong password'
28
+ end
29
+
30
+ def generate_password
31
+ letters = 'abcdefghijklmnopqrstuwxyz'
32
+ upcase = letters.upcase
33
+ numbers = '1234567890'
34
+ stuff = '!@$%^&#()-_'
35
+ all = [letters, upcase, numbers, stuff].collect{ |collection| collection.split('') }
36
+ output = all.collect { |collection| collection.shuffle.first }
37
+ (PASSWORD_LENGTH - all.length).times { output << all.flatten.shuffle.first }
38
+ output.join
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,60 @@
1
+ require 'pathname'
2
+
3
+ module Chupacabra
4
+ class Storage
5
+
6
+ def self.filepath
7
+ Pathname.new(ENV['HOME']) + filename
8
+ end
9
+
10
+ def self.clear
11
+ filepath.unlink if filepath.exist?
12
+ end
13
+
14
+ def initialize(password)
15
+ @password = password
16
+ end
17
+
18
+ def [](key)
19
+ data[extract(key)]
20
+ end
21
+
22
+ def []=(key, value)
23
+ data[extract(key)] = value
24
+ save
25
+ end
26
+
27
+ def to_h
28
+ data
29
+ end
30
+
31
+ private
32
+
33
+ def self.filename
34
+ Chupacabra.test? ? '.chupacabra_test' : '.chupacabra'
35
+ end
36
+
37
+ def data
38
+ @data ||=
39
+ if File.exists?(self.class.filepath)
40
+ Marshal.load(Crypto.decrypt(File.read(self.class.filepath), @password))
41
+ else
42
+ { }
43
+ end
44
+ end
45
+
46
+ def save
47
+ File.open(self.class.filepath, 'w') do |file|
48
+ file << Crypto.encrypt(Marshal.dump(@data), @password)
49
+ end
50
+ end
51
+
52
+ def extract(key)
53
+ if key =~ /https?\:\/\/(?:www.)?([^\/\?]+)/
54
+ $1
55
+ else
56
+ raise ArgumentError, "#{key} doesn't look like url"
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,69 @@
1
+ require 'base64'
2
+
3
+ module Chupacabra
4
+ module System
5
+ extend self
6
+
7
+ def get_password
8
+ return get_env_password if get_env_password
9
+ password = get_password_from_dialog
10
+ raise "Password can't be empty" if !password || password.empty?
11
+ set_env_password(password)
12
+ password
13
+ end
14
+
15
+ def clear
16
+ `launchctl unsetenv #{password_variable}` if osx?
17
+ end
18
+
19
+ def get_clipboard
20
+ `pbpaste`.strip
21
+ end
22
+
23
+ def set_clipboard(text)
24
+ raise 'Unsupported string' if text =~ /'/
25
+ `echo '#{text}' | pbcopy`
26
+ end
27
+
28
+ def osx?
29
+ `uname`.strip == 'Darwin'
30
+ end
31
+
32
+ def linux?
33
+ `uname`.strip == 'Linux'
34
+ end
35
+
36
+ private
37
+
38
+ def password_variable
39
+ Chupacabra.test? ? 'CHUPACABRA' : 'CHUPACABRA_TEST'
40
+ end
41
+
42
+ def get_password_from_dialog
43
+ strip_dialog_response(ask_for_password)
44
+ end
45
+
46
+ def strip_dialog_response(response)
47
+ response.match(/text returned:(.+), button returned:OK/)[1]
48
+ end
49
+
50
+ def ask_for_password
51
+ dialog = 'display dialog "Enter Chupacabra password"' +
52
+ 'default answer ""' +
53
+ 'with title "Chupacabra"' +
54
+ 'with icon caution with hidden answer'
55
+
56
+ `osascript -e 'tell application "Finder"' -e "activate" -e '#{dialog}' -e 'end tell'`
57
+ end
58
+
59
+ def get_env_password
60
+ password64 = `launchctl getenv #{password_variable}`.strip
61
+ return if password64.empty?
62
+ Base64.decode64(password64).strip
63
+ end
64
+
65
+ def set_env_password(password)
66
+ `launchctl setenv #{password_variable} '#{Base64.encode64(password).strip}'`
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ module Chupacabra
2
+ VERSION = '0.0.2'
3
+ end
metadata CHANGED
@@ -1,67 +1,92 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: chupacabra
3
- version: !ruby/object:Gem::Version
4
- hash: 31
5
- prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 0
10
- version: 0.0.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Dawid Sklodowski
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
-
18
- date: 2013-07-24 00:00:00 +01:00
19
- default_executable:
20
- dependencies: []
21
-
22
- description: Personal crypto pass
11
+ date: 2013-07-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Encrypted and easy to use personal storage for user passwords
23
56
  email: dawid.sklodowski@gmail.com
24
- executables: []
25
-
57
+ executables:
58
+ - chupacabra
26
59
  extensions: []
27
-
28
60
  extra_rdoc_files: []
29
-
30
- files:
61
+ files:
62
+ - bin/chupacabra
63
+ - lib/chupacabra/crypto.rb
64
+ - lib/chupacabra/storage.rb
65
+ - lib/chupacabra/system.rb
66
+ - lib/chupacabra/version.rb
31
67
  - lib/chupacabra.rb
32
- has_rdoc: true
33
68
  homepage: http://github.com/dawid-sklodowski/chupacabra
34
- licenses: []
35
-
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
36
72
  post_install_message:
37
73
  rdoc_options: []
38
-
39
- require_paths:
74
+ require_paths:
40
75
  - lib
41
- required_ruby_version: !ruby/object:Gem::Requirement
42
- none: false
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- hash: 3
47
- segments:
48
- - 0
49
- version: "0"
50
- required_rubygems_version: !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ">="
54
- - !ruby/object:Gem::Version
55
- hash: 3
56
- segments:
57
- - 0
58
- version: "0"
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
59
86
  requirements: []
60
-
61
87
  rubyforge_project:
62
- rubygems_version: 1.6.2
88
+ rubygems_version: 2.0.2
63
89
  signing_key:
64
- specification_version: 3
65
- summary: Chupacabra
90
+ specification_version: 4
91
+ summary: Personal crypto pass
66
92
  test_files: []
67
-