c7decrypt 0.2.0 → 0.2.1

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.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /coverage
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format documentation
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - 1.9.2
6
+ - jruby-18mode
7
+ - jruby-19mode
8
+ - rbx-18mode
9
+ - rbx-19mode
10
+ - ruby-head
11
+ - jruby-head
12
+ - 1.8.7
13
+ - ree
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,47 @@
1
+ # Contributing to C7Decrypt
2
+
3
+ Thanks for your interest in contributing to C7Decrypt.
4
+
5
+ If you could follow the following guidelines, you will make it much easier for
6
+ us to give feedback, help you find whatever problem you have and fix it.
7
+
8
+ ## Issues
9
+
10
+ If you have questions of any kind, or are unsure of how something works, please
11
+ [create an issue](https://github.com/claudijd/c7decrypt/issues/new).
12
+
13
+ Please try to answer the following questions in your issue:
14
+
15
+ - What did you do?
16
+ - What did you expect to happen?
17
+ - What happened instead?
18
+
19
+ If you have identified a bug, it would be very helpful if you could include a
20
+ way to replicate the bug. Ideally a failing test would be perfect, but even a
21
+ simple script demonstrating the error would suffice.
22
+
23
+ Feature requests are great and if submitted they will be considered for
24
+ inclusion, but sending a pull request is much more awesome.
25
+
26
+ ## Pull Requests
27
+
28
+ If you want your pull requests to be accepted, please follow the following guidelines:
29
+
30
+ - [**Add tests!**](http://rspec.info/) Your patch won't be accepted (or will be delayed) if it doesn't have tests.
31
+
32
+ - [**Document any change in behaviour**](http://yardoc.org/) Make sure the README and any other
33
+ relevant documentation are kept up-to-date.
34
+
35
+ - [**Create topic branches**](https://github.com/dchelimsky/rspec/wiki/Topic-Branches) Don't ask us to pull from your master branch.
36
+
37
+ - [**One pull request per feature**](https://help.github.com/articles/using-pull-requests) If you want to do more than one thing, send
38
+ multiple pull requests.
39
+
40
+ - [**Send coherent history**](http://stackoverflow.com/questions/6934752/git-combining-multiple-commits-before-pushing) Make sure each individual commit in your pull
41
+ request is meaningful. If you had to make multiple intermediate commits while
42
+ developing, please squash them before sending them to us.
43
+
44
+ - [**Follow coding conventions**](https://github.com/styleguide/ruby) The standard Ruby stuff, two spaces indent,
45
+ don't omit parens unless you have a good reason.
46
+
47
+ Thank you so much for contributing!
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "rspec"
4
+ gem "rake"
5
+ gem 'simplecov', :require => false, :group => :test
6
+
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (c) 2012, Jonathan Claudius
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+ * Neither the name of Jonathan Claudius nor the
13
+ names of its contributors may be used to endorse or promote products
14
+ derived from this software without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY JONTHAN CLAUDIUS ''AS IS'' AND ANY
17
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL JONATHAN CLAUDIUS BE LIABLE FOR ANY
20
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,114 @@
1
+ ![Cisco Logo](https://github.com/claudijd/c7decrypt/blob/master/images/cisco.jpeg?raw=true)
2
+
3
+ # C7Decrypt
4
+
5
+ [![Build Status](https://secure.travis-ci.org/claudijd/c7decrypt.png)](http://travis-ci.org/claudijd/c7decrypt)
6
+ [![Dependency Status](https://gemnasium.com/claudijd/c7decrypt.png)](https://gemnasium.com/claudijd/c7decrypt)
7
+ [![Code Climate](https://codeclimate.com/github/claudijd/c7decrypt.png)](https://codeclimate.com/github/claudijd/c7decrypt)
8
+
9
+ A Ruby-based implementation of a Cisco Type-7 Password Encryptor/Decryptor
10
+
11
+ ## Key Benefits
12
+
13
+ - **Written in Ruby** - First and only Cisco Type-7 implementation in Ruby that I know of.
14
+ - **Minimal/No Dependancies** - Uses native Ruby to do it's work, no heavy dependancies.
15
+ - **Not Just a Script** - Implementation is portable for use in another project or for automation of tasks.
16
+ - **Simple** - It is a small project so the interfaces are simple and easy to use.
17
+ - **Encrypt & Decrypt** - Supports both encryption (with seed control) and decryption operations.
18
+
19
+ ## Setup
20
+
21
+ To install, type
22
+
23
+ ```bash
24
+ gem install c7decrypt
25
+ ```
26
+
27
+ To use, just require
28
+
29
+ ```ruby
30
+ require 'c7decrypt'
31
+ ```
32
+
33
+ ## Example Usage(s)
34
+
35
+ Decrypt A Single Encrypted Password
36
+
37
+ ```ruby
38
+ >> C7Decrypt.decrypt("060506324F41")
39
+ => "cisco"
40
+ ```
41
+
42
+ Decrypt Array of Encrypted Passwords
43
+
44
+ ```ruby
45
+ >> encrypted_hashes = ["060506324F41", "0822455D0A16"]
46
+ => ["060506324F41", "0822455D0A16"]
47
+ >> C7Decrypt.decrypt_array(encrypted_hashes)
48
+ => ["cisco", "cisco"]
49
+ ```
50
+
51
+ Decrypt Encrypted Passwords from Config
52
+
53
+ ```ruby
54
+ >> C7Decrypt.decrypt_config("cisco_config.txt")
55
+ => ["cisco", "Password1", "admin"]
56
+ ```
57
+
58
+ Encrypt A Single Plaintext Password
59
+
60
+ ```ruby
61
+ >> C7Decrypt.encrypt("cisco")
62
+ => "02050D480809"
63
+ ```
64
+
65
+ Encrypt A Single Plaintext Password w/ Explicit Seed
66
+
67
+ ```ruby
68
+ >> C7Decrypt.encrypt("cisco", 6)
69
+ => "060506324F41"
70
+ ```
71
+
72
+ Encrypt An Array of Plaintext Passwords
73
+
74
+ ```ruby
75
+ >> passwords = ["cisco", "password"]
76
+ => ["cisco", "password"]
77
+ >> C7Decrypt.encrypt_array(passwords)
78
+ => ["02050D480809", "021605481811003348"]
79
+ ```
80
+
81
+ ## Rubies Supported
82
+
83
+ This project is integrated with [travis-ci](http://about.travis-ci.org/) and is regularly tested to work with the following rubies:
84
+
85
+ * [2.0.0](https://github.com/ruby/ruby/tree/ruby_2_0_0)
86
+ * [1.9.3](https://github.com/ruby/ruby/tree/ruby_1_9_3)
87
+ * [1.9.2](https://github.com/ruby/ruby/tree/ruby_1_9_2)
88
+ * 1.9.1 - Tested outside of Travis-CI
89
+ * [1.8.7](https://github.com/ruby/ruby/tree/ruby_1_8_7)
90
+ * 1.8.6 - Tested outside of Travis-CI
91
+ * [ruby-head](https://github.com/ruby/ruby)
92
+ * [jruby-head](http://jruby.org/)
93
+ * [jruby-19mode](http://jruby.org/)
94
+ * [jruby-18mode](http://jruby.org/)
95
+ * [rbx-19mode](http://rubini.us/)
96
+ * [rbx-18mode](http://rubini.us/)
97
+ * [ree](http://www.rubyenterpriseedition.com/)
98
+
99
+ To checkout the current build status for these rubies, click [here](https://travis-ci.org/#!/claudijd/c7decrypt).
100
+
101
+ ## Contributing
102
+
103
+ If you are interested in contributing to this project, please see [CONTRIBUTING.md](https://github.com/claudijd/c7decrypt/blob/master/CONTRIBUTING.md)
104
+
105
+ ## Credits
106
+
107
+ **Sources of Inspiration for C7Decrypt**
108
+
109
+ - [**Daren Matthew**](http://mccltd.net/blog/?p=1034) - For his blog post on the subject aggregating tools and sources that perform the decryption/decoding logic.
110
+ - [**m00nie**](http://www.m00nie.com/2011/09/cisco-type-7-password-decryption-and-encryption-with-perl/) - For the blog post on the subject, the source code of type7tool.pl and it's encryption techniques.
111
+
112
+ **Application(s) that use C7Decrypt**
113
+
114
+ - [**Marcus J Carey**](https://www.threatagent.com/c7) - For his web application implementation of this on the ThreatAgent website. Check it out and start decrypting Cisco type-7 passwords right now.
data/Rakefile ADDED
@@ -0,0 +1,57 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'rubygems'
3
+ require 'rake'
4
+ require 'rubygems/package_task'
5
+ require 'rspec'
6
+ require 'rspec/core'
7
+ require 'rspec/core/rake_task'
8
+
9
+ $:.unshift File.join(File.dirname(__FILE__), "lib")
10
+
11
+ require 'c7decrypt'
12
+
13
+ task :default => :spec
14
+
15
+ desc "Run all specs in spec directory"
16
+ RSpec::Core::RakeTask.new(:spec)
17
+
18
+ def clean_up
19
+ Dir.glob("*.gem").each { |f| File.unlink(f) }
20
+ Dir.glob("*.lock").each { |f| File.unlink(f) }
21
+ end
22
+
23
+ desc "Build the gem"
24
+ task :build do
25
+ puts "[+] Building C7Decrypt version #{C7Decrypt::VERSION}"
26
+ puts `gem build c7decrypt.gemspec`
27
+ end
28
+
29
+ desc "Publish the gem"
30
+ task :publish do
31
+ puts "[+] Publishing C7Decrypt version #{C7Decrypt::VERSION}"
32
+ Dir.glob("*.gem").each { |f| puts `gem push #{f}`}
33
+ end
34
+
35
+ desc "Tag the release"
36
+ task :tag do
37
+ puts "[+] Tagging C7Decrypt version #{C7Decrypt::VERSION}"
38
+ `git tag #{C7Decrypt::VERSION}`
39
+ `git push --tags`
40
+ end
41
+
42
+ desc "Bump the Gemspec Version"
43
+ task :bump do
44
+ puts "[+] Bumping C7Decrypt version #{C7Decrypt::VERSION}"
45
+ `git commit -a -m "Bumped Gem version to #{C7Decrypt::VERSION}"`
46
+ `git push origin master`
47
+ end
48
+
49
+ desc "Perform an end-to-end release of the gem"
50
+ task :release do
51
+ clean_up() # Clean up before we start
52
+ Rake::Task[:build].execute
53
+ Rake::Task[:bump].execute
54
+ Rake::Task[:tag].execute
55
+ Rake::Task[:publish].execute
56
+ clean_up() # Clean up after we complete
57
+ end
data/c7decrypt.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ $: << "lib"
2
+ require 'c7decrypt/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = 'c7decrypt'
6
+ s.version = C7Decrypt::VERSION
7
+ s.authors = ["Jonathan Claudius"]
8
+ s.date = Date.today.to_s
9
+ s.email = 'claudijd@yahoo.com'
10
+ s.platform = Gem::Platform::RUBY
11
+ s.files = Dir.glob("lib/**/*") +
12
+ Dir.glob("spec/**/*") +
13
+ Dir.glob("examples/**/*") +
14
+ [".gitignore",
15
+ ".rspec",
16
+ ".travis.yml",
17
+ "CONTRIBUTING.md",
18
+ "Gemfile",
19
+ "LICENSE",
20
+ "README.md",
21
+ "Rakefile",
22
+ "c7decrypt.gemspec"]
23
+ s.require_paths = ["lib"]
24
+ s.summary = 'Ruby based Cisco Type 7 Password Decryptor'
25
+ s.description = 'A library for decoding Cisco Type 7 passwords'
26
+ s.homepage = 'http://rubygems.org/gems/c7decrypt'
27
+ end
@@ -0,0 +1,39 @@
1
+ require '../lib/c7decrypt'
2
+ require 'optparse'
3
+ require 'ostruct'
4
+
5
+ options = OpenStruct.new
6
+ options.string = nil
7
+ options.file = nil
8
+
9
+ OptionParser.new do |opts|
10
+ opts.banner = "Usage: cdecrypt.rb [options] [hash/file]"
11
+
12
+ opts.on("-s", "--string [HASH]", "A single encrypted hash string") do |v|
13
+ options.string = v
14
+ end
15
+
16
+ opts.on("-f", "--file [FILE]", "A file containing multiple hashes") do |v|
17
+ options.file = v
18
+ end
19
+
20
+ opts.on_tail("-h", "--help", "Show this message") do
21
+ puts ""
22
+ puts opts
23
+ puts ""
24
+ puts "Example: ruby cdecrypt.rb -s 04480E051A33490E"
25
+ puts "Example: ruby cdecrypt.rb -f ../spec/example_configs/simple_canned_example.txt"
26
+ puts ""
27
+ exit
28
+ end
29
+ end.parse!
30
+
31
+ if options.string
32
+ puts C7Decrypt.decrypt(options.string)
33
+ end
34
+
35
+ if options.file &&
36
+ File.exists?(options.file)
37
+
38
+ C7Decrypt.decrypt_config(options.file).each {|pw| puts pw }
39
+ end
@@ -0,0 +1,192 @@
1
+ module C7Decrypt
2
+ module Constants
3
+ # Vigenere translation table (these are our key values for decryption)
4
+ VT_TABLE = [
5
+ 0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f, 0x41, 0x2c, 0x2e,
6
+ 0x69, 0x79, 0x65, 0x77, 0x72, 0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44,
7
+ 0x48, 0x53, 0x55, 0x42, 0x73, 0x67, 0x76, 0x63, 0x61, 0x36, 0x39,
8
+ 0x38, 0x33, 0x34, 0x6e, 0x63, 0x78, 0x76, 0x39, 0x38, 0x37, 0x33,
9
+ 0x32, 0x35, 0x34, 0x6b, 0x3b, 0x66, 0x67, 0x38, 0x37
10
+ ]
11
+
12
+ # Regexes for extracting hashes from configs
13
+ TYPE_7_REGEXES = [
14
+ /enable password 7 ([A-Z0-9]+)/,
15
+ /username [A-Z0-9]+ password 7 ([A-Z0-9]+)/,
16
+ /password 7 ([A-Z0-9]+)/
17
+ ]
18
+ end
19
+
20
+ class InvalidFirstCharacter < StandardError
21
+ end
22
+
23
+ class InvalidCharacter < StandardError
24
+ end
25
+
26
+ class OddNumberOfCharacters < StandardError
27
+ end
28
+
29
+ class InvalidEncryptionSeed < StandardError
30
+ end
31
+
32
+ # The Decryption Method for Cisco Type-7 Encrypted Strings
33
+ # @param [String] the Cisco Type-7 Encrypted String
34
+ # @raise [InvalidFirstCharacter,
35
+ # InvalidCharacter,
36
+ # OddNumberOfCharacters]
37
+ # @return [String] the Decrypted String
38
+ def self.decrypt(e_text)
39
+ check_type_7_errors(e_text)
40
+
41
+ d_text = ""
42
+ seed = nil
43
+
44
+ e_text.scan(/../).each_with_index do |char,i|
45
+ if i == 0
46
+ seed = char.to_i - 1
47
+ else
48
+ d_text += decrypt_char(char, i, seed)
49
+ end
50
+ end
51
+
52
+ return d_text
53
+ end
54
+
55
+ # The Encryption Method for Cisco Type-7 Encrypted Strings
56
+ # @param [String] the plaintext password
57
+ # @param [String] the seed for the encryption used
58
+ # @raise [InvalidEncryptionSeed,
59
+ # InvalidFirstCharacter,
60
+ # InvalidCharacter,
61
+ # OddNumberOfCharacters]
62
+ # @return [String] the encrypted password
63
+ def self.encrypt(d_text, seed = 2)
64
+ check_seed(seed)
65
+
66
+ e_text = sprintf("%02d", seed)
67
+
68
+ d_text.each_char.each_with_index do |d_char,i|
69
+ e_text += encrypt_char(d_char, i, seed)
70
+ end
71
+
72
+ check_type_7_errors(e_text)
73
+
74
+ return e_text
75
+ end
76
+
77
+ # The method for encrypting a single character
78
+ # @param [String] the plain text char
79
+ # @param [FixNum] the index of the char in plaintext string
80
+ # @param [FixNum] the seed used in the encryption process
81
+ # @return [String] the string of the encrypted char
82
+ def self.encrypt_char(char, i, seed)
83
+ sprintf("%02X", char.unpack('C')[0] ^ Constants::VT_TABLE[(i + seed) % 53])
84
+ end
85
+
86
+ # The method for decrypting a single character
87
+ # @param [String] the encrypted char
88
+ # @param [Integer] the index of the char pair in encrypted string
89
+ # @param [Integer] the seed used in the decryption process
90
+ # @return [String] the string of the decrypted char
91
+ def self.decrypt_char(char, i, seed)
92
+ (char.hex^Constants::VT_TABLE[(i + seed) % 53]).chr
93
+ end
94
+
95
+ # A helper method to decrypt an arracy of Cisco Type-7 Encrypted Strings
96
+ # @param [Array>String] an array of Cisco Type-7 Encrypted Strings
97
+ # @raise [InvalidFirstCharacter,
98
+ # InvalidCharacter,
99
+ # OddNumberOfCharacters]
100
+ # @return [Array>String] an array of Decrypted Strings
101
+ def self.decrypt_array(pw_array)
102
+ pw_array.collect {|pw| decrypt(pw)}
103
+ end
104
+
105
+ # A helper method to encrypt an arracy of passwords
106
+ # @param [Array>String] an array of plain-text passwords
107
+ # @raise [InvalidEncryptionSeed,
108
+ # InvalidFirstCharacter,
109
+ # InvalidCharacter,
110
+ # OddNumberOfCharacters]
111
+ # @return [Array>String] an array of encrypted passwords
112
+ def self.encrypt_array(pt_array, seed = 2)
113
+ pt_array.collect {|pw| encrypt(pw, seed)}
114
+ end
115
+
116
+ # This method scans a raw config file for type 7 passwords and
117
+ # decrypts them
118
+ # @param [String] a string of the config file path that contains
119
+ # Cisco Type-7 Encrypted Strings
120
+ # @raise [InvalidFirstCharacter,
121
+ # InvalidCharacter,
122
+ # OddNumberOfCharacters]
123
+ # @return [Array>String] an array of Decrypted Strings
124
+ def self.decrypt_config(file)
125
+ f = File.open(file, 'r').to_a
126
+ decrypt_array(f.collect {|line| type_7_matches(line)}.flatten)
127
+ end
128
+
129
+ # This method scans a config line for encrypted type-7 passwords and
130
+ # returns an array of results
131
+ # @param [String] a line with potential encrypted type-7 passwords
132
+ # @return [Array>String] an array of Cisco type-7 encrypted Strings
133
+ def self.type_7_matches(string)
134
+ Constants::TYPE_7_REGEXES.collect {|regex| string.scan(regex)}.flatten.uniq
135
+ end
136
+
137
+ # This method determines if an encrypted hash is corrupted/invalid
138
+ # and throw a specific exeception
139
+ # @param [String] the Cisco Type-7 Encrypted String
140
+ # @raise [InvalidFirstCharacter, InvalidCharacter, OddNumberOfCharacters]
141
+ # @return [Nil]
142
+ def self.check_type_7_errors(e_text)
143
+
144
+ valid_first_chars = (0..15).to_a.collect {|c| sprintf("%02d", c)}
145
+ first_char = e_text[0,2]
146
+
147
+ # Check for an invalid first character in the has
148
+ unless valid_first_chars.include? first_char
149
+ raise InvalidFirstCharacter,
150
+ "'#{e_text}' hash contains an invalid first chracter (only '00' - '15' allowed)"
151
+ end
152
+
153
+ # Check for an invalid character in the hash
154
+ unless e_text.match(/^[A-Z0-9]+$/)
155
+ raise InvalidCharacter,
156
+ "'#{e_text}' hash contains an invalid character (only upper-alpha numeric allowed)"
157
+ end
158
+
159
+ # Check for an odd number of characters in the hash
160
+ unless e_text.size % 2 == 0
161
+ raise OddNumberOfCharacters,
162
+ "'#{e_text}' hash contains odd length of chars (only even number of chars allowed)"
163
+ end
164
+
165
+ return nil
166
+
167
+ end
168
+
169
+ # This method determines if an encryption seed is valid or not
170
+ # and throw a specific exeception
171
+ # @param [FixNum] the seed used in the encryption process
172
+ # @raise [InvalidEncryptionSeed]
173
+ # @return [Nil]
174
+ def self.check_seed(seed)
175
+ if seed < 0 ||
176
+ seed > 15
177
+
178
+ raise InvalidEncryptionSeed,
179
+ "'#{seed.to_s}' seed is not a valid seed (only 0 - 15 allowed)"
180
+ end
181
+
182
+ return nil
183
+ end
184
+
185
+ #Definition of short-hand methods for the lazy
186
+ #alias :d :decrypt
187
+ #alias :e :encrypt
188
+ #alias :d_a :decrypt_array
189
+ #alias :e_a :encrypt_array
190
+ #alias :d_c :decrypt_config
191
+
192
+ end
@@ -0,0 +1,3 @@
1
+ module C7Decrypt
2
+ VERSION = '0.2.1'
3
+ end
@@ -0,0 +1,233 @@
1
+ require 'spec_helper'
2
+ require 'c7decrypt'
3
+
4
+ describe C7Decrypt do
5
+
6
+ before(:each) do
7
+ @known_values = [
8
+ {:pt => "cisco", :seed => 2, :ph => "02050D480809"},
9
+ {:pt => "cisco", :seed => 3, :ph => "030752180500"},
10
+ {:pt => "cisco", :seed => 4, :ph => "045802150C2E"},
11
+ {:pt => "cisco", :seed => 5, :ph => "05080F1C2243"},
12
+ {:pt => "cisco", :seed => 6, :ph => "060506324F41"},
13
+ {:pt => "cisco", :seed => 7, :ph => "070C285F4D06"},
14
+ {:pt => "cisco", :seed => 8, :ph => "0822455D0A16"},
15
+ {:pt => "cisco", :seed => 9, :ph => "094F471A1A0A"},
16
+ {:pt => "password", :seed => 9, :ph => "095C4F1A0A1218000F"},
17
+ {:pt => "password", :seed => 4, :ph => "044B0A151C36435C0D"}
18
+ ]
19
+ end
20
+
21
+ context "when decrypting single Cisco Type-7 hash using longhand" do
22
+ before(:each) do
23
+ @encrypted_hash = "060506324F41"
24
+ @decrypted_hash = C7Decrypt.decrypt(@encrypted_hash)
25
+ end
26
+
27
+ subject{@decrypted_hash}
28
+ its(:class) {should == ::String}
29
+ it {should == "cisco"}
30
+ end
31
+
32
+ context "when decrypting an array of Cisco Type-7 hashes" do
33
+ before(:each) do
34
+ @encrypted_hashes = [
35
+ "060506324F41",
36
+ "0822455D0A16"
37
+ ]
38
+ @decrypted_hashes = C7Decrypt.decrypt_array(@encrypted_hashes)
39
+ end
40
+
41
+ subject{@decrypted_hashes}
42
+ its(:class) {should == ::Array}
43
+ its(:first) {should == "cisco"}
44
+ its(:last) {should == "cisco"}
45
+ its(:size) {should == 2}
46
+ end
47
+
48
+ context "when decrypting Cisco Type-7 hashes from a config" do
49
+ before(:each) do
50
+ @config_file = "./spec/example_configs/simple_canned_example.txt"
51
+ @decrypted_hashes = C7Decrypt.decrypt_config(@config_file)
52
+ end
53
+
54
+ subject{@decrypted_hashes}
55
+ its(:class) {should == ::Array}
56
+ its(:size) {should == 5}
57
+ it {should == [
58
+ "cisco",
59
+ "cisco",
60
+ "cisco",
61
+ "cisco",
62
+ "cisco"
63
+ ]}
64
+ end
65
+
66
+ context "when decrypting known Cisco Type-7 known value matches" do
67
+ before(:each) do
68
+ @decrypted_hashes = C7Decrypt.decrypt_array(
69
+ @known_values.map {|known_value| known_value[:ph]}
70
+ )
71
+ end
72
+
73
+ subject{@decrypted_hashes}
74
+ its(:class) {should == ::Array}
75
+ its(:size) {should == @known_values.size}
76
+ it {should == @known_values.map {|known_value| known_value[:pt]}}
77
+ end
78
+
79
+ context "when decrypting Cisco Type-7 with a seed greater than 9" do
80
+ before(:each) do
81
+ @decrypt_hash = C7Decrypt.decrypt("15000E010723382727")
82
+ end
83
+
84
+ subject{@decrypt_hash}
85
+ its(:class) {should == ::String}
86
+ it {should == "remcisco"}
87
+ end
88
+
89
+ context "when matchings known Cisco Type-7 known config line matches" do
90
+ before(:each) do
91
+ @encrypted_hashes = []
92
+ @known_config_lines = {
93
+ "username test password 7 0822455D0A16" => "0822455D0A16",
94
+ "enable password 7 060506324F41" => "060506324F41",
95
+ "password 7 02050D480809" => "02050D480809"
96
+ }
97
+
98
+ @known_config_lines.keys.each do |k,v|
99
+ @encrypted_hashes << C7Decrypt.type_7_matches(k)
100
+ end
101
+ @encrypted_hashes.flatten!
102
+ end
103
+
104
+ subject{@encrypted_hashes}
105
+ its(:class) {should == ::Array}
106
+ its(:size) {should == @known_config_lines.size}
107
+ it {should == @known_config_lines.values}
108
+ end
109
+
110
+ context "when encrypting single Cisco Type-7 hash" do
111
+ before(:each) do
112
+ @plaintext_hash = "cisco"
113
+ @encrypted_hash = C7Decrypt.encrypt(@plaintext_hash)
114
+ end
115
+
116
+ subject{@encrypted_hash}
117
+ its(:class) {should == ::String}
118
+ it {should == "02050D480809"}
119
+ end
120
+
121
+ context "when encrypting single Cisco Type-7 hash with an alternate seed value" do
122
+ before(:each) do
123
+ @plaintext_hash = "cisco"
124
+ @seed = 3
125
+ @encrypted_hash = C7Decrypt.encrypt(@plaintext_hash, @seed)
126
+ end
127
+
128
+ subject{@encrypted_hash}
129
+ its(:class) {should == ::String}
130
+ it {should == "030752180500"}
131
+
132
+ it "should decrypt back to the original plaintext hash" do
133
+ C7Decrypt.decrypt(@encrypted_hash).should == @plaintext_hash
134
+ end
135
+ end
136
+
137
+ context "when encrypting multiple plaintext passwords with alternate seed values" do
138
+ before(:each) do
139
+ @plaintext_hash = "cisco"
140
+ @seeds = 0..15
141
+ @encrypted_hashes = @seeds.map {|seed| C7Decrypt.encrypt(@plaintext_hash, seed)}
142
+ end
143
+
144
+ subject{@encrypted_hashes}
145
+ its(:class) {should == ::Array}
146
+
147
+ it "should decrypt back to the original plaintext hashes" do
148
+ @encrypted_hashes.each do |encrypted_hash|
149
+ C7Decrypt.decrypt(encrypted_hash).should == @plaintext_hash
150
+ end
151
+ end
152
+ end
153
+
154
+ context "when encrypting known value matches individually" do
155
+ before(:each) do
156
+ @encrypted_hashes = []
157
+ @known_values.each do |known_value|
158
+ @encrypted_hashes << C7Decrypt.encrypt(known_value[:pt], known_value[:seed])
159
+ end
160
+ end
161
+
162
+ subject{@encrypted_hashes}
163
+ its(:class) {should == ::Array}
164
+ its(:size) {should == @known_values.size}
165
+ it {should == @known_values.map {|known_value| known_value[:ph]}}
166
+ end
167
+
168
+ context "when encrypting known value matches individually as an array" do
169
+ before(:each) do
170
+ @plaintext_passwords = @known_values.map {|known_value| known_value[:pt]}.uniq
171
+ @encrypted_passwords = C7Decrypt.encrypt_array(@plaintext_passwords)
172
+ end
173
+
174
+ subject{@encrypted_passwords}
175
+ its(:class) {should == ::Array}
176
+ its(:size) {should == @plaintext_passwords.size}
177
+ it {should == @plaintext_passwords.map {|plaintext_password| C7Decrypt.encrypt(plaintext_password)}}
178
+ end
179
+
180
+ context "when encrypting Cisco Type-7" do
181
+ before(:each) do
182
+ @plaintext_hash = "remcisco"
183
+ @encrypted_hash = C7Decrypt.encrypt(@plaintext_hash)
184
+ end
185
+
186
+ subject{@encrypted_hash}
187
+ its(:class) {should == ::String}
188
+ it {should == "02140156080F1C2243"}
189
+ end
190
+
191
+ context "when encrypting Cisco Type-7 with a seed of 15" do
192
+ before(:each) do
193
+ @plaintext_hash = "remcisco"
194
+ @seed = 15
195
+ @encrypted_hash = C7Decrypt.encrypt(@plaintext_hash, @seed)
196
+ end
197
+
198
+ subject{@encrypted_hash}
199
+ its(:class) {should == ::String}
200
+ it {should == "15000E010723382727"}
201
+ end
202
+
203
+ context "when trying to decrypt a hash with an invalid first character" do
204
+ it "should raise an InvalidFirstCharacter Exception" do
205
+ expect { C7Decrypt.decrypt("AA000E010723382727") }.to raise_error(C7Decrypt::InvalidFirstCharacter)
206
+ end
207
+ end
208
+
209
+ context "when trying to decrypt a hash with an invalid character" do
210
+ it "should raise an InvalidFirstCharacter Exception" do
211
+ expect { C7Decrypt.decrypt("06000**E010723382727") }.to raise_error(C7Decrypt::InvalidCharacter)
212
+ end
213
+ end
214
+
215
+ context "when trying to decrypt a hash with an odd number of characters" do
216
+ it "should raise an InvalidFirstCharacter Exception" do
217
+ expect { C7Decrypt.decrypt("06000E01723382727") }.to raise_error(C7Decrypt::OddNumberOfCharacters)
218
+ end
219
+ end
220
+
221
+ context "when trying to encrypt a hash with an invalid high encryption seed" do
222
+ it "should raise an InvalidFirstCharacter Exception" do
223
+ expect { C7Decrypt.encrypt("bananas", 16) }.to raise_error(C7Decrypt::InvalidEncryptionSeed)
224
+ end
225
+ end
226
+
227
+ context "when trying to encrypt a hash with an invalid low encryption seed" do
228
+ it "should raise an InvalidFirstCharacter Exception" do
229
+ expect { C7Decrypt.encrypt("bananas", -1) }.to raise_error(C7Decrypt::InvalidEncryptionSeed)
230
+ end
231
+ end
232
+
233
+ end
@@ -0,0 +1,13 @@
1
+ # Removed "7"
2
+ username password 0822455D0A16
3
+ # Removed password
4
+ username password 7
5
+ # changed password to pword
6
+ enable pword 7 060506324F41
7
+ # changed hash to something weird, but still expect this to "hit"
8
+ enable password 7 abc123
9
+ R3(config)#do show run | sec vty
10
+ line vty 0 4
11
+ # again changed hash to something weird, expect this to "hit" but it doesn't ...
12
+ password 7 /etc/passwd
13
+ login
File without changes
@@ -0,0 +1,8 @@
1
+ username test password 7 0822455D0A16
2
+ username test password 7 0822455D0A16
3
+ enable password 7 060506324F41
4
+ enable password 7 060506324F41
5
+ R3(config)#do show run | sec vty
6
+ line vty 0 4
7
+ password 7 02050D480809
8
+ login
@@ -0,0 +1,7 @@
1
+ begin
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ rescue LoadError
5
+ warn "Couldn't load simplecov, so coverage reports will be generated"
6
+ warn "Run 'gem install simplecov' to get coverage reports"
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: c7decrypt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-05 00:00:00.000000000 Z
12
+ date: 2013-05-28 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A library for decoding Cisco Type 7 passwords
15
15
  email: claudijd@yahoo.com
@@ -17,7 +17,24 @@ executables: []
17
17
  extensions: []
18
18
  extra_rdoc_files: []
19
19
  files:
20
+ - lib/c7decrypt/c7decrypt.rb
21
+ - lib/c7decrypt/version.rb
20
22
  - lib/c7decrypt.rb
23
+ - spec/c7decrypt_spec.rb
24
+ - spec/example_configs/bad_canned_example.txt
25
+ - spec/example_configs/empty_example.txt
26
+ - spec/example_configs/simple_canned_example.txt
27
+ - spec/spec_helper.rb
28
+ - examples/cdecrypt.rb
29
+ - .gitignore
30
+ - .rspec
31
+ - .travis.yml
32
+ - CONTRIBUTING.md
33
+ - Gemfile
34
+ - LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - c7decrypt.gemspec
21
38
  homepage: http://rubygems.org/gems/c7decrypt
22
39
  licenses: []
23
40
  post_install_message:
@@ -30,9 +47,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
30
47
  - - ! '>='
31
48
  - !ruby/object:Gem::Version
32
49
  version: '0'
33
- segments:
34
- - 0
35
- hash: 4090891342571299322
36
50
  required_rubygems_version: !ruby/object:Gem::Requirement
37
51
  none: false
38
52
  requirements:
@@ -41,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
41
55
  version: '0'
42
56
  requirements: []
43
57
  rubyforge_project:
44
- rubygems_version: 1.8.25
58
+ rubygems_version: 1.8.23
45
59
  signing_key:
46
60
  specification_version: 3
47
61
  summary: Ruby based Cisco Type 7 Password Decryptor