'''
ciscodecrypt
version 0.1
cisco password type 7 encryption / decryption
passwords rules
- Must contain from 1 to 25 uppercase and lowercase alphanumeric characters.
- Must not have a number as the first character.
- Can have leading spaces, but they are ignored.
However, intermediate and trailing spaces are recognized.
- Can contain the question mark (?) character.
Version 0.1 April 2015;
initial version
Author: Guillermo Gomez (a.k.a Momo)
'''
import struct
import argparse
import time
import random
import string
class type7_key(object):
KEY_SEED = (0x64,0x73,0x66,0x64,0x3b,0x6b,0x66,0x6f, \
0x41,0x2c,0x2e,0x69,0x79,0x65,0x77,0x72, \
0x6b,0x6c,0x64,0x4a,0x4b,0x44,0x48,0x53, \
0x55,0x42,0x73,0x67,0x76,0x63,0x61,0x36, \
0x39,0x38,0x33,0x34,0x6e,0x63,0x78,0x76, \
0x39,0x38,0x37,0x33,0x32,0x35,0x34,0x6b, \
0x3b,0x66,0x67,0x38,0x37)
def __init__(self):
'''
clear all values
'''
self.clear_text = ""
self.encrypt_text = ""
self.salt = 0
self.error = ""
def decrypt (self):
self.clear_text = ""
for i in range(2, len(self.encrypt_text),2):
self.clear_text += str (chr (int (self.KEY_SEED[self.salt+(i/2-1)] ^ int(self.encrypt_text[i:i+2],base=16))))
def encrypt (self):
index = self.salt
if index < 10:
self.encrypt_text = '0'
self.encrypt_text += str(self.salt)
for c in self.clear_text:
e = hex (self.KEY_SEED[index] ^ ord (c)) # output format is '0x_' or '0x__'
index += 1
if len(e) == 4:
self.encrypt_text += e[2:4].upper()
else:
self.encrypt_text += '0'+e[2].upper()
def check_pswd (self): # check if password conforms rules
self.clear_text.lstrip()
if len(self.clear_text) > 25:
self.error = "password too long"
return False
for c in self.clear_text:
if not (c in string.ascii_letters or\
c in string.digits or\
c in string.punctuation or \
c == " "):
self.error = "ilegal character"
return False
self.error = ""
return True
def check_encpswd (self): # check encrypted text
if (len(self.encrypt_text)%2 != 0) or (len(self.encrypt_text) < 4):
self.error = "invalid cypher (short)"
return False
for c in self.encrypt_text:
if not c in string.hexdigits:
self.error = "invalid cypher (char)"
return False
if not self.encrypt_text[0].isdigit() or not self.encrypt_text[1].isdigit():
self.error = "invalid cypher (salt)"
return False
self.salt = int(self.encrypt_text[0:2])
if self.salt not in range (0, 16):
self.error = "invalid cypher (salt)"
return False
self.error = ""
return True
def main():
# argument analysis
parser = argparse.ArgumentParser(
prog = 'ciscodecrypt',
description = 'Cisco password type 7 encryption/descryption',
epilog = ' Hope you enjoy ;) -- M0M0 --')
parser.add_argument ('password', \
help='Password to be decrypted or encrypted')
parser.add_argument ('-s', dest='salt', type=int,\
help='Set cypher salt: 0 to 15')
parser.add_argument ('-v', '--verbose', action='store_true',\
help='Verbose output')
args = parser.parse_args()
cpwrd = type7_key()
if args.salt in range (0,15):
cpwrd.salt = args.salt
elif not args.salt:
cpwrd.salt = random.randint (0, 15)
else:
cpwrd.salt = random.randint (0, 15)
print 'Invalid salt, randomizing'
if args.password[0].isdigit(): # decrypt
print 'Decrypting'
cpwrd.encrypt_text = args.password
if cpwrd.check_encpswd():
cpwrd.decrypt()
print ' Salt is:',cpwrd.salt
if cpwrd.check_pswd():
print ' Password is:',cpwrd.clear_text
else:
print ' Found an error: ',cpwrd.error
else:
print cpwrd.error
else:
print 'Encrypting'
cpwrd.clear_text = args.password
if cpwrd.check_pswd():
cpwrd.encrypt()
print ' Salt is:',cpwrd.salt
if cpwrd.check_encpswd():
print ' Encrypted password is:',cpwrd.encrypt_text
else:
print ' Found an error: ',cpwrd.error
else:
print cpwrd.error
if args.verbose:
print '\n'
print 'Password :',cpwrd.clear_text
print 'Encrypted password :',cpwrd.encrypt_text
print 'Used salt :',cpwrd.salt
print 'Error if found :',cpwrd.error
if __name__ == "__main__":
main()
No comments:
Post a Comment