You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java实现Blowfish/CBC可变加密及与在线工具兼容问题

Fixing Blowfish-CBC Encryption to Match codebeautify.org Behavior

I see exactly what's going on here—your code is almost there, but two key pieces are missing to match the website's behavior: random IV handling, and proper packaging of the IV with the ciphertext. Let's walk through this step by step:

1. Why Your Encryption Results Are Not Random

Blowfish in CBC mode produces identical ciphertexts when you use the same plaintext, key, and initialization vector (IV). Your code hardcodes a fixed IV ("12345678"), so every encryption run spits out the same result. To get different ciphertexts each time (while still being able to decrypt back to the original plaintext), you need to generate a random 8-byte IV for every encryption (Blowfish uses an 8-byte block size).

2. How codebeautify.org Handles Encryption

The site follows this standard secure workflow for CBC mode:

  • Generates a random 8-byte IV for each encryption
  • Encrypts the plaintext using Blowfish-CBC-PKCS5Padding with that random IV
  • Concatenates the IV bytes + encrypted ciphertext bytes into a single byte array
  • Encodes this combined array with Base64 to produce the final displayed ciphertext
  • For decryption: Decodes the Base64 string, splits off the first 8 bytes as the IV, then uses that IV to decrypt the remaining bytes

Your error decrypting the site's ciphertext happens because you're using your fixed IV instead of extracting the random IV embedded in the site's ciphertext.

3. Updated Code to Match the Site's Behavior

Here's the revised Crypto class that implements the correct logic:

Encryption Method (Random IV + IV+Ciphertext Packaging)

import javax.crypto.Cipher;
import javax.crypto.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.bind.DatatypeConverter;
import java.security.SecureRandom;

public class Crypto {
    private static final int BLOWFISH_BLOCK_SIZE = 8; // Blowfish uses 8-byte blocks
    private static final String CIPHER_CONFIG = "Blowfish/CBC/PKCS5Padding";

    public static String enc(String content, String key) {
        String encryptedResult = "";
        try {
            // Generate a random 8-byte IV
            byte[] iv = new byte[BLOWFISH_BLOCK_SIZE];
            new SecureRandom().nextBytes(iv);

            // Initialize cipher with random IV
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "Blowfish");
            Cipher cipher = Cipher.getInstance(CIPHER_CONFIG);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));

            // Encrypt the plaintext
            byte[] ciphertext = cipher.doFinal(content.getBytes("UTF-8"));

            // Combine IV and ciphertext into one byte array
            byte[] ivPlusCiphertext = new byte[iv.length + ciphertext.length];
            System.arraycopy(iv, 0, ivPlusCiphertext, 0, iv.length);
            System.arraycopy(ciphertext, 0, ivPlusCiphertext, iv.length, ciphertext.length);

            // Encode to Base64 for final output
            encryptedResult = DatatypeConverter.printBase64Binary(ivPlusCiphertext);
            System.out.println("-- Encrypted -----------");
            System.out.println("-- Result: " + encryptedResult);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return encryptedResult;
    }

Decryption Method (Extract IV from Ciphertext)

public static String dec(String content, String key) {
        String decryptedResult = "";
        try {
            // Decode the Base64 string to get IV + ciphertext bytes
            byte[] ivPlusCiphertext = DatatypeConverter.parseBase64Binary(content);

            // Split into IV (first 8 bytes) and ciphertext (remaining bytes)
            byte[] iv = new byte[BLOWFISH_BLOCK_SIZE];
            byte[] ciphertext = new byte[ivPlusCiphertext.length - BLOWFISH_BLOCK_SIZE];
            System.arraycopy(ivPlusCiphertext, 0, iv, 0, iv.length);
            System.arraycopy(ivPlusCiphertext, iv.length, ciphertext, 0, ciphertext.length);

            // Initialize cipher with extracted IV
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "Blowfish");
            Cipher cipher = Cipher.getInstance(CIPHER_CONFIG);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));

            // Decrypt and convert to plaintext
            byte[] plaintextBytes = cipher.doFinal(ciphertext);
            decryptedResult = new String(plaintextBytes, "UTF-8");
            System.out.println("-- Decrypted -----------");
            System.out.println("-- Result: " + decryptedResult);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return decryptedResult;
    }
}

Test the Code

public class Main {
    public static void main(String[] args) {
        // Test encryption: two runs produce different ciphertexts
        String ciphertext1 = Crypto.enc("Hello", "key123");
        String ciphertext2 = Crypto.enc("Hello", "key123");
        System.out.println("\nTwo different encryption results:");
        System.out.println(ciphertext1);
        System.out.println(ciphertext2);

        // Test decryption: both ciphertexts decrypt to "Hello"
        Crypto.dec(ciphertext1, "key123");
        Crypto.dec(ciphertext2, "key123");

        // Now decrypt the ciphertext from codebeautify.org successfully
        Crypto.dec("08GCpwyZc+qGNuxSvXAD2A==", "key123");
    }
}

4. Confirming the Encoding Type

codebeautify.org uses Base64 encoding for the final output. The reason you didn't get matching results before is that your code only encoded the ciphertext, not the combined IV + ciphertext array. With the updated code, you'll produce Base64 strings in the exact same format as the site.

内容的提问来源于stack exchange,提问作者Chor Wai Chun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:09:42