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

请求协助:将VB.NET的RijndaelManaged加密代码转Java

VB.NET RijndaelManaged to Java Compatible Conversion

I've worked through converting VB.NET's RijndaelManaged encryption/decryption functions to Java while maintaining full compatibility. The key to getting this right is matching every single parameter and behavior from the VB code—small mismatches (like encoding or key derivation order) will break compatibility.

Core Compatibility Notes First

Before diving into code, let's align on the critical details your VB.NET code is likely using (adjust if your actual VB settings differ):

  • Key Derivation: Uses Rfc2898DeriveBytes (PBKDF2 with HMAC-SHA1) with a fixed salt and iteration count
  • Cipher Settings: BlockSize=256, KeySize=256, Mode=CBC, Padding=PKCS7
  • Encoding: VB's Encoding.UTF8 (or Encoding.Unicode—we'll note how to adjust this)
  • IV Generation: Derived from the same Rfc2898DeriveBytes instance as the key (not a separate one)

Java Implementation (With BouncyCastle for 256-bit Block Size)

Java's standard library doesn't support Rijndael with 256-bit block sizes (only AES 128-bit blocks), so we use BouncyCastle for full compatibility.

Step 1: Add BouncyCastle Dependency

For Maven, add this to your pom.xml:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>

Step 2: Complete Java Class

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Security;
import java.util.Base64;

public class ClRijndaelManaged {

    static {
        // Register BouncyCastle as a security provider
        Security.addProvider(new BouncyCastleProvider());
    }

    // Replace these values with EXACT matches from your VB.NET code
    private static final byte[] SALT = Base64.getDecoder().decode("VGVzdFNhbHQ="); // Match VB's Convert.FromBase64String("your-salt")
    private static final int ITERATION_COUNT = 1000; // Match VB's Rfc2898DeriveBytes iteration count
    private static final int KEY_SIZE = 256; // Match VB's KeySize
    private static final int BLOCK_SIZE = 256; // Match VB's BlockSize

    /**
     * Equivalent to VB.NET's fncVerschluesseln
     */
    public static String encrypt(String plainText, String password) throws Exception {
        // Derive combined key + IV bytes (matches VB's sequential GetBytes calls)
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), SALT, ITERATION_COUNT, KEY_SIZE + BLOCK_SIZE);
        byte[] keyIvBytes = factory.generateSecret(spec).getEncoded();

        // Split into key and IV (VB gets key first, then IV)
        byte[] keyBytes = new byte[KEY_SIZE / 8];
        byte[] ivBytes = new byte[BLOCK_SIZE / 8];
        System.arraycopy(keyIvBytes, 0, keyBytes, 0, keyBytes.length);
        System.arraycopy(keyIvBytes, keyBytes.length, ivBytes, 0, ivBytes.length);

        // Initialize Rijndael cipher (CBC mode + PKCS7 padding)
        Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS7Padding", "BC");
        SecretKey secretKey = new SecretKeySpec(keyBytes, "Rijndael");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);

        // Encrypt and encode to Base64 (matches VB's Convert.ToBase64String)
        byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8);
        // IF your VB code uses Encoding.Unicode, replace with StandardCharsets.UTF_16LE
        byte[] encryptedBytes = cipher.doFinal(plainBytes);
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * Equivalent to VB.NET's fncEntschluesseln
     */
    public static String decrypt(String encryptedText, String password) throws Exception {
        // Derive key + IV exactly like encryption (critical for compatibility)
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), SALT, ITERATION_COUNT, KEY_SIZE + BLOCK_SIZE);
        byte[] keyIvBytes = factory.generateSecret(spec).getEncoded();

        byte[] keyBytes = new byte[KEY_SIZE / 8];
        byte[] ivBytes = new byte[BLOCK_SIZE / 8];
        System.arraycopy(keyIvBytes, 0, keyBytes, 0, keyBytes.length);
        System.arraycopy(keyIvBytes, keyBytes.length, ivBytes, 0, ivBytes.length);

        // Initialize decryptor
        Cipher cipher = Cipher.getInstance("Rijndael/CBC/PKCS7Padding", "BC");
        SecretKey secretKey = new SecretKeySpec(keyBytes, "Rijndael");
        IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);

        // Decode Base64 and decrypt
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes, StandardCharsets.UTF_8);
        // Again, use UTF_16LE if VB used Encoding.Unicode
    }

    // Test compatibility with your VB.NET output
    public static void main(String[] args) {
        try {
            String testPassword = "your-test-password";
            String testPlainText = "Hello from VB.NET!";
            String encrypted = encrypt(testPlainText, testPassword);
            System.out.println("Encrypted (Java): " + encrypted);
            String decrypted = decrypt(encrypted, testPassword);
            System.out.println("Decrypted (Java): " + decrypted);

            // Compare 'encrypted' to the output of your VB fncVerschluesseln—they should match exactly
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

If Your VB Code Uses 128-bit Block Size (AES Compatible)

If your VB.NET RijndaelManaged.BlockSize = 128 (the default), you can skip BouncyCastle entirely. Modify these parts:

  1. Remove the BouncyCastle dependency and Security.addProvider call
  2. Change BLOCK_SIZE = 128
  3. Update cipher initialization to use standard AES:
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
    

PKCS5 padding works here because Java's PKCS5Padding implementation correctly handles PKCS7 padding for AES 128-bit blocks.

Common Mistakes That Break Compatibility

Your original Java code likely failed due to one or more of these:

  1. Wrong Key/IV Derivation: Generating key and IV from separate PBKDF2 instances (VB uses the same instance sequentially)
  2. Mismatched Block Size: Using Java's default AES 128-bit blocks while VB uses 256-bit
  3. Encoding Mismatch: Using UTF-8 in Java but Encoding.Unicode (UTF-16LE) in VB
  4. Incorrect Padding: Using NoPadding or ISO10126Padding instead of PKCS7/PKCS5
  5. Wrong Hash Algorithm: Using PBKDF2 with HMAC-SHA256 instead of SHA1 (VB's Rfc2898DeriveBytes defaults to SHA1)

Test with a known plaintext/password pair—if the encrypted string matches between VB and Java, decryption will work perfectly.

内容的提问来源于stack exchange,提问作者C.B.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:05:01