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 103 104 105 106 107 108 109 110 111 112
| from Crypto.Cipher import AES, Blowfish from hashlib import sha1 import binascii
class NavicatPassword: def __init__(self, version=11): self.version = version self.aes_key = b'libcckeylibcckey' self.aes_iv = b'libcciv libcciv ' self.blowfish_key = sha1(b'3DC5CA39').digest() self.blowfish_iv = bytes([0xd9, 0xc7, 0xc3, 0xc8, 0x87, 0x0d, 0x64, 0xbd])
def xor_bytes(self, a, b): return bytes([x ^ y for x, y in zip(a, b)])
def decrypt(self, encrypted): if self.version == 12: return self.decrypt_twelve(encrypted) else: return self.decrypt_eleven(encrypted)
def decrypt_twelve(self, encrypted): """Navicat 12 使用 AES-128-CBC""" encrypted_bytes = binascii.unhexlify(encrypted) if len(encrypted_bytes) % 16 != 0: encrypted_bytes += b'\x00' * (16 - len(encrypted_bytes) % 16) cipher = AES.new(self.aes_key, AES.MODE_CBC, self.aes_iv) decrypted = cipher.decrypt(encrypted_bytes) return decrypted.rstrip(b'\x00').decode('utf-8', errors='ignore')
def decrypt_eleven(self, encrypted): """Navicat 11 使用 Blowfish + 自定义 XOR 链""" encrypted_bytes = binascii.unhexlify(encrypted) result = b'' current_vector = self.blowfish_iv cipher = Blowfish.new(self.blowfish_key, Blowfish.MODE_ECB)
round_count = len(encrypted_bytes) // 8 left_length = len(encrypted_bytes) % 8
for i in range(round_count): block = encrypted_bytes[i * 8:(i + 1) * 8] decrypted_block = cipher.decrypt(block) temp = self.xor_bytes(decrypted_block, current_vector) current_vector = self.xor_bytes(current_vector, block) result += temp
if left_length > 0: remaining = encrypted_bytes[round_count * 8:] encrypted_vector = cipher.encrypt(current_vector) result += self.xor_bytes(remaining, encrypted_vector[:left_length])
return result.rstrip(b'\x00').decode('utf-8', errors='ignore')
def encrypt(self, plaintext): if self.version == 12: return self.encrypt_twelve(plaintext) else: return self.encrypt_eleven(plaintext)
def encrypt_eleven(self, plaintext): """Navicat 11 加密""" plaintext_bytes = plaintext.encode('utf-8') result = b'' current_vector = self.blowfish_iv cipher = Blowfish.new(self.blowfish_key, Blowfish.MODE_ECB)
round_count = len(plaintext_bytes) // 8 left_length = len(plaintext_bytes) % 8
for i in range(round_count): block = plaintext_bytes[i * 8:(i + 1) * 8] temp = self.xor_bytes(block, current_vector) encrypted_block = cipher.encrypt(temp) current_vector = self.xor_bytes(current_vector, encrypted_block) result += encrypted_block
if left_length > 0: remaining = plaintext_bytes[round_count * 8:] encrypted_vector = cipher.encrypt(current_vector) result += self.xor_bytes(remaining, encrypted_vector[:left_length])
return result.hex().upper()
def encrypt_twelve(self, plaintext): """Navicat 12 加密""" plaintext_bytes = plaintext.encode('utf-8') if len(plaintext_bytes) % 16 != 0: plaintext_bytes += b'\x00' * (16 - len(plaintext_bytes) % 16) cipher = AES.new(self.aes_key, AES.MODE_CBC, self.aes_iv) encrypted = cipher.encrypt(plaintext_bytes) return encrypted.hex().upper()
if __name__ == '__main__': passwords = { 'ceshi (localhost:3306, root)': 'BE536F6210406B878B', 'measu (10.xxx.xxx.xxx:3308, root)': '99E5C424961F27FC2FD4', 'widi (57.xxx.xxx.xxx:33032, root)': 'CA50766B9665F921CC0CD065CA', }
nav = NavicatPassword(version=11) for name, enc_pwd in passwords.items(): decrypted = nav.decrypt(enc_pwd) print(f"\n连接: {name}") print(f"密文: {enc_pwd}") print(f"明文: {decrypted}")
|