passforge 1.0.0 → 1.1.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 +4 -4
- data/README.md +85 -5
- data/lib/passforge/batch.rb +60 -0
- data/lib/passforge/pattern.rb +54 -0
- data/lib/passforge/pronounceable.rb +70 -0
- data/lib/passforge/version.rb +1 -1
- data/lib/passforge.rb +35 -0
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4a1d4c2fc2135b7b729e8e6768463070cbb6fe4e02c3b45b36bd3ee4f8697ae4
|
|
4
|
+
data.tar.gz: d6acd23b744bcf275093dfec5022451b1c34039e002838e47eb1883310e2201f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f3e7a72036d5607b20306a6067487e606ca47774ee97102a778778f3c08c962dd56c17417bb17b8f188f8689bb468561f5dfa1e6686f19bc8974ad1864db7d08
|
|
7
|
+
data.tar.gz: ebebbb78520b87792020174054e16d376977832d72c18c3d30c3c0f6e320eb09e5f462fc40c0017086d3d64e04dabe07e3fba86b11e6703b0440f596b17889d7
|
data/README.md
CHANGED
|
@@ -13,8 +13,9 @@ PassForge is a feature-rich password generation toolkit that goes beyond simple
|
|
|
13
13
|
- 📝 **Memorable Passphrases** - XKCD-style word-based passwords
|
|
14
14
|
- 🛡️ **Strength Analysis** - Entropy calculation and crack time estimation
|
|
15
15
|
- 🔍 **Breach Checking** - HaveIBeenPwned API integration
|
|
16
|
-
- 🗣️ **Pronounceable Passwords** - Easier to type and remember
|
|
17
|
-
- 🎨 **Pattern-Based Generation** - Custom password patterns
|
|
16
|
+
- 🗣️ **Pronounceable Passwords** - Easier to type and remember
|
|
17
|
+
- 🎨 **Pattern-Based Generation** - Custom password patterns
|
|
18
|
+
- 📦 **Batch Generation** - Generate multiple passwords at once
|
|
18
19
|
|
|
19
20
|
## 📦 Installation
|
|
20
21
|
|
|
@@ -187,13 +188,92 @@ result[:count] # => 0
|
|
|
187
188
|
- Your actual password never leaves your system
|
|
188
189
|
- Powered by HaveIBeenPwned API
|
|
189
190
|
|
|
191
|
+
### Pronounceable Passwords
|
|
192
|
+
|
|
193
|
+
Generate passwords that are easier to type and remember:
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
# Basic pronounceable password
|
|
197
|
+
PassForge.pronounceable
|
|
198
|
+
# => "Fabiroxotu86"
|
|
199
|
+
|
|
200
|
+
# Custom length
|
|
201
|
+
PassForge.pronounceable(length: 16)
|
|
202
|
+
# => "Tuvaxo8qibale9f#"
|
|
203
|
+
|
|
204
|
+
# Without capitalization
|
|
205
|
+
PassForge.pronounceable(capitalize: false)
|
|
206
|
+
# => "fabiroxotu86"
|
|
207
|
+
|
|
208
|
+
# Without numbers
|
|
209
|
+
PassForge.pronounceable(numbers: false)
|
|
210
|
+
# => "Fabiroxotu"
|
|
211
|
+
|
|
212
|
+
# With symbols
|
|
213
|
+
PassForge.pronounceable(symbols: true)
|
|
214
|
+
# => "Fabiroxotu86#"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Pattern-Based Generation
|
|
218
|
+
|
|
219
|
+
Create passwords from custom patterns:
|
|
220
|
+
|
|
221
|
+
```ruby
|
|
222
|
+
# Basic pattern
|
|
223
|
+
PassForge.pattern("Cvccvc99!")
|
|
224
|
+
# => "Piceej98{"
|
|
225
|
+
|
|
226
|
+
# Pattern characters:
|
|
227
|
+
# C = uppercase letter
|
|
228
|
+
# c = lowercase letter
|
|
229
|
+
# v = lowercase vowel
|
|
230
|
+
# V = uppercase vowel
|
|
231
|
+
# 9 = digit
|
|
232
|
+
# ! = symbol
|
|
233
|
+
# Any other = literal
|
|
234
|
+
|
|
235
|
+
# Complex pattern
|
|
236
|
+
PassForge.pattern("CC-vv-99-!!")
|
|
237
|
+
# => "XY-ae-42-@#"
|
|
238
|
+
|
|
239
|
+
# With literal characters
|
|
240
|
+
PassForge.pattern("Pass-Cvcc-9999")
|
|
241
|
+
# => "Pass-Rabi-5678"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Batch Generation
|
|
245
|
+
|
|
246
|
+
Generate multiple passwords at once:
|
|
247
|
+
|
|
248
|
+
```ruby
|
|
249
|
+
# Generate 10 random passwords
|
|
250
|
+
passwords = PassForge.batch(10, :random, length: 16)
|
|
251
|
+
# => ["aB3dE7gH9jK2mN5p", "xY9zA2bC4dE6fG8h", ...]
|
|
252
|
+
|
|
253
|
+
# Generate 5 passphrases
|
|
254
|
+
passwords = PassForge.batch(5, :passphrase, words: 4)
|
|
255
|
+
# => ["Correct-Horse-Battery-Staple", ...]
|
|
256
|
+
|
|
257
|
+
# Generate pronounceable passwords
|
|
258
|
+
passwords = PassForge.batch(10, :pronounceable, length: 12)
|
|
259
|
+
|
|
260
|
+
# Generate from pattern
|
|
261
|
+
passwords = PassForge.batch(10, :pattern, pattern: "Cvccvc99!")
|
|
262
|
+
|
|
263
|
+
# Export to CSV
|
|
264
|
+
csv = PassForge::Batch.to_csv(passwords)
|
|
265
|
+
|
|
266
|
+
# Export to JSON
|
|
267
|
+
json = PassForge::Batch.to_json(passwords)
|
|
268
|
+
```
|
|
269
|
+
|
|
190
270
|
## 🔮 Coming Soon
|
|
191
271
|
|
|
192
272
|
PassForge v1.1+ will include:
|
|
193
273
|
|
|
194
|
-
- **
|
|
195
|
-
- **
|
|
196
|
-
- **
|
|
274
|
+
- **CLI Tool**: Command-line interface for quick password generation
|
|
275
|
+
- **Browser Extension**: Chrome/Firefox extension
|
|
276
|
+
- **Password History**: Save generated passwords locally (encrypted)
|
|
197
277
|
|
|
198
278
|
## 🛠️ Development
|
|
199
279
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module PassForge
|
|
4
|
+
# Batch password generator
|
|
5
|
+
# Generate multiple passwords at once
|
|
6
|
+
class Batch
|
|
7
|
+
# Generate multiple passwords
|
|
8
|
+
#
|
|
9
|
+
# @param count [Integer] Number of passwords to generate
|
|
10
|
+
# @param type [Symbol] Type of password (:random, :passphrase, :pronounceable, :pattern)
|
|
11
|
+
# @param options [Hash] Options for the generator
|
|
12
|
+
# @return [Array<String>] Array of generated passwords
|
|
13
|
+
#
|
|
14
|
+
# @example Generate 10 random passwords
|
|
15
|
+
# PassForge::Batch.generate(10, :random, length: 16)
|
|
16
|
+
# # => ["aB3dE7gH9jK2mN5p", "xY9zA2bC4dE6fG8h", ...]
|
|
17
|
+
#
|
|
18
|
+
def self.generate(count, type = :random, **options)
|
|
19
|
+
raise ArgumentError, "Count must be at least 1" if count < 1
|
|
20
|
+
raise ArgumentError, "Count must be at most 1000" if count > 1000
|
|
21
|
+
|
|
22
|
+
passwords = []
|
|
23
|
+
|
|
24
|
+
count.times do
|
|
25
|
+
password = case type
|
|
26
|
+
when :random
|
|
27
|
+
length = options.delete(:length) || 12
|
|
28
|
+
Generator.generate(length, **options)
|
|
29
|
+
when :passphrase
|
|
30
|
+
Passphrase.generate(**options)
|
|
31
|
+
when :pronounceable
|
|
32
|
+
Pronounceable.generate(**options)
|
|
33
|
+
when :pattern
|
|
34
|
+
Pattern.generate(options[:pattern] || "Cvccvc99!")
|
|
35
|
+
else
|
|
36
|
+
raise ArgumentError, "Unknown type: #{type}"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
passwords << password
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
passwords
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Export passwords to CSV format
|
|
46
|
+
# @param passwords [Array<String>] Passwords to export
|
|
47
|
+
# @return [String] CSV string
|
|
48
|
+
def self.to_csv(passwords)
|
|
49
|
+
"Password\n" + passwords.join("\n")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Export passwords to JSON format
|
|
53
|
+
# @param passwords [Array<String>] Passwords to export
|
|
54
|
+
# @return [String] JSON string
|
|
55
|
+
def self.to_json(passwords)
|
|
56
|
+
require "json"
|
|
57
|
+
{ passwords: passwords, count: passwords.length, generated_at: Time.now.iso8601 }.to_json
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "securerandom"
|
|
4
|
+
|
|
5
|
+
module PassForge
|
|
6
|
+
# Pattern-based password generator
|
|
7
|
+
# Generate passwords based on custom patterns
|
|
8
|
+
class Pattern
|
|
9
|
+
# Generate password from pattern
|
|
10
|
+
#
|
|
11
|
+
# @param pattern [String] Pattern string
|
|
12
|
+
# @return [String] Generated password
|
|
13
|
+
#
|
|
14
|
+
# Pattern characters:
|
|
15
|
+
# - C = uppercase letter
|
|
16
|
+
# - c = lowercase letter
|
|
17
|
+
# - v = lowercase vowel
|
|
18
|
+
# - V = uppercase vowel
|
|
19
|
+
# - 9 = digit
|
|
20
|
+
# - ! = symbol
|
|
21
|
+
# - Any other character = literal
|
|
22
|
+
#
|
|
23
|
+
# @example Generate from pattern
|
|
24
|
+
# PassForge::Pattern.generate("Cvccvc99!")
|
|
25
|
+
# # => "Rabmit42!"
|
|
26
|
+
#
|
|
27
|
+
def self.generate(pattern)
|
|
28
|
+
raise ArgumentError, "Pattern cannot be empty" if pattern.nil? || pattern.empty?
|
|
29
|
+
|
|
30
|
+
result = []
|
|
31
|
+
|
|
32
|
+
pattern.each_char do |char|
|
|
33
|
+
result << case char
|
|
34
|
+
when 'C'
|
|
35
|
+
Charsets::UPPER_CASE.sample
|
|
36
|
+
when 'c'
|
|
37
|
+
Charsets::LOWER_CASE.sample
|
|
38
|
+
when 'v'
|
|
39
|
+
Pronounceable::VOWELS.sample
|
|
40
|
+
when 'V'
|
|
41
|
+
Pronounceable::VOWELS.sample.upcase
|
|
42
|
+
when '9'
|
|
43
|
+
Charsets::NUMBERS.sample
|
|
44
|
+
when '!'
|
|
45
|
+
Charsets::SYMBOLS.sample
|
|
46
|
+
else
|
|
47
|
+
char # Literal character
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
result.join
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "securerandom"
|
|
4
|
+
|
|
5
|
+
module PassForge
|
|
6
|
+
# Pronounceable password generator
|
|
7
|
+
# Creates passwords that are easier to type and remember
|
|
8
|
+
class Pronounceable
|
|
9
|
+
CONSONANTS = %w[b c d f g h j k l m n p r s t v w x z].freeze
|
|
10
|
+
VOWELS = %w[a e i o u].freeze
|
|
11
|
+
|
|
12
|
+
# Generate a pronounceable password
|
|
13
|
+
#
|
|
14
|
+
# @param length [Integer] Length of the password (default: 12)
|
|
15
|
+
# @param capitalize [Boolean] Capitalize first letter (default: true)
|
|
16
|
+
# @param numbers [Boolean] Include numbers (default: true)
|
|
17
|
+
# @param symbols [Boolean] Include symbols (default: false)
|
|
18
|
+
# @return [String] Generated pronounceable password
|
|
19
|
+
#
|
|
20
|
+
# @example Generate a pronounceable password
|
|
21
|
+
# PassForge::Pronounceable.generate(12)
|
|
22
|
+
# # => "Tuvaxo8qiba#"
|
|
23
|
+
#
|
|
24
|
+
def self.generate(length: 12, capitalize: true, numbers: true, symbols: false)
|
|
25
|
+
raise ArgumentError, "Length must be at least 4" if length < 4
|
|
26
|
+
|
|
27
|
+
# Reserve space for numbers and symbols
|
|
28
|
+
letter_count = length
|
|
29
|
+
letter_count -= 2 if numbers
|
|
30
|
+
letter_count -= 1 if symbols
|
|
31
|
+
|
|
32
|
+
# Generate pronounceable base
|
|
33
|
+
password = generate_pronounceable_string(letter_count)
|
|
34
|
+
|
|
35
|
+
# Capitalize first letter
|
|
36
|
+
password[0] = password[0].upcase if capitalize
|
|
37
|
+
|
|
38
|
+
# Add numbers
|
|
39
|
+
if numbers
|
|
40
|
+
2.times { password += SecureRandom.random_number(10).to_s }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Add symbol
|
|
44
|
+
if symbols
|
|
45
|
+
symbol = Charsets::SYMBOLS.sample
|
|
46
|
+
password += symbol
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
password
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Generate pronounceable string by alternating consonants and vowels
|
|
53
|
+
# @private
|
|
54
|
+
def self.generate_pronounceable_string(length)
|
|
55
|
+
result = []
|
|
56
|
+
use_consonant = [true, false].sample
|
|
57
|
+
|
|
58
|
+
length.times do
|
|
59
|
+
if use_consonant
|
|
60
|
+
result << CONSONANTS.sample
|
|
61
|
+
else
|
|
62
|
+
result << VOWELS.sample
|
|
63
|
+
end
|
|
64
|
+
use_consonant = !use_consonant
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
result.join
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
data/lib/passforge/version.rb
CHANGED
data/lib/passforge.rb
CHANGED
|
@@ -7,6 +7,10 @@ require "passforge/generator"
|
|
|
7
7
|
require "passforge/passphrase"
|
|
8
8
|
require "passforge/analyzer"
|
|
9
9
|
require "passforge/breach_checker"
|
|
10
|
+
require "passforge/pronounceable"
|
|
11
|
+
require "passforge/pattern"
|
|
12
|
+
require "passforge/batch"
|
|
13
|
+
require "passforge/personal"
|
|
10
14
|
require "securerandom"
|
|
11
15
|
|
|
12
16
|
# PassForge - A comprehensive password generation toolkit
|
|
@@ -48,4 +52,35 @@ module PassForge
|
|
|
48
52
|
def self.breached?(password)
|
|
49
53
|
BreachChecker.check(password)
|
|
50
54
|
end
|
|
55
|
+
|
|
56
|
+
# Generate a pronounceable password
|
|
57
|
+
# @param options [Hash] Generation options
|
|
58
|
+
# @return [String] Generated password
|
|
59
|
+
def self.pronounceable(**options)
|
|
60
|
+
Pronounceable.generate(**options)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Generate password from pattern
|
|
64
|
+
# @param pattern [String] Pattern string
|
|
65
|
+
# @return [String] Generated password
|
|
66
|
+
def self.pattern(pattern)
|
|
67
|
+
Pattern.generate(pattern)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Generate multiple passwords
|
|
71
|
+
# @param count [Integer] Number of passwords
|
|
72
|
+
# @param type [Symbol] Type of password
|
|
73
|
+
# @param options [Hash] Generation options
|
|
74
|
+
# @return [Array<String>] Generated passwords
|
|
75
|
+
def self.batch(count, type = :random, **options)
|
|
76
|
+
Batch.generate(count, type, **options)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Generate a personalized password
|
|
80
|
+
# @param keywords [Array<String>] Personal keywords
|
|
81
|
+
# @param options [Hash] Generation options
|
|
82
|
+
# @return [String] Generated password
|
|
83
|
+
def self.personal(keywords, **options)
|
|
84
|
+
Personal.generate(keywords, **options)
|
|
85
|
+
end
|
|
51
86
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: passforge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bhavin Nandani
|
|
@@ -127,10 +127,13 @@ files:
|
|
|
127
127
|
- Rakefile
|
|
128
128
|
- lib/passforge.rb
|
|
129
129
|
- lib/passforge/analyzer.rb
|
|
130
|
+
- lib/passforge/batch.rb
|
|
130
131
|
- lib/passforge/breach_checker.rb
|
|
131
132
|
- lib/passforge/charsets.rb
|
|
132
133
|
- lib/passforge/generator.rb
|
|
133
134
|
- lib/passforge/passphrase.rb
|
|
135
|
+
- lib/passforge/pattern.rb
|
|
136
|
+
- lib/passforge/pronounceable.rb
|
|
134
137
|
- lib/passforge/version.rb
|
|
135
138
|
- lib/passforge/wordlist.rb
|
|
136
139
|
- sig/passforge.rbs
|