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

C#与Java同加密算法输出不一致,如何实现输出统一?

问题:C#与Java AES加密结果不一致

将C#的密码加密代码转为Java后,两者生成的加密字符串无法匹配。输入密码为Hello World2时:

  • C#输出:orc_Aup5rLQZ_vB5atFuqw2
  • Java输出:orc_Aup5rLQZ_vB5atFuqw==

需要调整Java代码,使其输出与C#一致。

C# 原加密代码
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace Crypto.Client
{
    /// <summary>
    ///     Helper functions to encrypt and decrypt stuff
    /// </summary>
    public static class CryptoHelper
    {
        private static readonly byte[] Key =
        {
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12,
            0x13, 0x14, 0x15, 0x16
        };

        private static readonly byte[] InitializationVector =
        {
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
        };

        //Encrypts the input string using a .net function.
        public static string Encrypt(string plainText)
        {
            var rmCrypto = new RijndaelManaged();
            using (var memoryStream = new MemoryStream())
            {
                using (
                    var cryptoStream = new CryptoStream(
                        memoryStream, rmCrypto.CreateEncryptor(Key, InitializationVector), CryptoStreamMode.Write))
                {
                    using (var streamWiter = new StreamWriter(cryptoStream))
                    {
                        streamWiter.Write(plainText);
                    }
                }
                return HttpServerUtility.UrlTokenEncode(memoryStream.ToArray());
            }
        }
    }
}
Java 原加密代码
public class CryptoHelper
{
    private static final byte[] Key =
    {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12,
        0x13, 0x14, 0x15, 0x16
    };

    private static final byte[] InitializationVector =
    {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
    };
    
    public static String Encrypt(String plainText) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(Key, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(InitializationVector);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        CipherOutputStream cryptoStream = new CipherOutputStream(outputStream, cipher);
        cryptoStream.write(plainText.getBytes("UTF-8"));
        cryptoStream.close();
        
        byte[] encryptedBytes = outputStream.toByteArray();

        
        return Base64.getUrlEncoder().encodeToString(encryptedBytes);
    }
}
解决方案

差异根源在于Base64编码的处理规则不同:

  • C#的HttpServerUtility.UrlTokenEncode是微软自定义的URL安全Base64:
    1. 先做标准Base64编码
    2. 把+替换为-,/替换为_
    3. 去掉末尾的=,并在最后添加一个数字表示去掉的=数量(比如2代表去掉了2个=)
  • Java的Base64.getUrlEncoder()是标准URL安全Base64:仅替换+为-、/为_,保留末尾的=

要让Java输出与C#一致,需实现相同的URL Token编码逻辑,修改后的Java代码如下:

import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.util.Base64;

public class CryptoHelper
{
    private static final byte[] Key =
    {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12,
        0x13, 0x14, 0x15, 0x16
    };

    private static final byte[] InitializationVector =
    {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
    };
    
    public static String Encrypt(String plainText) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec keySpec = new SecretKeySpec(Key, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(InitializationVector);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        CipherOutputStream cryptoStream = new CipherOutputStream(outputStream, cipher);
        cryptoStream.write(plainText.getBytes("UTF-8"));
        cryptoStream.close();
        
        byte[] encryptedBytes = outputStream.toByteArray();

        // 实现与C# HttpServerUtility.UrlTokenEncode一致的逻辑
        String base64Url = Base64.getUrlEncoder().withoutPadding().encodeToString(encryptedBytes);
        int paddingCount = (4 - (encryptedBytes.length % 4)) % 4;
        return base64Url + paddingCount;
    }
}

代码说明:

  1. 使用Base64.getUrlEncoder().withoutPadding()生成不带末尾=的URL安全Base64字符串
  2. 计算原本需要的=数量(paddingCount),并将这个数字追加到字符串末尾
  3. 处理后Java输出将与C#的UrlTokenEncode结果完全一致

内容的提问来源于stack exchange,提问作者Rajesh Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:34:52