Skip to content

Commit

Permalink
Added scrypt support and moved to 1.0.1.4
Browse files Browse the repository at this point in the history
  • Loading branch information
Harun Esur committed Nov 3, 2016
1 parent 0720020 commit a8fcd52
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 21 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,19 @@ Application Options:
-c, --complexity=C_LEVEL 0-3 complexity level of password generation. (Default: 0)
-e, --select-credentials Select host and account info from saved list of credentials. If just host or account specified then you get filtered credentials.
-t, --test Runs core tests for the algorithm
-p, --scrypt Use scrypt algorithm to strengthen algorithm
```

## Release notes

- 1.0.1.3 and 1.0.1.4
- Added scrypt support with -p/--scrypt option
- Fixed various parameter parsing bugs

## Algorithm

(Note: After 1.0.1.4 version, SCrypt support added)

Forgiva uses following digest and encryption algorithm to complex password
generation phases:

Expand Down Expand Up @@ -201,11 +210,15 @@ Forgiva uses PBKDF2-HMAC as base of the key-derivation family and uses **forgiva

Depending on choices of the complexity it uses SHA1 (Normal),SHA256 (Intermediate) and SHA512 (Advanced) hashing algorithms.

Note: After 1.0.1.4 Algorithm; SCrypt support added

```
algorithm key-derivation
Input: forgiva-encrypted-inputs as SALT, SHA512 value of master key as KEY
Output: Array of password sized of animal count
hash = KEY
if scrypt_required
hash = scrypt(hash,SALT,131072,8,1) // n = 2^7 , p=8, r=1
for each Animal
hash = PBKDF2_HMAC_SHA1(hash,SALT, 10.000 iterationg with 32 bit key expectation)
password = forgiva-hash-to-password(hash)
Expand Down
4 changes: 3 additions & 1 deletion bin/forgiva
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ BANNER = Constants::COLOR_CYA + "\n .-\" L_ " +

USAGE = <<ENDUSAGE
Usage:
forgiva [-h HOST] [-a ACCOUNT-ID] [-l LENGTH] [-s] [-c [1-3]] [-e] [OPTION...]
forgiva [-h HOST] [-a ACCOUNT-ID] [-l LENGTH] [-s] [-c [1-3]] [-e] [-p] [OPTION...]
ENDUSAGE

HELP = <<ENDHELP
Expand All @@ -32,6 +32,7 @@ Application Options:
\t-c, --complexity=C_LEVEL 0-3 complexity level of password generation. (Default: 0)
\t-e, --select-credentials Select host and account info from saved list of credentials. If just host or account specified then you get filtered credentials.
\t-t, --test Runs core tests for the algorithm
\t-p, --scrypt Use scrypt algorithm to strengthen algorithm
ENDHELP


Expand Down Expand Up @@ -74,6 +75,7 @@ t_hash_args = Hash[ ARGV.join(" ").
gsub("-e","-e 0").
gsub("-t","-t 0").
gsub("-s","-s 0").
gsub("-p","-p 0").
scan(/--?([^=\s]+)(?:[=\s+]?([^-]\S+))?/) ]


Expand Down
6 changes: 4 additions & 2 deletions forgiva.gemspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Gem::Specification.new do |gem|
gem.name = 'forgiva'
gem.version = '1.0.1.2'
gem.date = '2016-07-12'
gem.version = '1.0.1.4'
gem.date = '2016-10-03'

gem.summary = 'Forgiva'
gem.description = 'The new-age password manager.'
Expand All @@ -16,6 +16,8 @@ Gem::Specification.new do |gem|
gem.files = `git ls-files`.split("\n")

gem.add_runtime_dependency 'highline', '~> 1.6', '>= 1.6.20'
gem.add_runtime_dependency 'scrypt'


gem.add_development_dependency 'rubocop', '~> 0.26'
end
10 changes: 8 additions & 2 deletions lib/forgiva.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@
require 'openssl'
require 'highline/import'
require 'constants'
require 'scrypt'

# Password generation from 4 inputs
class Forgiva
attr_accessor :hostname, :account, :renewal_date, :master_password, :complexity, :length
attr_accessor :hostname, :account, :renewal_date, :master_password, :complexity, :length, :use_scrypt

def initialize(hostname, account, renewal_date, master_password, complexity, length)
def initialize(hostname, account, renewal_date, master_password, complexity, length, use_scrypt)
@hostname = hostname
@account = account
@renewal_date = renewal_date
@master_password = master_password
@complexity = complexity
@length = length
@use_scrypt = use_scrypt
end

def passwords
Expand Down Expand Up @@ -43,6 +45,10 @@ def generate

puts "ENC KEY: #{key.unpack('H*')}" if Constants::DEBUG_OUTPUT

if (@use_scrypt) then
key = SCrypt::Engine.scrypt(key,salt,131072,8,1,32)
end


Constants::ANIMALS.each do |a|
# For every other animal we re-run pbkdf2 hmac with sha1 over key
Expand Down
11 changes: 8 additions & 3 deletions lib/forgiva_commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,14 @@ def single_generate
init_length
init_master_password
init_complexity
init_scrypt

puts Constants::COLOR_GRN + "Generating..." + Constants::COLOR_RST
puts ""

record if record?

passwords = make_passwords(@hostname, @account, @renewal_date, @master_password, @complexity, @length)
passwords = make_passwords(@hostname, @account, @renewal_date, @master_password, @complexity, @length, @use_scrypt)

if animals.length > 1
Constants::ANIMALS.each { |a| puts "#{Constants::COLOR_YEL}#{a}#{Constants::COLOR_RST}\t#{Constants::COLOR_BRI}#{passwords[a]}#{Constants::COLOR_RST}" }
Expand All @@ -114,6 +115,10 @@ def single_by_choose?
hash_args.key?('e') || hash_args.key?('select-credentials')
end

def init_scrypt
@use_scrypt = (hash_args['p'] != nil || hash_args['scrypt'] != nil)
end

def init_length
@length = 16
@length = hash_args['l'].to_i if hash_args['l'] != nil
Expand Down Expand Up @@ -178,8 +183,8 @@ def animals

end

def make_passwords(hostname, account, renewal_date, master_password, complexity,length)
Forgiva.new(hostname, account, renewal_date, master_password,complexity,length).passwords
def make_passwords(hostname, account, renewal_date, master_password, complexity,length,use_scrypt)
Forgiva.new(hostname, account, renewal_date, master_password,complexity,length,use_scrypt).passwords
end


Expand Down
16 changes: 12 additions & 4 deletions lib/forgiva_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,13 @@ def self.run_tests

TestVectors::FG_TESTS.each do |test_vec|

for i in 0..1 do
puts "#{Constants::COLOR_GRN} Testing forgiva #{Constants::COLOR_BLU} #{test_vec[:host]} " \
<<"/ #{test_vec[:account]} / #{test_vec[:renewal_date]} / #{Constants::COLOR_MGN} #{test_vec[:animal_name]} #{Constants::COLOR_GRN} " \
<<" on complexity #{test_vec[:complexity]} #{Constants::COLOR_RST}"
<<" on complexity #{test_vec[:complexity]} #{Constants::COLOR_RST}" \
<<"#{Constants::COLOR_YEL}" \
<< (i == 1 ? "+SCRYPT" : "") \
<< "#{Constants::COLOR_RST}"
p_hash = OpenSSL::Digest.digest("sha512",test_vec[:master_key])
Expand All @@ -45,16 +49,20 @@ def self.run_tests
test_vec[:renewal_date],
p_hash,
test_vec[:complexity],
16).passwords
16,
i == 1
).passwords
g_pass = passes[test_vec[:animal_name]].unpack('H*')[0]
expected = (i == 0 ? test_vec[:expected_password_hash] : test_vec[:expected_password_hash_scrypt])
if (g_pass.downcase != test_vec[:expected_password_hash]) then
puts "#{Constants::COLOR_RED} FAILED: (Expected: #{test_vec[:expected_password_hash]}) #{Constants::COLOR_RST} #{g_pass}"
if (g_pass.downcase != expected) then
puts "#{Constants::COLOR_RED} FAILED: (Expected: #{expected}) #{Constants::COLOR_RST} #{g_pass}"
else
puts "#{Constants::COLOR_GRN}! SUCCESS: (#{g_pass}) #{Constants::COLOR_RST}"
end
end
end
Expand Down
35 changes: 26 additions & 9 deletions lib/testvectors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ module TestVectors
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_SIMPLE,
:animal_name => "Ape",
:expected_password_hash => "797036592a475f78444c6153504d3757"},
:expected_password_hash => "797036592a475f78444c6153504d3757",
:expected_password_hash_scrypt => "466b74674d645a4d6939302a6e56797a"
},

## facebook.com - root
{:host => "facebook.com",
Expand All @@ -18,7 +20,8 @@ module TestVectors
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_INTERMEDIATE,
:animal_name => "Bat",
:expected_password_hash => "5544245f2b72682e4635765040416a49"
:expected_password_hash => "5544245f2b72682e4635765040416a49",
:expected_password_hash_scrypt => "354b223d3b6c246733386c2d6674283d"

},

Expand All @@ -29,7 +32,8 @@ module TestVectors
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_ADVANCED,
:animal_name => "Bear",
:expected_password_hash => "4f5c7653513251417a675949284c5539"
:expected_password_hash => "4f5c7653513251417a675949284c5539",
:expected_password_hash_scrypt => "587a796a7c40267426637b694d345459"

},

Expand All @@ -40,8 +44,11 @@ module TestVectors
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_SIMPLE,
:animal_name => "Whale",
:expected_password_hash => "6465635a675374322f47695051464157"
:expected_password_hash => "6465635a675374322f47695051464157",
:expected_password_hash_scrypt => "496375392e63486a59434473334d6169"
},



## microsoft.com - toor
{:host => "microsoft.com",
Expand All @@ -50,38 +57,47 @@ module TestVectors
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_INTERMEDIATE,
:animal_name => "Crow",
:expected_password_hash => "4d314573586d403649672970786d7133"
:expected_password_hash => "4d314573586d403649672970786d7133",
:expected_password_hash_scrypt => "3e51542a4d364d31657673467c6d4728"
},


## 192.168.0.1 - root
{:host => "192.168.0.1",
:account => "root",
:renewal_date => "1970-01-01",
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_ADVANCED,
:animal_name => "Dog",
:expected_password_hash => "2c376d234a7a6c4d6f785c34494a672a"
:expected_password_hash => "2c376d234a7a6c4d6f785c34494a672a",
:expected_password_hash_scrypt => "4939c2a232217c5c405a6c714e76552566"
},



## 10.0.0.2:22 - root
{:host => "10.0.0.2:22",
:account => "root",
:renewal_date => "1970-01-01",
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_SIMPLE,
:animal_name => "Duck",
:expected_password_hash => "6440562a36375065693646396e312c4b"
:expected_password_hash => "6440562a36375065693646396e312c4b",
:expected_password_hash_scrypt => "345057425a5133756c5965745f7a7054"

},



## 10.0.0.2:22 - k3ym4k3r
{:host => "10.0.0.2:22",
:account => "k3ym4k3r",
:renewal_date => "1970-01-01",
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_INTERMEDIATE,
:animal_name => "Cat",
:expected_password_hash => "78435f57566e2f53535f2e617738293b"
:expected_password_hash => "78435f57566e2f53535f2e617738293b",
:expected_password_hash_scrypt => "5c624f23723e704673452530773e3144"

},

Expand All @@ -92,7 +108,8 @@ module TestVectors
:master_key => "forgiva_rockz_all_the_fuck1ng_t1m3",
:complexity => Constants::FORGIVA_PG_ADVANCED,
:animal_name => "Wasp",
:expected_password_hash => "54534a582b265f337e2e43403b536861"
:expected_password_hash => "54534a582b265f337e2e43403b536861",
:expected_password_hash_scrypt => "332b2541364e306537704e4551763938"
}].freeze

FA_TESTS = [{:is_encryption_algorithm => true,
Expand Down

0 comments on commit a8fcd52

Please sign in to comment.