<?php
class NavicatPassword
{
protected $version = 0;
protected $aesKey = 'libcckeylibcckey';
protected $aesIv = 'libcciv libcciv ';
protected $blowString = '3DC5CA39';
protected $blowKey = null;
protected $blowIv = null;
public function __construct($version = 12)
{
$this->version = $version;
$this->blowKey = sha1('3DC5CA39', true); $this->blowIv = hex2bin('d9c7c3c8870d64bd');
}
public function encrypt($string)
{
$result = FALSE;
switch ($this->version) {
case 11:
$result = $this->encryptEleven($string);
break;
case 12:
$result = $this->encryptTwelve($string);
break;
default:
break;
}
return $result;
}
protected function encryptEleven($string)
{
$leftLength = strlen($string) % 8; $result = '';
$currentVector = $this->blowIv;
for ($i = 0; $i < $round; $i++) {
$temp = $this->encryptBlock($this->xorBytes(substr($string, 8 * $i, 8), $currentVector)); $currentVector = $this->xorBytes($currentVector, $temp);
$result .= $temp;
}
if ($leftLength) {
$currentVector = $this->encryptBlock($currentVector);
$result .= $this->xorBytes(substr($string, 8 * $round), $currentVector); }
}
protected function encryptBlock($block)
{
return openssl_encrypt($block, 'BF-ECB', $this->blowKey, OPENSSL_RAW_DATA|OPENSSL_NO_PADDING);
}
protected function decryptBlock($block)
{
return openssl_decrypt($block, 'BF-ECB', $this->blowKey, OPENSSL_RAW_DATA|OPENSSL_NO_PADDING);
}
protected function xorBytes($str1, $str2)
{
$result = '';
for ($i = 0; $i < strlen($str1); $i++) { $result .= chr(ord($str1[$i]) ^
ord($str2[$i])); }
return $result;
}
public function decrypt($string)
{
$result = FALSE;
switch ($this->version) {
case 11:
$result = $this->decryptEleven($string);
break;
case 12:
$result = $this->decryptTwelve($string);
break;
default:
break;
}
return $result;
}
protected function decryptEleven($upperString)
{
$leftLength = strlen($string) % 8; $result = '';
$currentVector = $this->blowIv;
for ($i = 0; $i < $round; $i++) {
$encryptedBlock = substr($string, 8 * $i, 8); $temp = $this->xorBytes($this->decryptBlock($encryptedBlock), $currentVector);
$currentVector = $this->xorBytes($currentVector, $encryptedBlock);
$result .= $temp;
}
if ($leftLength) {
$currentVector = $this->encryptBlock($currentVector);
$result .= $this->xorBytes(substr($string, 8 * $round), $currentVector); }
return $result;
}
protected function encryptTwelve($string)
{
$result = openssl_encrypt($string, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv);
}
protected function decryptTwelve($upperString)
{
return openssl_decrypt($string, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv);
}
}
// 使用示例
$navicatPassword = new NavicatPassword(12);
$encryptedHex = 'B744013C755BBCE9B4F034329224';
$decryptedPassword = $navicatPassword->decrypt($encryptedHex);
echo "解密后的密码: ". $decryptedPassword. PHP_EOL;
?>
PD9waHAKY2xhc3MgTmF2aWNhdFBhc3N3b3JkCnsKICAgIHByb3RlY3RlZCAkdmVyc2lvbiA9IDA7CiAgICBwcm90ZWN0ZWQgJGFlc0tleSA9ICdsaWJjY2tleWxpYmNja2V5JzsKICAgIHByb3RlY3RlZCAkYWVzSXYgPSAnbGliY2NpdiBsaWJjY2l2ICc7CiAgICBwcm90ZWN0ZWQgJGJsb3dTdHJpbmcgPSAnM0RDNUNBMzknOwogICAgcHJvdGVjdGVkICRibG93S2V5ID0gbnVsbDsKICAgIHByb3RlY3RlZCAkYmxvd0l2ID0gbnVsbDsKCiAgICBwdWJsaWMgZnVuY3Rpb24gX19jb25zdHJ1Y3QoJHZlcnNpb24gPSAxMikKICAgIHsKICAgICAgICAkdGhpcy0+dmVyc2lvbiA9ICR2ZXJzaW9uOwogICAgICAgICR0aGlzLT5ibG93S2V5ID0gc2hhMSgnM0RDNUNBMzknLCB0cnVlKTsKICAgICAgICAkdGhpcy0+Ymxvd0l2ID0gaGV4MmJpbignZDljN2MzYzg4NzBkNjRiZCcpOwogICAgfQoKICAgIHB1YmxpYyBmdW5jdGlvbiBlbmNyeXB0KCRzdHJpbmcpCiAgICB7CiAgICAgICAgJHJlc3VsdCA9IEZBTFNFOwogICAgICAgIHN3aXRjaCAoJHRoaXMtPnZlcnNpb24pIHsKICAgICAgICAgICAgY2FzZSAxMToKICAgICAgICAgICAgICAgICRyZXN1bHQgPSAkdGhpcy0+ZW5jcnlwdEVsZXZlbigkc3RyaW5nKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDEyOgogICAgICAgICAgICAgICAgJHJlc3VsdCA9ICR0aGlzLT5lbmNyeXB0VHdlbHZlKCRzdHJpbmcpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICB9CgogICAgICAgIHJldHVybiAkcmVzdWx0OwogICAgfQoKICAgIHByb3RlY3RlZCBmdW5jdGlvbiBlbmNyeXB0RWxldmVuKCRzdHJpbmcpCiAgICB7CiAgICAgICAgJHJvdW5kID0gaW50dmFsKGZsb29yKHN0cmxlbigkc3RyaW5nKSAvIDgpKTsKICAgICAgICAkbGVmdExlbmd0aCA9IHN0cmxlbigkc3RyaW5nKSAlIDg7CiAgICAgICAgJHJlc3VsdCA9ICcnOwogICAgICAgICRjdXJyZW50VmVjdG9yID0gJHRoaXMtPmJsb3dJdjsKCiAgICAgICAgZm9yICgkaSA9IDA7ICRpIDwgJHJvdW5kOyAkaSsrKSB7CiAgICAgICAgICAgICR0ZW1wID0gJHRoaXMtPmVuY3J5cHRCbG9jaygkdGhpcy0+eG9yQnl0ZXMoc3Vic3RyKCRzdHJpbmcsIDggKiAkaSwgOCksICRjdXJyZW50VmVjdG9yKSk7CiAgICAgICAgICAgICRjdXJyZW50VmVjdG9yID0gJHRoaXMtPnhvckJ5dGVzKCRjdXJyZW50VmVjdG9yLCAkdGVtcCk7CiAgICAgICAgICAgICRyZXN1bHQgLj0gJHRlbXA7CiAgICAgICAgfQoKICAgICAgICBpZiAoJGxlZnRMZW5ndGgpIHsKICAgICAgICAgICAgJGN1cnJlbnRWZWN0b3IgPSAkdGhpcy0+ZW5jcnlwdEJsb2NrKCRjdXJyZW50VmVjdG9yKTsKICAgICAgICAgICAgJHJlc3VsdCAuPSAkdGhpcy0+eG9yQnl0ZXMoc3Vic3RyKCRzdHJpbmcsIDggKiAkcm91bmQpLCAkY3VycmVudFZlY3Rvcik7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gc3RydG91cHBlcihiaW4yaGV4KCRyZXN1bHQpKTsKICAgIH0KCiAgICBwcm90ZWN0ZWQgZnVuY3Rpb24gZW5jcnlwdEJsb2NrKCRibG9jaykKICAgIHsKICAgICAgICByZXR1cm4gb3BlbnNzbF9lbmNyeXB0KCRibG9jaywgJ0JGLUVDQicsICR0aGlzLT5ibG93S2V5LCBPUEVOU1NMX1JBV19EQVRBfE9QRU5TU0xfTk9fUEFERElORyk7CiAgICB9CgogICAgcHJvdGVjdGVkIGZ1bmN0aW9uIGRlY3J5cHRCbG9jaygkYmxvY2spCiAgICB7CiAgICAgICAgcmV0dXJuIG9wZW5zc2xfZGVjcnlwdCgkYmxvY2ssICdCRi1FQ0InLCAkdGhpcy0+Ymxvd0tleSwgT1BFTlNTTF9SQVdfREFUQXxPUEVOU1NMX05PX1BBRERJTkcpOwogICAgfQoKICAgIHByb3RlY3RlZCBmdW5jdGlvbiB4b3JCeXRlcygkc3RyMSwgJHN0cjIpCiAgICB7CiAgICAgICAgJHJlc3VsdCA9ICcnOwogICAgICAgIGZvciAoJGkgPSAwOyAkaSA8IHN0cmxlbigkc3RyMSk7ICRpKyspIHsKICAgICAgICAgICAgJHJlc3VsdCAuPSBjaHIob3JkKCRzdHIxWyRpXSkgXiBvcmQoJHN0cjJbJGldKSk7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gJHJlc3VsdDsKICAgIH0KCiAgICBwdWJsaWMgZnVuY3Rpb24gZGVjcnlwdCgkc3RyaW5nKQogICAgewogICAgICAgICRyZXN1bHQgPSBGQUxTRTsKICAgICAgICBzd2l0Y2ggKCR0aGlzLT52ZXJzaW9uKSB7CiAgICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgICAgICAkcmVzdWx0ID0gJHRoaXMtPmRlY3J5cHRFbGV2ZW4oJHN0cmluZyk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAxMjoKICAgICAgICAgICAgICAgICRyZXN1bHQgPSAkdGhpcy0+ZGVjcnlwdFR3ZWx2ZSgkc3RyaW5nKTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gJHJlc3VsdDsKICAgIH0KCiAgICBwcm90ZWN0ZWQgZnVuY3Rpb24gZGVjcnlwdEVsZXZlbigkdXBwZXJTdHJpbmcpCiAgICB7CiAgICAgICAgJHN0cmluZyA9IGhleDJiaW4oc3RydG9sb3dlcigkdXBwZXJTdHJpbmcpKTsKCiAgICAgICAgJHJvdW5kID0gaW50dmFsKGZsb29yKHN0cmxlbigkc3RyaW5nKSAvIDgpKTsKICAgICAgICAkbGVmdExlbmd0aCA9IHN0cmxlbigkc3RyaW5nKSAlIDg7CiAgICAgICAgJHJlc3VsdCA9ICcnOwogICAgICAgICRjdXJyZW50VmVjdG9yID0gJHRoaXMtPmJsb3dJdjsKCiAgICAgICAgZm9yICgkaSA9IDA7ICRpIDwgJHJvdW5kOyAkaSsrKSB7CiAgICAgICAgICAgICRlbmNyeXB0ZWRCbG9jayA9IHN1YnN0cigkc3RyaW5nLCA4ICogJGksIDgpOwogICAgICAgICAgICAkdGVtcCA9ICR0aGlzLT54b3JCeXRlcygkdGhpcy0+ZGVjcnlwdEJsb2NrKCRlbmNyeXB0ZWRCbG9jayksICRjdXJyZW50VmVjdG9yKTsKICAgICAgICAgICAgJGN1cnJlbnRWZWN0b3IgPSAkdGhpcy0+eG9yQnl0ZXMoJGN1cnJlbnRWZWN0b3IsICRlbmNyeXB0ZWRCbG9jayk7CiAgICAgICAgICAgICRyZXN1bHQgLj0gJHRlbXA7CiAgICAgICAgfQoKICAgICAgICBpZiAoJGxlZnRMZW5ndGgpIHsKICAgICAgICAgICAgJGN1cnJlbnRWZWN0b3IgPSAkdGhpcy0+ZW5jcnlwdEJsb2NrKCRjdXJyZW50VmVjdG9yKTsKICAgICAgICAgICAgJHJlc3VsdCAuPSAkdGhpcy0+eG9yQnl0ZXMoc3Vic3RyKCRzdHJpbmcsIDggKiAkcm91bmQpLCAkY3VycmVudFZlY3Rvcik7CiAgICAgICAgfQoKICAgICAgICByZXR1cm4gJHJlc3VsdDsKICAgIH0KCiAgICBwcm90ZWN0ZWQgZnVuY3Rpb24gZW5jcnlwdFR3ZWx2ZSgkc3RyaW5nKQogICAgewogICAgICAgICRyZXN1bHQgPSBvcGVuc3NsX2VuY3J5cHQoJHN0cmluZywgJ0FFUy0xMjgtQ0JDJywgJHRoaXMtPmFlc0tleSwgT1BFTlNTTF9SQVdfREFUQSwgJHRoaXMtPmFlc0l2KTsKICAgICAgICByZXR1cm4gc3RydG91cHBlcihiaW4yaGV4KCRyZXN1bHQpKTsKICAgIH0KCiAgICBwcm90ZWN0ZWQgZnVuY3Rpb24gZGVjcnlwdFR3ZWx2ZSgkdXBwZXJTdHJpbmcpCiAgICB7CiAgICAgICAgJHN0cmluZyA9IGhleDJiaW4oc3RydG9sb3dlcigkdXBwZXJTdHJpbmcpKTsKICAgICAgICByZXR1cm4gb3BlbnNzbF9kZWNyeXB0KCRzdHJpbmcsICdBRVMtMTI4LUNCQycsICR0aGlzLT5hZXNLZXksIE9QRU5TU0xfUkFXX0RBVEEsICR0aGlzLT5hZXNJdik7CiAgICB9Cn0KCi8vIOS9v+eUqOekuuS+iwokbmF2aWNhdFBhc3N3b3JkID0gbmV3IE5hdmljYXRQYXNzd29yZCgxMik7CiRlbmNyeXB0ZWRIZXggPSAnQjc0NDAxM0M3NTVCQkNFOUI0RjAzNDMyOTIyNCc7CiRkZWNyeXB0ZWRQYXNzd29yZCA9ICRuYXZpY2F0UGFzc3dvcmQtPmRlY3J5cHQoJGVuY3J5cHRlZEhleCk7CmVjaG8gIuino+WvhuWQjueahOWvhueggTogIi4gJGRlY3J5cHRlZFBhc3N3b3JkLiBQSFBfRU9MOwo/Pg==