kyle 0.0.4 → 0.0.5

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
  SHA1:
3
- metadata.gz: 0e3f01dd717ea2c77c86f500aac403598e5dff92
4
- data.tar.gz: 7769d19716cacdd3bd146c99163b7bea667a2344
3
+ metadata.gz: 3f04555392f57d6f09a00cc5f1e2a5bc5f185efe
4
+ data.tar.gz: 5369fc8ad09357dd2791e3945c967f7f95290ae0
5
5
  SHA512:
6
- metadata.gz: b8e9f48d5d94cb23a7fe63474494180cf77a98e76950e10185d9a8c4a4ad81a2f8beb2a39e6cdd32b42cdda297fbc55e00be8daa60df732e9dc178ee8f5477fb
7
- data.tar.gz: 05770529219032c2338a956d9853d9dccf58263cfc24f324a6e04af4eaec073fd6fc282c0d57b8cfc9972e0b889bb0b8714baa55138de473d89895a77751a756
6
+ metadata.gz: 5d2565eeb14b542d6afbbb0e940734329168172caa165535ac2679716a3d9fb9108b68af11ce49b89b9a92bc15ff38f860f4043895f898875ac0527d141e2799
7
+ data.tar.gz: af2beb34df3ae60876544336624936850695812c1f5a2b4d97e2ba3db9d46bb0d39ed3033f35c47b8316382936935e9deca50ad7a9031bcfd6f99b97414fab6d
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ .DS_Store
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,47 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ kyle (0.0.3)
5
+ highline (~> 1.6, >= 1.6.20)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ ast (2.0.0)
11
+ astrolabe (1.3.0)
12
+ parser (>= 2.2.0.pre.3, < 3.0)
13
+ diff-lcs (1.2.5)
14
+ highline (1.6.21)
15
+ parser (2.2.0.pre.4)
16
+ ast (>= 1.1, < 3.0)
17
+ slop (~> 3.4, >= 3.4.5)
18
+ powerpack (0.0.9)
19
+ rainbow (2.0.0)
20
+ rspec (3.0.0)
21
+ rspec-core (~> 3.0.0)
22
+ rspec-expectations (~> 3.0.0)
23
+ rspec-mocks (~> 3.0.0)
24
+ rspec-core (3.0.3)
25
+ rspec-support (~> 3.0.0)
26
+ rspec-expectations (3.0.3)
27
+ diff-lcs (>= 1.2.0, < 2.0)
28
+ rspec-support (~> 3.0.0)
29
+ rspec-mocks (3.0.3)
30
+ rspec-support (~> 3.0.0)
31
+ rspec-support (3.0.3)
32
+ rubocop (0.26.0)
33
+ astrolabe (~> 1.3)
34
+ parser (>= 2.2.0.pre.4, < 3.0)
35
+ powerpack (~> 0.0.6)
36
+ rainbow (>= 1.99.1, < 3.0)
37
+ ruby-progressbar (~> 1.4)
38
+ ruby-progressbar (1.5.1)
39
+ slop (3.6.0)
40
+
41
+ PLATFORMS
42
+ ruby
43
+
44
+ DEPENDENCIES
45
+ kyle!
46
+ rspec (~> 3.0.0)
47
+ rubocop (~> 0.26)
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Harun Esur
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,244 @@
1
+ Kyle
2
+ ====
3
+ A password manager for paranoids.
4
+
5
+ ### Overview
6
+
7
+ Kyle differs from other password managers, since:
8
+
9
+ * It doesn't store any passwords so there is nothing to steal/crack for
10
+ attackers.
11
+ * However, you can't store any given password, but must set one generated by
12
+ Kyle.
13
+
14
+ Kyle differs from other password generators, since:
15
+
16
+ * Generated passwords are not random, but a brute-force method can take
17
+ thousands of years to crack one:
18
+
19
+ e.g. on the test vectors Bill Gates' password tooks 12.11 seconds on a MacBook
20
+ Pro Early 2013 with 2,4 GHZ Intel Core i7. So even for a lazy master-key with
21
+ 8 chars includes small-case-letters and numbers, there are
22
+ `36^8+36^7+36^5+36^4+36^3+36^2+36 = 2901713047668` combinations; with 12.11s
23
+ per combination, it would take ***1,114,274 years*** to try all combinations.
24
+
25
+ * It doesn't use any specific hash or encryption algorithm, using a mixture of
26
+ several, chosen using the input info and key.
27
+
28
+ ### Installation
29
+
30
+ ```bash
31
+ $ gem install kyle
32
+ ```
33
+
34
+ ### Usage
35
+
36
+ Just type `kyle` on the command line to run, and pick any password depending
37
+ on your favourite animal.
38
+
39
+ ```bash
40
+ $ kyle
41
+ Hostname:
42
+ abc.com
43
+ Account:
44
+ superuser
45
+ Port:
46
+ 80
47
+ Key:
48
+
49
+
50
+ Ape _,o_iMmO5L!ZRlQH
51
+ Bat EZPBcTf6oo-jzWpM
52
+ Bear .ZmYlZ4PQpdOfish
53
+ Whale wb%EOphi7uqySwRZ
54
+ Crow eTXvLc.4FgTdIEJ%
55
+ Dog .Q,PBaMeFRO8nG-a
56
+ Cat ,lHFEMVXo%SjTlsm
57
+ Wasp e0CyUAHvs9-ljGFr
58
+ Fox 2%yxWtBZz-cOVW@b
59
+ Gull avuR86nGjG6DNkkX
60
+ Jackal +zhRwHPWCHknxlZp
61
+ Lion xMxPwb0E+5vQ_q4x
62
+ Panda qj7GQqJP7EKjU*gG
63
+ Rat kvniGIszq758@Sie
64
+ Shark 1aF3.iiV,e*OTGpT
65
+ Spider *nrvUtila0wnmb22
66
+ Turtle wYQerXRYffJJGvxZ
67
+ Wolf MD!VTDkikYxZvzM!
68
+ Zebra asVw!Q/5!QvqxiRf
69
+ ```
70
+
71
+ You can also specify the hostname, account, port, and animal when typing the
72
+ command:
73
+
74
+ ```bash
75
+ $ kyle abc.com superuser 80 jackal
76
+ Key:
77
+
78
+
79
+ +zhRwHPWCHknxlZp
80
+ ```
81
+
82
+ Arguments must in this order, but any missing ones will be prompted for.
83
+
84
+ Adding the `-c` flag will prompt for the key twice, so you can be sure you
85
+ didn't make a typo.
86
+
87
+ Adding the `-r` flag saves the hostname/account/port combination in `~/.kyle`.
88
+
89
+ Adding `-a ` flag lets you choose from one of savedhost/account/port records saved with -r;
90
+
91
+
92
+ #### Batch usage
93
+
94
+ ```bash
95
+ $ kyle -b path/to/file.kyle animal
96
+ Key:
97
+
98
+
99
+ hostname:account:port (animal) = password
100
+ hostname:account:port (animal) = password
101
+ ```
102
+
103
+ Where `file.kyle` contains triples of hostname, account, port separated by
104
+ semi-colons (`;`), one per line. E.g.:
105
+
106
+ ```
107
+ facebook.com;zuckerberg;80
108
+ amazon.com;bezos;443
109
+ ```
110
+
111
+ ### Changelog
112
+
113
+ #### 0.0.5
114
+
115
+ * Merge version with Isaac Seymour's efforts to unify multiple development lines that includes;
116
+
117
+ * Refactored code to have proper Rspec tests, and respect Rubocop conventions
118
+
119
+ * Added ability to specify hostname, account, port, and animal as args to the
120
+ executable
121
+
122
+ #### 0.0.4
123
+
124
+ * Added -a (Auto) flag
125
+
126
+ #### 0.0.2
127
+
128
+ * Added -b (BATCH) mode which help you generate bulk passwords;
129
+
130
+ * Added -r option to add entered values to <USER_HOME>/.kyle file
131
+
132
+ ### Algorithm
133
+
134
+ #### Overall
135
+
136
+ ```
137
+
138
+ +--------+ +-------+ +----+ +----------+
139
+ |HOSTNAME| |ACCOUNT| |PORT| |MASTER-KEY|
140
+ +---+----+ +---+---+ +--+-+ +-----+----+
141
+ | | | |
142
+ v v v v
143
+ +------+ +------+ +------+ +------+
144
+ |I.HASH| |I.HASH| |I.HASH| |I.HASH|
145
+ +------+ +------+ +------+ +------+
146
+ | | | |
147
+ v v v v
148
+ +------+ +------+ +------+ +------+
149
+ |I.HASH| |I.HASH| |I.HASH| |I.HASH|
150
+ +------+ +------+ +------+ +------+
151
+ + + + +
152
+ | | | |
153
+ +-----+++----+ +-----+++----+
154
+ | |
155
+ v v
156
+ +------+ +------+
157
+ |I.ENC.| |I.ENC.|
158
+ +------+ +------+
159
+ + +
160
+ | |
161
+ +------------+++-------+
162
+ |
163
+ v
164
+ +------+
165
+ |I.ENC.|
166
+ +------+ +------------+
167
+ + |ANIMAL NAMES|
168
+ | +------------+
169
+ ENC | A1..AN |
170
+ | +------------+
171
+ v
172
+ +--(A1..AN)------------------------------+
173
+ |RES = PBKDF2_HMAC_SHA1(ENC,RES,10000,32)|
174
+ +----------------------------------------+
175
+ +
176
+ v
177
+ +-----------------------------+
178
+ |HASH_TO_PASSWORD(SHA512(RES))|
179
+ +-----------------------------+
180
+ + + +
181
+ | | |
182
+ (A1..AN)
183
+ | | |
184
+ v v v
185
+
186
+ MULTIPLE PASSES
187
+
188
+ ```
189
+
190
+ #### Iterative Hash
191
+
192
+ ```
193
+ +-------------+
194
+ Iterative Hash |ALGORITHMS |
195
+ +-------------+
196
+ +-------------+ +--> |SHA512 |
197
+ |Text=(t1..tn)| | +-------------+
198
+ +------+------+ +--> |SHA384 |
199
+ | | +-------------+
200
+ | +--> |SHA256 |
201
+ v | +-------------+
202
+ +--(i=1..n)-----------------------------------------+ +--> |SHA224 |
203
+ |HASH=ALGORITHM[(ti % ALGORITHMS.SIZE)](Text | HASH)|+-+ +-------------+
204
+ +---------------------------------------------------+ +--> |SHA1 |
205
+ + | +-------------+
206
+ | +--> |SHA2 |
207
+ | | +-------------+
208
+ v +--> |MD5 |
209
+ | +-------------+
210
+ HASH +--> |MD4 |
211
+ | +-------------+
212
+ +--> |RIPEMD160 |
213
+ +-------------+
214
+ ```
215
+
216
+ #### Iterative Encryption
217
+
218
+ ```
219
+ +-------------+
220
+ Iterative Encryption |ALGORITHMS |
221
+ +-------------+
222
+ +-------------+ +--> |DES3 |
223
+ |TEXT=(t1..tn)| | +-------------+
224
+ |KEY=(k1..kn) | +--> |DESX |
225
+ +-------------+ | +-------------+
226
+ | +--> |DES |
227
+ v | +-------------+
228
+ +--(i=1..n)----------------------------------------------+ +--> |CAST |
229
+ |ENC.=ALGORITHM[(ti % ALGORITHMS.SIZE)]((Text | ENC.),KEY|--------->| +-------------+
230
+ +-------------------------------------------+------------+ +--> |BLOWFISH |
231
+ + | ^ | +-------------+
232
+ | | | +--> |AES128 |
233
+ | | | | +-------------+
234
+ | v | +--> |AES192 |
235
+ | +--------------+------------+ | +-------------+
236
+ | |KEY=PBKDF2("kyle",10000,32)| +--> |AES256 |
237
+ | | IV=SHA512(KEY) | | +-------------+
238
+ | +---------------------------+ +--> |RC4 |
239
+ | +-------------+
240
+ v
241
+
242
+ ENCRYPTED
243
+ ```
244
+
data/bin/kyle CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'kyle'
3
+ require 'kyle_commands'
4
4
 
5
- Kyle.run(ARGV)
5
+ KyleCommands.new(ARGV).run
data/kyle.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = 'kyle'
3
+ gem.version = '0.0.5'
4
+ gem.date = '2014-09-17'
5
+
6
+ gem.summary = 'Kyle'
7
+ gem.description = 'A password manager for paranoids.'
8
+ gem.authors = ['Harun Esur', 'Isaac Seymour']
9
+ gem.email = 'harun.esur@sceptive.com'
10
+ gem.homepage = 'http://sceptive.com'
11
+ gem.license = 'MIT'
12
+ gem.requirements << 'Ruby should be compiled with openssl support.'
13
+
14
+ gem.executables << 'kyle'
15
+
16
+ gem.files = `git ls-files`.split("\n")
17
+
18
+ gem.add_runtime_dependency 'highline', '~> 1.6', '>= 1.6.20'
19
+
20
+ gem.add_development_dependency 'rubocop', '~> 0.26'
21
+ gem.add_development_dependency 'rspec', '~> 3.0.0'
22
+ end
data/lib/constants.rb ADDED
@@ -0,0 +1,15 @@
1
+ # Algorithms, password characters, animals
2
+ module Constants
3
+ ENC_ALGS = %w(des3 desx des cast bf aes128 aes192 aes256 rc4).freeze
4
+ HASH_ALGS = %w(sha512 sha384 sha256 sha224 sha1 sha md5 md4 ripemd160).freeze
5
+
6
+ LETTERS = %w(q w e r t y u i o p a s d f g h j k l z x c v b n m).freeze
7
+ BIG_LETTERS = %w(Q W E R T Y U I O P A S D F G H J K L Z X C V B N M).freeze
8
+ NUMBERS = %w(0 1 2 3 4 5 6 7 8 9).freeze
9
+ SPECIAL_CHARS = %w(. @ + - * / % _ ! ,).freeze
10
+
11
+ PASSWORD_CHARS = (LETTERS + BIG_LETTERS + NUMBERS + SPECIAL_CHARS).freeze
12
+
13
+ ANIMALS = %w(Ape Bat Bear Whale Crow Dog Cat Wasp Fox Gull Jackal Lion Panda
14
+ Rat Shark Spider Turtle Wolf Zebra).freeze
15
+ end
data/lib/kyle.rb CHANGED
@@ -1,277 +1,118 @@
1
1
  #!/usr/bin/ruby
2
2
  require 'openssl'
3
3
  require 'highline/import'
4
+ require 'constants'
4
5
 
6
+ # Password generation from 4 inputs
7
+ class Kyle
8
+ attr_accessor :hostname, :account, :port, :key
5
9
 
6
- $ENC_ALGS = [
7
- "des3", "desx", "des", "cast", "bf",
8
- "aes128", "aes192", "aes256", "rc4"
9
-
10
- ]
10
+ def initialize(hostname, account, port, key)
11
+ @hostname = hostname
12
+ @account = account
13
+ @port = port
14
+ @key = key
15
+ end
11
16
 
12
- $HSH_ALGS = [
13
- "sha512", "sha384", "sha256", "sha224", "sha1", "sha",
14
- "md5", "md4", "ripemd160"
15
- ]
17
+ def passwords
18
+ @passwords ||= generate
19
+ end
16
20
 
17
- $letters = [
18
- "q","w","e","r","t","y","u","i","o","p",
19
- "a","s","d","f","g","h","j","k","l","z",
20
- "x","c","v","b","n","m"
21
- ]
21
+ def generate
22
+ passwords = {}
22
23
 
23
- $bletters = [
24
- "Q","W","E","R","T","Y","U","I","O","P",
25
- "A","S","D","F","G","H","J","K","L","Z",
26
- "X","C","V","B","N","M"
27
- ]
24
+ salt = encrypted_inputs
25
+ cipher = salt
28
26
 
29
- $nums = [
30
- "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
31
- ]
27
+ Constants::ANIMALS.each do |a|
28
+ cipher = OpenSSL::PKCS5.pbkdf2_hmac_sha1(cipher, salt, 10_000, 32)
32
29
 
33
- $schars = [
34
- ".", "@", "+", "-", "*", "/", "%", "_", "!", ","
35
- ]
30
+ passwords[a] = Kyle.hash_to_password(cipher)
31
+ end
36
32
 
37
- $passctable = []
33
+ passwords
34
+ end
38
35
 
39
- $letters.each { |c| $passctable << c }
40
- $bletters.each { |c| $passctable << c }
41
- $nums.each { |c| $passctable << c }
42
- $schars.each { |c| $passctable << c }
36
+ def hashed_hostname
37
+ Kyle.hash_twice(hostname)
38
+ end
43
39
 
44
- $animalnames = [
45
- "Ape", "Bat", "Bear", "Whale", "Crow", "Dog", "Cat", "Wasp",
46
- "Fox", "Gull", "Jackal", "Lion", "Panda", "Rat", "Shark", "Spider",
47
- "Turtle", "Wolf", "Zebra"
48
- ]
40
+ def hashed_account
41
+ Kyle.hash_twice(account)
42
+ end
49
43
 
50
- class Kyle
44
+ def hashed_port
45
+ Kyle.hash_twice(port)
46
+ end
51
47
 
52
- def self.to_hex(s)
53
- s.each_byte.map { |b| b.to_s(16) }.join
48
+ def hashed_key
49
+ Kyle.hash_twice(key)
54
50
  end
55
51
 
52
+ def encrypted_inputs
53
+ Kyle.iterative_encrypt(
54
+ Kyle.iterative_encrypt(hashed_hostname, hashed_account),
55
+ Kyle.iterative_encrypt(hashed_port, hashed_key))
56
+ end
56
57
 
57
- def self.enc_it(alg,val,key)
58
- #puts "enc_it #{alg} #{to_hex(val)} #{to_hex(key)}"
59
- begin
60
- cipher = OpenSSL::Cipher::Cipher.new(alg)
61
- cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(key, "kyle", 10000, 32)
62
- cipher.iv = sha512ize(key)
63
- cipher.encrypt
64
- return cipher.update(val) + cipher.final
65
- rescue OpenSSL::Cipher::CipherError => e
66
- puts "Error: #{e.message}"
67
- end
58
+ #################
59
+ # Class methods #
60
+ #################
61
+ def self.encrypt(alg, val, key)
62
+ cipher = OpenSSL::Cipher::Cipher.new(alg)
63
+ cipher.key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(key, 'kyle', 10_000, 32)
64
+ cipher.iv = sha512ize(key)
65
+ cipher.encrypt
66
+ return cipher.update(val) + cipher.final
67
+ rescue OpenSSL::Cipher::CipherError => e
68
+ puts "Error: #{e.message}"
68
69
  end
69
70
 
70
- def self.iterative_enc(val, key)
71
+ def self.iterative_encrypt(val, key)
71
72
  ret = val
73
+
72
74
  val.each_byte do |c|
73
- ret = enc_it($ENC_ALGS[c % ($ENC_ALGS.size)], ret, key)
75
+ alg = Constants::ENC_ALGS[c % Constants::ENC_ALGS.length]
76
+ ret = encrypt(alg, ret, key)
74
77
  end
75
-
76
- return ret
78
+
79
+ ret
77
80
  end
78
81
 
79
- def self.hash_it(alg,val)
80
- #puts "hash_it #{alg} - #{to_hex(val)}"
81
- OpenSSL::Digest.digest(alg,val)
82
+ def self.hash(alg, val)
83
+ OpenSSL::Digest.digest(alg, val)
82
84
  end
83
85
 
84
86
  def self.iterative_hash(val)
85
87
  ret = val
88
+
86
89
  val.each_byte do |c|
87
- ret = hash_it($HSH_ALGS[c % ($HSH_ALGS.size)], ret)
90
+ alg = Constants::HASH_ALGS[c % Constants::HASH_ALGS.length]
91
+ ret = hash(alg, ret)
88
92
  end
89
- return ret
93
+
94
+ ret
90
95
  end
91
96
 
92
97
  def self.sha512ize(val)
93
- hash_it("sha512",val)
98
+ hash('sha512', val)
94
99
  end
95
100
 
96
- def self.di_hash(val)
101
+ def self.hash_twice(val)
97
102
  iterative_hash(iterative_hash(val))
98
103
  end
99
104
 
100
- def self.hash2pass(val)
101
- ret = ""
102
-
103
- # to be sure it is long enough
104
- h = sha512ize(val)
105
-
106
- h.each_byte do |c|
107
- ret += $passctable[c % ($passctable.size)]
108
- end
109
-
110
- return ret[0..15]
111
- end
112
-
113
-
114
-
115
- def self.generate(hostname,account,port,key)
116
-
117
- ret = Array.new
118
-
119
- harr = [ di_hash(hostname), di_hash(account), di_hash(port), di_hash(key) ]
120
-
121
- v1 = iterative_enc(harr[0],harr[1])
122
- v2 = iterative_enc(harr[2],harr[3])
105
+ def self.hash_to_password(val)
106
+ ret = ''
123
107
 
124
- v = iterative_enc(v1,v2)
125
-
126
- c = v
127
- $animalnames.each do |animal|
128
- c = OpenSSL::PKCS5.pbkdf2_hmac_sha1(c, v, 10000, 32)
129
-
130
- ret << hash2pass(c)
131
-
132
- end
133
-
134
- return ret
135
- end
136
-
137
- $testarr = [
138
- [
139
- "microsoft.com","bill.gates","666","iKnowWhatYouDidToIBMLastSummer",
140
- "WW0nQIY.0Rn6D8d2", "nXzU19faM7*gv7,I", "cgu0q7*DuT65r3rY", "ILZ,5vZLl/wRxf9y",
141
- "Od..eF2k6_l3XHxe", "sedWPnJsSb4DEJw-", "JEr_SzZBoofgI7Tb", "xbbg@ebdz3FA.n6S",
142
- "5EMS!XZP7WfPLKpO", "LcwDHUu0/ynzdSWE", "5+fDOoY.yrE+ESbj", "VWKqetfVKZtT,FI9",
143
- "EDe7XvMZ%8tt2vsT", "vks.HPeDVkklS_qb", "hcVznOxvT5YvxIlU", "iBTr-I42uz7h7XnA",
144
- "fLV,g6%@1G7xpQil", "toMFvN@Zd,b*KBC%", "FYbi/6Udx_4mO3D0"
145
- ],
146
- [
147
- $passctable.join,$passctable.join,$passctable.join,$passctable.join,
148
- "cuoTJm!UuIYCcQxs", "3HrQ3s/j53A+Rssm", "KK+IV7QE9Imd65hi", "M@FH%uduAIvn/0Fg",
149
- "C@ffelLPbsh!ps68", "mF%j06cgTaD63v5C", "5pRiaZDk%SY6quet", "d56XIGF8PhHu!TfI",
150
- "71UES8Six9G48hsc", "kmtu%gr1.k%T!tPy", "zE8*qE+uU.PsOkYY", "77Rbxcaiwp4Fwm.M",
151
- "qWT0K%tFP8w7_H0S", "2uGyZI.SzAOujmkw", ".QhaGPzV_jnnRj@F", "4FsOh0GfaM4MVUUH",
152
- "_3r0DzAdYvEp@dlA", "qcWgE@nt9SgUEsjP", "8F1BJ.OlV5Kj!wmM"
153
- ]
154
- ]
155
-
156
- def self.test_it()
157
- puts "Testing..."
158
-
159
- failed = false
160
- (0..1).each do |idx|
161
- vals = generate($testarr[idx][0],$testarr[idx][1],$testarr[idx][2],$testarr[idx][3])
162
- vals.each.with_index(0) do |v,i|
163
- if ($testarr[idx][i+4] != v)
164
- puts "Test failed: #{$testarr[idx][i+4]} <> #{v}"
165
- failed = true
166
- end
167
- end
168
- end
169
- puts "Finished #{failed ? "and Failed" : "successfully"}"
170
- end
171
-
172
- def self.getkey()
173
-
174
- key = "a"
175
- key2 = "b"
108
+ # to be sure it is long enough
109
+ hashed = sha512ize(val)
176
110
 
177
- while (key != key2)
178
- key = ask("Key:") { |q| q.echo = false }
179
- key2 = ask("Key (again):") { |q| q.echo = false }
180
-
181
- if (key != key2)
182
- puts "Passes do not match!!"
183
- end
111
+ hashed.each_byte do |c|
112
+ ret += Constants::PASSWORD_CHARS[c % Constants::PASSWORD_CHARS.length]
113
+ break if ret.length >= 16
184
114
  end
185
115
 
186
- return key
187
-
188
- end
189
-
190
- def self.run(args)
191
-
192
- puts "Kyle - A password manager for paranoids. ( 0.0.4 )"
193
- puts ""
194
-
195
- if (args.size > 0 && args[0] == "test")
196
- test_it()
197
- elsif (args.size == 3 && args[0].to_s.downcase == "-b" && args[1] != nil && args[2] != nil)
198
-
199
- # Batch MODE
200
- # -b record_file favourite_animal_name
201
-
202
- key = getkey()
203
-
204
- text=File.open(args[1]).read
205
- text.gsub!(/\r\n?/, "\n")
206
- text.each_line do |line|
207
-
208
- hostname, account, port = line.split(';')
209
-
210
- port = port.gsub(/\n/,"")
211
-
212
- vals = generate(hostname,account,port,key)
213
-
214
- $animalnames.each.with_index(0) do |animal,i|
215
-
216
- puts "#{hostname}:#{account}:#{port} = #{vals[i]}" if (animal.downcase == args[2].downcase)
217
-
218
- end
219
-
220
-
221
- end
222
-
223
- else
224
-
225
- hostname = ""
226
- account = ""
227
- port = ""
228
-
229
- # Record given parameters to .kyle file at home
230
- kyle_r_path = File.join(Dir.home,".kyle")
231
-
232
- if (args.size > 0 && args[0].to_s.downcase == "-a")
233
- recs = []
234
- iA = 0
235
- File.open(kyle_r_path).each do |line|
236
- recs << line.rstrip!
237
- puts "#{iA} - #{line}"
238
- iA+=1
239
- end
240
-
241
- puts("")
242
- idx = ask("Selection:")
243
-
244
- r = recs[idx.to_i].split(";")
245
-
246
- hostname = r[0]
247
- account = r[1]
248
- port = r[2]
249
-
250
- else
251
- hostname = ask("Hostname:")
252
- account = ask("Account:")
253
- port = ask("Port:")
254
- end
255
- key = getkey()
256
-
257
- if (args.size > 0 && args[0].to_s.downcase == "-r")
258
-
259
-
260
- line_to_add = "#{hostname};#{account};#{port}"
261
-
262
- File.open(kyle_r_path, 'a') do |file|
263
- file.puts line_to_add
264
- end
265
- end
266
-
267
- puts "Calculating..."
268
- vals = generate(hostname,account,port,key)
269
-
270
- $animalnames.each.with_index(0) do |animal,i|
271
-
272
- puts "#{animal}\t#{vals[i]}"
273
-
274
- end
275
- end
116
+ ret[0..15]
276
117
  end
277
118
  end
@@ -0,0 +1,159 @@
1
+ require 'kyle'
2
+
3
+ # Command line access to Kyle
4
+ class KyleCommands
5
+ attr_accessor :args
6
+
7
+ def initialize(args = [])
8
+ @args = args
9
+ end
10
+
11
+ def run
12
+ puts 'Kyle - A password manager for paranoids. ( 0.0.5 )'
13
+ puts ''
14
+
15
+ batch_generate if batch?
16
+ single_generate_choose if single_by_choose?
17
+ single_generate if !batch? && !single_by_choose?
18
+ end
19
+
20
+ def ask_for_key
21
+ return ask('Key:') { |q| q.echo = false } unless check?
22
+
23
+ key = 'a'
24
+ key_check = 'b'
25
+
26
+ while key != key_check
27
+ key = ask('Key:') { |q| q.echo = false }
28
+ key_check = ask('Key (again):') { |q| q.echo = false }
29
+
30
+ puts 'Keys do not match!' unless key == key_check
31
+ end
32
+
33
+ key
34
+ end
35
+
36
+ def batch_generate
37
+ text = File.open(file).read
38
+
39
+ text.gsub!(/\r\n?/, "\n")
40
+
41
+ text.each_line do |line|
42
+ hostname, account, port = line.split(';')
43
+
44
+ port.gsub!(/\n/, '')
45
+
46
+ passwords = make_passwords(hostname, account, port, key)
47
+
48
+ passwords.select { |a, _| animals.include? a }.each do |a, p|
49
+ puts "#{hostname}:#{account}:#{port} (#{a}) = #{p}"
50
+ end
51
+ end
52
+ end
53
+
54
+ def kyle_r_path
55
+ File.join(Dir.home, '.kyle')
56
+ end
57
+
58
+ def record
59
+ line_to_add = "#{hostname};#{account};#{port}"
60
+
61
+ File.open(kyle_r_path, 'a') do |file|
62
+ file.puts line_to_add
63
+ end
64
+ end
65
+
66
+ def saved_records
67
+ recs = []
68
+ i_a = 0
69
+ File.open(kyle_r_path).each do |line|
70
+ recs << line.rstrip!
71
+ puts "#{i_a} - #{line}"
72
+ i_a += 1
73
+ end
74
+
75
+ recs
76
+ end
77
+
78
+ def single_generate_choose
79
+ recs = saved_records
80
+
81
+ puts('')
82
+ idx = ask('Selection:')
83
+
84
+ r = recs[idx.to_i].split(';')
85
+
86
+ @hostname = r[0]
87
+ @account = r[1]
88
+ @port = r[2]
89
+
90
+ single_generate
91
+ end
92
+
93
+ def single_generate
94
+ record if record?
95
+
96
+ passwords = make_passwords(hostname, account, port, key)
97
+
98
+ if animals.length > 1
99
+ Constants::ANIMALS.each { |a| puts "#{a}\t#{passwords[a]}" }
100
+ else
101
+ puts passwords[animals[0]]
102
+ end
103
+ end
104
+
105
+ def record?
106
+ args.include? '-r'
107
+ end
108
+
109
+ def check?
110
+ (args.include? '-c') || (record?)
111
+ end
112
+
113
+ def batch?
114
+ args.include? '-b'
115
+ end
116
+
117
+ def single_by_choose?
118
+ args.include? '-a'
119
+ end
120
+
121
+ def main_args
122
+ args.reject { |arg| arg[0] == '-' }
123
+ end
124
+
125
+ def hostname
126
+ @hostname ||= main_args[0] || ask('Hostname:')
127
+ end
128
+
129
+ def account
130
+ @account ||= main_args[1] || ask('Account:')
131
+ end
132
+
133
+ def port
134
+ @port ||= main_args[2] || ask('Port:')
135
+ end
136
+
137
+ def animals
138
+ animal = batch? ? main_args[1] : main_args[3]
139
+
140
+ return Constants::ANIMALS if animal.nil?
141
+ Constants::ANIMALS.select { |a| a.downcase == animal.downcase }
142
+ end
143
+
144
+ def make_passwords(hostname, account, port, key)
145
+ puts 'Generating...'
146
+ puts ''
147
+
148
+ Kyle.new(hostname, account, port, key).passwords
149
+ end
150
+
151
+ def file
152
+ fail 'File only for batch operations' unless batch?
153
+ main_args[0]
154
+ end
155
+
156
+ def key
157
+ @key ||= ask_for_key
158
+ end
159
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe KyleCommands do
4
+ subject(:cmds) { described_class.new(args) }
5
+
6
+ context 'in batch mode' do
7
+ let(:args) { %w(-b filename.txt whale) }
8
+
9
+ it 'is in batch mode' do
10
+ expect(cmds.batch?).to eq(true)
11
+ end
12
+
13
+ it 'runs #batch_generate' do
14
+ expect(cmds).to receive(:batch_generate)
15
+ cmds.run
16
+ end
17
+ end
18
+
19
+ context 'in single mode' do
20
+ let(:args) { %w(microsoft.com evilcommander 8080 panda) }
21
+
22
+ it 'is in single mode' do
23
+ expect(cmds.batch?).to eq(false)
24
+ end
25
+
26
+ it 'has details set' do
27
+ expect(cmds.hostname).to eq('microsoft.com')
28
+ expect(cmds.account).to eq('evilcommander')
29
+ expect(cmds.port).to eq('8080')
30
+ expect(cmds.animals).to eq(['Panda'])
31
+ end
32
+ end
33
+ end
data/spec/kyle_spec.rb ADDED
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Kyle do
4
+ let!(:passwords) { Kyle.new(hostname, account, port, key).passwords }
5
+
6
+ context "Bill Gates' passwords" do
7
+ let(:hostname) { 'microsoft.com' }
8
+ let(:account) { 'bill.gates' }
9
+ let(:port) { '666' }
10
+ let(:key) { 'iKnowWhatYouDidToIBMLastSummer' }
11
+
12
+ it 'has the correct passwords' do
13
+ expect(passwords).to eq(
14
+ 'Ape' => 'WW0nQIY.0Rn6D8d2',
15
+ 'Bat' => 'nXzU19faM7*gv7,I',
16
+ 'Bear' => 'cgu0q7*DuT65r3rY',
17
+ 'Whale' => 'ILZ,5vZLl/wRxf9y',
18
+ 'Crow' => 'Od..eF2k6_l3XHxe',
19
+ 'Dog' => 'sedWPnJsSb4DEJw-',
20
+ 'Cat' => 'JEr_SzZBoofgI7Tb',
21
+ 'Wasp' => 'xbbg@ebdz3FA.n6S',
22
+ 'Fox' => '5EMS!XZP7WfPLKpO',
23
+ 'Gull' => 'LcwDHUu0/ynzdSWE',
24
+ 'Jackal' => '5+fDOoY.yrE+ESbj',
25
+ 'Lion' => 'VWKqetfVKZtT,FI9',
26
+ 'Panda' => 'EDe7XvMZ%8tt2vsT',
27
+ 'Rat' => 'vks.HPeDVkklS_qb',
28
+ 'Shark' => 'hcVznOxvT5YvxIlU',
29
+ 'Spider' => 'iBTr-I42uz7h7XnA',
30
+ 'Turtle' => 'fLV,g6%@1G7xpQil',
31
+ 'Wolf' => 'toMFvN@Zd,b*KBC%',
32
+ 'Zebra' => 'FYbi/6Udx_4mO3D0'
33
+ )
34
+ end
35
+ end
36
+
37
+ context 'with crazy inputs' do
38
+ let(:hostname) { Constants::PASSWORD_CHARS.join }
39
+ let(:account) { Constants::PASSWORD_CHARS.join }
40
+ let(:port) { Constants::PASSWORD_CHARS.join }
41
+ let(:key) { Constants::PASSWORD_CHARS.join }
42
+
43
+ it 'has correct passwords' do
44
+ expect(passwords).to eq(
45
+ 'Ape' => 'cuoTJm!UuIYCcQxs',
46
+ 'Bat' => '3HrQ3s/j53A+Rssm',
47
+ 'Bear' => 'KK+IV7QE9Imd65hi',
48
+ 'Whale' => 'M@FH%uduAIvn/0Fg',
49
+ 'Crow' => 'C@ffelLPbsh!ps68',
50
+ 'Dog' => 'mF%j06cgTaD63v5C',
51
+ 'Cat' => '5pRiaZDk%SY6quet',
52
+ 'Wasp' => 'd56XIGF8PhHu!TfI',
53
+ 'Fox' => '71UES8Six9G48hsc',
54
+ 'Gull' => 'kmtu%gr1.k%T!tPy',
55
+ 'Jackal' => 'zE8*qE+uU.PsOkYY',
56
+ 'Lion' => '77Rbxcaiwp4Fwm.M',
57
+ 'Panda' => 'qWT0K%tFP8w7_H0S',
58
+ 'Rat' => '2uGyZI.SzAOujmkw',
59
+ 'Shark' => '.QhaGPzV_jnnRj@F',
60
+ 'Spider' => '4FsOh0GfaM4MVUUH',
61
+ 'Turtle' => '_3r0DzAdYvEp@dlA',
62
+ 'Wolf' => 'qcWgE@nt9SgUEsjP',
63
+ 'Zebra' => '8F1BJ.OlV5Kj!wmM'
64
+ )
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,5 @@
1
+ require 'kyle'
2
+ require 'kyle_commands'
3
+
4
+ RSpec.configure do |_|
5
+ end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kyle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Harun Esur
8
+ - Isaac Seymour
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-07-26 00:00:00.000000000 Z
12
+ date: 2014-09-17 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: highline
@@ -30,6 +31,34 @@ dependencies:
30
31
  - - ">="
31
32
  - !ruby/object:Gem::Version
32
33
  version: 1.6.20
34
+ - !ruby/object:Gem::Dependency
35
+ name: rubocop
36
+ requirement: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.26'
41
+ type: :development
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.26'
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ requirement: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.0.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.0
33
62
  description: A password manager for paranoids.
34
63
  email: harun.esur@sceptive.com
35
64
  executables:
@@ -37,8 +66,19 @@ executables:
37
66
  extensions: []
38
67
  extra_rdoc_files: []
39
68
  files:
40
- - lib/kyle.rb
69
+ - ".gitignore"
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - LICENSE
73
+ - README.md
41
74
  - bin/kyle
75
+ - kyle.gemspec
76
+ - lib/constants.rb
77
+ - lib/kyle.rb
78
+ - lib/kyle_commands.rb
79
+ - spec/kyle_commands_spec.rb
80
+ - spec/kyle_spec.rb
81
+ - spec/spec_helper.rb
42
82
  homepage: http://sceptive.com
43
83
  licenses:
44
84
  - MIT