# How the Chat2DB Navicat/DBWeaver Import Feature Decrypts Connection Passwords

> Learn how Chat2DB's import feature decrypts Navicat/DBWeaver connection passwords using Blowfish or AES ciphers. Recover your plaintext credentials efficiently.

- Repository: [OtterMind/Chat2DB](https://github.com/OtterMind/Chat2DB)
- Tags: internals
- Published: 2026-07-26

---

**The Navicat/DBWeaver import feature decrypts connection passwords by selecting a version-specific cipher implementation—either Blowfish for Navicat 11 or AES for Navicat 12+—via the `CipherFactory`, then applying the algorithm to hex-encoded ciphertext to recover the plaintext credentials.**

When migrating database connections from Navicat or DBWeaver into Chat2DB, the import process must handle encrypted passwords stored in `.ncx` export files. The Chat2DB source code implements dedicated cipher classes in the `chat2db-community-domain-core` module that reverse-engineer Navicat's proprietary encryption schemes. This allows the `TaskNcxImportServiceImpl` to transparently recover credentials during the import workflow.

## Cipher Selection Via the Factory Pattern

The import service delegates password decryption to the `CipherFactory`, which maintains a registry mapping version identifiers to concrete `CommonCipher` implementations. When processing an `.ncx` file, the service extracts the version enum and requests the appropriate cipher instance.

```java
// TaskNcxImportServiceImpl delegates to the factory
CommonCipher cipher = CipherFactory.get(VersionEnum.native11.name());
// or for modern exports
CommonCipher cipher = CipherFactory.get(VersionEnum.navicat12more.name());

```

### VersionEnum Strategy

The factory recognizes two primary export formats:
- **`VersionEnum.native11`** — Maps to `Navicat11Cipher` for Blowfish-based encryption used in older Navicat releases.
- **`VersionEnum.navicat12more`** — Maps to `Navicat12Cipher` for AES-based encryption introduced in Navicat 12 and later.

This enum-driven approach ensures backward compatibility while supporting modern encryption standards.

## Navicat 11 Blowfish Decryption

For exports generated by Navicat 11, the `Navicat11Cipher` class (located at [`chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ncx/cipher/Navicat11Cipher.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ncx/cipher/Navicat11Cipher.java)) handles decryption using a custom Blowfish implementation. Unlike standard Blowfish/ECB, this cipher employs a variant of CBC mode with a statically derived key and a dynamically generated initialization vector.

### Key Derivation and IV Generation

The cipher derives its secret key from the hardcoded constant `DefaultUserKey = "3DC5CA39"`. It hashes this string using **SHA-1** to produce the Blowfish key material. The initialization vector is generated by encrypting a constant block of `0xFF` bytes with the Blowfish encryptor, creating the starting IV for the chaining process.

### The Custom CBC Decryption Routine

The `decryptString` method processes hex-encoded ciphertext through the following steps:
1. Convert the hex string to a byte array.
2. Decrypt the data in 8-byte blocks using Blowfish.
3. XOR each decrypted block with the evolving IV (a variant of CBC mode) before returning the result as a UTF-8 string.

```java
// Simplified representation of Navicat11Cipher logic
public String decryptString(String ciphertext) {
    byte[] encrypted = parseHexBinary(ciphertext);
    // Initialize Blowfish with SHA-1 hashed DefaultUserKey
    Cipher blowfish = initBlowfishCipher();
    byte[] iv = generateIV(blowfish); // Encrypt 0xFF block
    
    byte[] decrypted = new byte[encrypted.length];
    byte[] previousBlock = iv;
    
    for (int i = 0; i < encrypted.length; i += 8) {
        byte[] block = Arrays.copyOfRange(encrypted, i, i + 8);
        byte[] decryptedBlock = blowfish.update(block);
        // XOR with previous ciphertext block (CBC mode)
        for (int j = 0; j < 8; j++) {
            decrypted[i + j] = (byte) (decryptedBlock[j] ^ previousBlock[j]);
        }
        previousBlock = block;
    }
    return new String(decrypted, StandardCharsets.UTF_8).trim();
}

```

## Navicat 12 and Later AES Decryption

For Navicat 12, 15, and later versions, `Navicat12Cipher` (located at [`chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ncx/cipher/Navicat12Cipher.java`](https://github.com/OtterMind/Chat2DB/blob/main/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/ncx/cipher/Navicat12Cipher.java)) utilizes standard **AES-128 in CBC mode** with PKCS5 padding. This implementation uses fixed, hardcoded key and IV values embedded in the Navicat binary.

### AES Parameters

The decryption relies on these static parameters:
- **Key**: `"libcckeylibcckey"` (16 bytes) wrapped in a `SecretKeySpec`.
- **IV**: `"libcciv libcciv "` (16 bytes) wrapped in an `IvParameterSpec`.
- **Algorithm**: `AES/CBC/PKCS5Padding`.

```java
// Navicat12Cipher implementation
private static final String AES_KEY = "libcckeylibcckey";
private static final String AES_IV = "libcciv libcciv ";

public String decryptString(String ciphertext) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec keySpec = new SecretKeySpec(AES_KEY.getBytes(), "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(AES_IV.getBytes());
    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
    
    byte[] decoded = parseHexBinary(ciphertext);
    byte[] decrypted = cipher.doFinal(decoded);
    return new String(decrypted, StandardCharsets.UTF_8);
}

```

## Practical Decryption Workflow

Putting the components together, the complete workflow for decrypting a connection password from an `.ncx` file looks like this:

```java
import ai.chat2db.community.domain.core.impl.ncx.CipherFactory;
import ai.chat2db.community.domain.core.impl.ncx.cipher.CommonCipher;
import ai.chat2db.community.domain.core.impl.ncx.enums.VersionEnum;

public class PasswordDecryptor {
    public String decryptPassword(String encryptedHex, String navicatVersion) {
        // Select cipher based on export version
        CommonCipher cipher = CipherFactory.get(
            navicatVersion.equals("11") 
                ? VersionEnum.native11.name() 
                : VersionEnum.navicat12more.name()
        );
        
        // Decrypt the hex-encoded password
        return cipher.decryptString(encryptedHex);
    }
}

```

The `CipherFactory.get()` method returns the singleton instance of the requested cipher, which is then used to transform the stored hex string back into the plaintext password required for establishing database connections.

## Summary

- The `CipherFactory` registers `Navicat11Cipher` and `Navicat12Cipher`, selecting the appropriate implementation based on `VersionEnum.native11` or `VersionEnum.navicat12more`.
- `Navicat11Cipher` implements a custom Blowfish decryption routine with a SHA-1 derived key from the static string `"3DC5CA39"` and a dynamically generated IV.
- `Navicat12Cipher` utilizes standard AES/CBC/PKCS5Padding with the fixed key `"libcckeylibcckey"` and IV `"libcciv libcciv "`.
- `TaskNcxImportServiceImpl` orchestrates the import process by extracting version metadata, obtaining the correct cipher, and calling `decryptString()` on hex-encoded passwords from `.ncx` files.

## Frequently Asked Questions

### What encryption algorithm does Navicat 11 use for passwords?

Navicat 11 uses a custom Blowfish implementation with a static key derived from SHA-1 hashing of `"3DC5CA39"`. The algorithm employs a CBC-like mode where the IV is generated by encrypting a block of `0xFF` bytes, and decryption involves XORing blocks with the previous ciphertext block.

### How does Chat2DB determine which cipher to use during import?

Chat2DB examines the version metadata stored within the `.ncx` export file. The `TaskNcxImportServiceImpl` maps this version to `VersionEnum.native11` (for Blowfish) or `VersionEnum.navicat12more` (for AES), then requests the corresponding cipher from the `CipherFactory` using the enum name as the lookup key.

### Is the Navicat 12 encryption key secure?

No. The AES key `"libcckeylibcckey"` and IV `"libcciv libcciv "` are hardcoded constants embedded in the Navicat application binary. This is **obfuscation, not secure encryption**, as anyone with access to the Navicat binary (or this open-source implementation) can decrypt the passwords. Chat2DB uses these known keys to provide import compatibility.

### Can this decryption handle DBWeaver exports as well?

Yes. DBWeaver exports that utilize the `.ncx` format (the same as Navicat) are processed through the same `TaskNcxImportServiceImpl` pathway. The service treats them as Navicat-compatible exports and applies the same version detection and cipher selection logic to decrypt connection passwords.