-
Notifications
You must be signed in to change notification settings - Fork 16
/
junosdecode.py
executable file
·102 lines (78 loc) · 2.7 KB
/
junosdecode.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/python
#############################################################################
## this lovely script was painfully ported
## by matt hite ([email protected]), who knows
## very little perl
##
## original: http://search.cpan.org/dist/Crypt-Juniper/lib/Crypt/Juniper.pm
## requires python 2.7 due to use of dict comprehension
##
## version 1.0
##
import sys
from optparse import OptionParser, OptionGroup
#################################################################
## globals
MAGIC = "$9$"
###################################
## letter families
FAMILY = ["QzF3n6/9CAtpu0O", "B1IREhcSyrleKvMW8LXx", "7N-dVbwsY2g4oaJZGUDj", "iHkq.mPf5T"]
EXTRA = dict()
for x, item in enumerate(FAMILY):
for c in item:
EXTRA[c] = 3 - x
###################################
## forward and reverse dictionaries
NUM_ALPHA = [x for x in "".join(FAMILY)]
ALPHA_NUM = {NUM_ALPHA[x]: x for x in range(0, len(NUM_ALPHA))}
###################################
## encoding moduli by position
ENCODING = [[1, 4, 32], [1, 16, 32], [1, 8, 32], [1, 64], [1, 32], [1, 4, 16, 128], [1, 32, 64]]
def _nibble(cref, length):
nib = cref[0:length]
rest = cref[length:]
if len(nib) != length:
print "Ran out of characters: hit '%s', expecting %s chars" % (nib, length)
sys.exit(1)
return nib, rest
def _gap(c1, c2):
return (ALPHA_NUM[str(c2)] - ALPHA_NUM[str(c1)]) % (len(NUM_ALPHA)) - 1
def _gap_decode(gaps, dec):
num = 0
if len(gaps) != len(dec):
print "Nibble and decode size not the same!"
sys.exit(1)
for x in range(0, len(gaps)):
num += gaps[x] * dec[x]
return chr(num % 256)
def juniper_decrypt(crypt):
chars = crypt.split("$9$", 1)[1]
first, chars = _nibble(chars, 1)
toss, chars = _nibble(chars, EXTRA[first])
prev = first
decrypt = ""
while chars:
decode = ENCODING[len(decrypt) % len(ENCODING)]
nibble, chars = _nibble(chars, len(decode))
gaps = []
for i in nibble:
g = _gap(prev, i)
prev = i
gaps += [g]
decrypt += _gap_decode(gaps, decode)
return decrypt
def main():
parser = OptionParser(usage="usage: %prog [options] encrypted_string",
version="1.0")
(options, args) = parser.parse_args()
# right number of arguments?
if len(args) < 1:
parser.error("wrong number of arguments")
encrypted_string = args[0]
print "junos password decrypter"
print "python version by matt hite"
print "original perl version by kevin brintnall\n"
print "encrypted version: %s" % encrypted_string
print "decrypted version: %s" % juniper_decrypt(encrypted_string)
if __name__ == "__main__":
main()