ciscodecrypt - Cisco password type 7 encryption / decryption

'''
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