router_crypt 0.3.0
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 +1 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +17 -0
- data/README.md +36 -0
- data/bin/rtrcrypt +9 -0
- data/lib/cli/cli.rb +16 -0
- data/lib/ios/common.rb +3 -0
- data/lib/ios/decrypt.rb +15 -0
- data/lib/junos/common.rb +40 -0
- data/lib/junos/decrypt.rb +27 -0
- data/lib/nxos/common.rb +4 -0
- data/lib/nxos/decrypt.rb +15 -0
- data/lib/router_crypt.rb +10 -0
- data/rakefile +36 -0
- data/router_crypt.gemspec +15 -0
- data/spec/ios/decrypt_spec.rb +9 -0
- data/spec/junos/common_spec.rb +39 -0
- data/spec/junos/decrypt_spec.rb +9 -0
- data/spec/nxos/decrypt_spec.rb +9 -0
- data/spec/spec_helper.rb +7 -0
- metadata +71 -0
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
gems/*
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
GEM
|
2
|
+
specs:
|
3
|
+
diff-lcs (1.2.1)
|
4
|
+
rspec (2.13.0)
|
5
|
+
rspec-core (~> 2.13.0)
|
6
|
+
rspec-expectations (~> 2.13.0)
|
7
|
+
rspec-mocks (~> 2.13.0)
|
8
|
+
rspec-core (2.13.0)
|
9
|
+
rspec-expectations (2.13.0)
|
10
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
11
|
+
rspec-mocks (2.13.0)
|
12
|
+
|
13
|
+
PLATFORMS
|
14
|
+
ruby
|
15
|
+
|
16
|
+
DEPENDENCIES
|
17
|
+
rspec
|
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
router_crypt
|
2
|
+
============
|
3
|
+
|
4
|
+
About
|
5
|
+
-----
|
6
|
+
Ruby library and executable to (de)crypt various router vendors (JunOS, IOS, NXOS) password. As of now, only decrypt is implemented
|
7
|
+
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
gem install router_crypt
|
12
|
+
|
13
|
+
|
14
|
+
CLI usage
|
15
|
+
---------
|
16
|
+
rtrcrypt [encrypted password]
|
17
|
+
|
18
|
+
|
19
|
+
Library usage
|
20
|
+
-------------
|
21
|
+
require 'router_crypt'
|
22
|
+
|
23
|
+
RouterCrypt::IOS.decrypt ios_pw
|
24
|
+
RouterCrypt::NXOS.decrypt nxos_pw
|
25
|
+
RouterCrypt::JunOS.decrypt junos_pw
|
26
|
+
|
27
|
+
|
28
|
+
Thanks
|
29
|
+
------
|
30
|
+
I've ripped the JunOS algo from CPAN Crypt::Juniper by Kevin Brintnall. IOS algo
|
31
|
+
source is unknown I've ported it long time ago from anonymous perl source.
|
32
|
+
|
33
|
+
|
34
|
+
License
|
35
|
+
-------
|
36
|
+
Public domain, copyleft, whatnot
|
data/bin/rtrcrypt
ADDED
data/lib/cli/cli.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
class RouterCrypt::CLI
|
2
|
+
class << self
|
3
|
+
def run
|
4
|
+
pw = ARGV[0].dup or raise ArgumentError, 'no password given'
|
5
|
+
case pw
|
6
|
+
when /^\$9\$/
|
7
|
+
RouterCrypt::JunOS.decrypt pw
|
8
|
+
when /^[\dA-F]+$/
|
9
|
+
RouterCrypt::IOS.decrypt pw
|
10
|
+
else
|
11
|
+
#presume it's NXOS, no clear way to separate garbage and NXOS PW
|
12
|
+
RouterCrypt::NXOS.decrypt pw
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/ios/common.rb
ADDED
data/lib/ios/decrypt.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class RouterCrypt::IOS
|
2
|
+
class << self
|
3
|
+
# Decrypts IOS type 7 passwords. Original is from unknown perl source
|
4
|
+
#
|
5
|
+
# @param [String] the encrypted string
|
6
|
+
# @return [String] the unencrypted string
|
7
|
+
def decrypt e_pw
|
8
|
+
index = e_pw.slice!(0..1).to_i-1
|
9
|
+
e_pw.scan(/../).inject("") do |d_pw, byte|
|
10
|
+
index += 1 % KEY.size
|
11
|
+
d_pw + (byte.hex ^ KEY[index]).chr
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/junos/common.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
class RouterCrypt::JunOS
|
2
|
+
class InvalidPW < StandardError; end
|
3
|
+
|
4
|
+
ENCODE = [
|
5
|
+
[ 1, 4, 32 ],
|
6
|
+
[ 1, 16, 32 ],
|
7
|
+
[ 1, 8, 32 ],
|
8
|
+
[ 1, 64 ],
|
9
|
+
[ 1, 32 ],
|
10
|
+
[ 1, 4, 16, 128 ],
|
11
|
+
[ 1, 32, 64 ],
|
12
|
+
]
|
13
|
+
EXTRA = {}
|
14
|
+
KEY = %w( QzF3n6/9CAtpu0O B1IREhcSyrleKvMW8LXx 7N-dVbwsY2g4oaJZGUDj iHkq.mPf5T )
|
15
|
+
KEYCHAR = KEY.join.each_char.to_a
|
16
|
+
KEY.each_with_index do |key, index|
|
17
|
+
key.each_char { |c| EXTRA[c] = 3-index }
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def nibble str, len
|
25
|
+
nib, str[0..len-1] = str[0..len-1], ''
|
26
|
+
nib.size == len or raise InvalidPW, 'Insufficent amont of characters'
|
27
|
+
nib
|
28
|
+
end
|
29
|
+
|
30
|
+
def gap c1, c2
|
31
|
+
(KEYCHAR.index(c1) - KEYCHAR.index(c2)) % KEYCHAR.size - 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def gap_decode gaps, dec
|
35
|
+
gaps.size == dec.size or raise InvalidPW, 'gaps and dec are unequal size'
|
36
|
+
(gaps.each_with_index.inject(0) { |num, (e, index)| num + e * dec[index] } % 256).chr
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class RouterCrypt::JunOS
|
2
|
+
class << self
|
3
|
+
# Decrypts JunOS $9$ style passwords. This is reimplementation of CPAN
|
4
|
+
# Crypt::Juniper (by Kevin Brintnall, <kbrint at rufus.net>) ''juniper_decrypt' function
|
5
|
+
#
|
6
|
+
# @param [String] the encrypted string, with or without $9$ in front of it
|
7
|
+
# @return [String] the unencrypted string
|
8
|
+
def decrypt e_pw
|
9
|
+
e_pw = e_pw[3..-1] if e_pw['$9$']
|
10
|
+
d_pw = ''
|
11
|
+
prev = nibble e_pw, 1
|
12
|
+
nibble e_pw, EXTRA[prev]
|
13
|
+
|
14
|
+
while e_pw.size > 0
|
15
|
+
decode = ENCODE[d_pw.size % ENCODE.size]
|
16
|
+
gaps = nibble(e_pw, decode.size).each_char.map do |e|
|
17
|
+
g = gap e, prev
|
18
|
+
prev = e
|
19
|
+
g
|
20
|
+
end
|
21
|
+
d_pw += gap_decode gaps, decode
|
22
|
+
end
|
23
|
+
|
24
|
+
d_pw
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/nxos/common.rb
ADDED
data/lib/nxos/decrypt.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
class RouterCrypt::NXOS
|
2
|
+
class << self
|
3
|
+
# Decrypts NXOS type 7 passwords, original research
|
4
|
+
#
|
5
|
+
# @param [String] the unencrypted string
|
6
|
+
# @return [String] the decrypted string
|
7
|
+
def decrypt e_pw
|
8
|
+
index = -1
|
9
|
+
e_pw.each_char.inject("") do |d_pw, chr|
|
10
|
+
index += 1
|
11
|
+
d_pw + (ALPHA.include?(chr) ? ALPHA[chr.ord - KEY[index]] : chr)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/router_crypt.rb
ADDED
data/rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
Bundler.setup
|
5
|
+
rescue LoadError
|
6
|
+
warn 'missing dependencies'
|
7
|
+
exit 42
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
gemspec = eval(File.read(Dir['*.gemspec'].first))
|
12
|
+
|
13
|
+
desc 'Validate the gemspec'
|
14
|
+
task :gemspec do
|
15
|
+
gemspec.validate
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec::Core::RakeTask.new(:spec)
|
19
|
+
|
20
|
+
|
21
|
+
desc "Build gem locally"
|
22
|
+
task :build => %i(spec gemspec) do
|
23
|
+
system "gem build #{gemspec.name}.gemspec"
|
24
|
+
FileUtils.mkdir_p "gems"
|
25
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "gems"
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "Install gem locally"
|
29
|
+
task :install => :build do
|
30
|
+
system "sudo sh -c \'umask 022; gem20 install gems/#{gemspec.name}-#{gemspec.version}\'"
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Clean automatically generated files"
|
34
|
+
task :clean do
|
35
|
+
FileUtils.rm_rf "gems"
|
36
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'router_crypt'
|
3
|
+
s.version = '0.3.0'
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
s.authors = [ 'Saku Ytti' ]
|
6
|
+
s.email = %w( saku@ytti.fi )
|
7
|
+
s.homepage = 'http://github.com/ytti/router_crypt'
|
8
|
+
s.summary = 'Crypt library for JunOS/IOS/NX-OS passwords'
|
9
|
+
s.description = 'Library and binary which decrypt (crypt unimplemented) Juniper JunOS $9$, Cisco IOS type 7 and Cisco NX-OS passwords'
|
10
|
+
s.rubyforge_project = s.name
|
11
|
+
s.files = `git ls-files`.split("\n")
|
12
|
+
s.executables = %w( rtrcrypt )
|
13
|
+
s.require_path = 'lib'
|
14
|
+
s.required_rubygems_version = '>= 1.3.6'
|
15
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'router_crypt'
|
2
|
+
|
3
|
+
|
4
|
+
describe RouterCrypt::JunOS, '#nibble' do
|
5
|
+
it 'returns k for 1 char out of "kakka"' do
|
6
|
+
str = 'kakka'
|
7
|
+
nib = RouterCrypt::JunOS.send :nibble, str, 1
|
8
|
+
nib.should eq 'k'
|
9
|
+
str.should eq 'akka'
|
10
|
+
end
|
11
|
+
it 'returns kak for 3 char out of "kakka"' do
|
12
|
+
str = 'kakka'
|
13
|
+
nib = RouterCrypt::JunOS.send :nibble, str, 3
|
14
|
+
nib.should eq 'kak'
|
15
|
+
str.should eq 'ka'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe RouterCrypt::JunOS, '#gap' do
|
20
|
+
it 'returns 7 for gap between k and J' do
|
21
|
+
gap = RouterCrypt::JunOS.send :gap, 'k', 'J'
|
22
|
+
gap.should eq 7
|
23
|
+
end
|
24
|
+
it 'returns 56 for gap between J and k' do
|
25
|
+
gap = RouterCrypt::JunOS.send :gap, 'J', 'k'
|
26
|
+
gap.should eq 56
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe RouterCrypt::JunOS, "#gaps" do
|
31
|
+
it 'returns ) for [gaps], [dec]' do
|
32
|
+
chr = RouterCrypt::JunOS.send :gap_decode, RouterCrypt::JunOS::ENCODE[1], [9, 42, 12]
|
33
|
+
chr.should eq ')'
|
34
|
+
end
|
35
|
+
it 'returns n for [gaps2], [dec2]' do
|
36
|
+
chr = RouterCrypt::JunOS.send :gap_decode, RouterCrypt::JunOS::ENCODE[5], [42, 69, 99, 4]
|
37
|
+
chr.should eq 'n'
|
38
|
+
end
|
39
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: router_crypt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Saku Ytti
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-07 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Library and binary which decrypt (crypt unimplemented) Juniper JunOS
|
15
|
+
$9$, Cisco IOS type 7 and Cisco NX-OS passwords
|
16
|
+
email:
|
17
|
+
- saku@ytti.fi
|
18
|
+
executables:
|
19
|
+
- rtrcrypt
|
20
|
+
extensions: []
|
21
|
+
extra_rdoc_files: []
|
22
|
+
files:
|
23
|
+
- .gitignore
|
24
|
+
- .rspec
|
25
|
+
- Gemfile
|
26
|
+
- Gemfile.lock
|
27
|
+
- README.md
|
28
|
+
- bin/rtrcrypt
|
29
|
+
- lib/cli/cli.rb
|
30
|
+
- lib/ios/common.rb
|
31
|
+
- lib/ios/decrypt.rb
|
32
|
+
- lib/junos/common.rb
|
33
|
+
- lib/junos/decrypt.rb
|
34
|
+
- lib/nxos/common.rb
|
35
|
+
- lib/nxos/decrypt.rb
|
36
|
+
- lib/router_crypt.rb
|
37
|
+
- rakefile
|
38
|
+
- router_crypt.gemspec
|
39
|
+
- spec/ios/decrypt_spec.rb
|
40
|
+
- spec/junos/common_spec.rb
|
41
|
+
- spec/junos/decrypt_spec.rb
|
42
|
+
- spec/nxos/decrypt_spec.rb
|
43
|
+
- spec/spec_helper.rb
|
44
|
+
homepage: http://github.com/ytti/router_crypt
|
45
|
+
licenses: []
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
hash: 322463051478397895
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.3.6
|
65
|
+
requirements: []
|
66
|
+
rubyforge_project: router_crypt
|
67
|
+
rubygems_version: 1.8.25
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Crypt library for JunOS/IOS/NX-OS passwords
|
71
|
+
test_files: []
|