JAVA的AES加密解密代码, 转为NET CORE后解密出来的是乱码?

网友给的JAVA的AES加密解密代码,自己想转为NET CORE的,通过AI转出来了,自己加密解密也成,不过用JAVA代码里的解密示例失败,解出来的是乱码,但是在JAVA那边又是正确的,请问应该怎么解决?
JAVA代码:


import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
 
 public class HelloWorld {

    public static String AESCFBencrypt(String token, String price) throws Exception {
        byte[] tokenBytes = token.getBytes(StandardCharsets.UTF_8);
        byte[] datePrice = java.util.Base64.getUrlEncoder().encode(price.getBytes(StandardCharsets.UTF_8));
        byte[] ciphertext = encrypt(tokenBytes, datePrice);
        return java.util.Base64.getUrlEncoder().encodeToString(ciphertext);
    }

    public static String decode(String token, String text) throws Exception {
        byte[] key = token.getBytes(StandardCharsets.UTF_8), value = Base64.getUrlDecoder().decode(text);
        byte[] result = AESCFBdecrypt(key, value);
        return new String(result);
    }

    public static byte[] encrypt(byte[] key, byte[] text) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");
        byte[] iv = new byte[cipher.getBlockSize()];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);

        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);

        byte[] encryptedText = cipher.doFinal(text);

        // Combine the IV and encrypted text
        byte[] ciphertext = new byte[iv.length + encryptedText.length];
        System.arraycopy(iv, 0, ciphertext, 0, iv.length);
        System.arraycopy(encryptedText, 0, ciphertext, iv.length, encryptedText.length);

        return ciphertext;
    }

    /**
     * 解密
     *
     * @param key
     * @param text
     * @return
     * @throws Exception
     */
    public static byte[] AESCFBdecrypt(byte[] key, byte[] text) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher = Cipher.getInstance("AES/CFB/NoPadding");

        byte[] iv = new byte[cipher.getBlockSize()];
        System.arraycopy(text, 0, iv, 0, 16);

        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));

        byte[] ciphertext = new byte[text.length - 16];
        System.arraycopy(text, 16, ciphertext, 0, text.length - 16);

        byte[] decryptedText = cipher.doFinal(ciphertext);
        return java.util.Base64.getDecoder().decode(new String(decryptedText));
    }

    public static void main(String[] args) {
        try {
            String token = "cd9f4d2ca833a29097b8af0bae8dff69"; //密钥
            String str = AESCFBencrypt(token, "222"); //加密字符串222
            System.out.println(str);
            str = "y_Npr5GG3bLju4UDJzerZkgGmSM"; //解密出来的结果是222,用C#的解出来的是乱码
            System.out.println(decode(token, str));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

C#代码:

using System;
using System.Buffers.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;

namespace Niunan.Tool.Util
{

    public class AESHelper
    {
        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="token">32位密钥</param>
        /// <param name="price">需要加密的文本</param>
        /// <returns></returns>
        public static string AesCfbEncrypt(string token, string price)
        {
            byte[] tokenBytes = Encoding.UTF8.GetBytes(token);
            byte[] datePrice = Encoding.UTF8.GetBytes(price);
            byte[] ciphertext = encrypt(tokenBytes, datePrice);



            // 转换为Base64字符串
            string base64Encoded = Convert.ToBase64String(ciphertext);

            // 替换URL不安全的字符
            return base64Encoded.Replace('+', '-').Replace('/', '_').TrimEnd('=');
        }
        public static byte[] encrypt(byte[] key, byte[] text)
        {
            using (Aes aesAlg = Aes.Create())
            {
                // 设置加密密钥
                aesAlg.Key = key;
                aesAlg.Mode = CipherMode.CFB; // 注意:C#中没有直接的“CFB/NoPadding”模式,这里使用最接近的CFB模式。
                aesAlg.Padding = PaddingMode.None;

                // 生成初始化向量(IV)
                aesAlg.GenerateIV();

                // 创建加密器
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // 加密文本
                byte[] encryptedText;
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    // 将IV写入输出流的开头
                    msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        csEncrypt.Write(text, 0, text.Length);
                        csEncrypt.FlushFinalBlock();
                        encryptedText = msEncrypt.ToArray();
                    }
                }

                return encryptedText;
            }
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="token">32位密钥</param>
        /// <param name="text">要解密的文本</param>
        /// <returns></returns>
        public static string AesCfbDecrypt(string token, string text)
        {
            byte[] key = Encoding.UTF8.GetBytes(token), value = Decode(text);
            byte[] result =  Decrypt(key, value);
            return Encoding.UTF8.GetString(result);

        }

        /// <summary>
        /// JAVA的Base64.getUrlDecoder().decode方法
        /// </summary>
        /// <param name="base64UrlEncoded"></param>
        /// <returns></returns>
        public static byte[] Decode(string base64UrlEncoded)
        {
            // 将URL安全的Base64字符串转换回标准的Base64字符串
            string base64Encoded = base64UrlEncoded.Replace('-', '+').Replace('_', '/');

            // 添加可能缺失的填充字符
            switch (base64Encoded.Length % 4)
            {
                case 2: base64Encoded += "=="; break;
                case 3: base64Encoded += "="; break;
            }

            // 转换回字节数组
            byte[] bytes = Convert.FromBase64String(base64Encoded);

            return bytes;
        }

        public static byte[] Decrypt(byte[] key, byte[] text)
        {
            using (Aes aesAlg = Aes.Create())
            {
                // 设置加密密钥
                aesAlg.Key = key;
                aesAlg.Mode = CipherMode.CFB; // 注意:这里我们尽可能模拟原始的CFB模式
                aesAlg.Padding = PaddingMode.None;

                // 提取IV(前16字节)
                byte[] iv = new byte[aesAlg.BlockSize / 8];
                Buffer.BlockCopy(text, 0, iv, 0, iv.Length);

                // 创建解密器
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, iv);

                // 解密文本
                using (MemoryStream msDecrypt = new MemoryStream())
                {
                    // 跳过IV部分
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write))
                    {
                        // 写入实际的加密数据
                        csDecrypt.Write(text, iv.Length, text.Length - iv.Length);
                        csDecrypt.FlushFinalBlock();

                        // 获取解密后的数据并进行Base64解码
                        byte[] decryptedText = msDecrypt.ToArray();
                        return decryptedText;
                    }
                }
            }
        }
    }
}

具体也可看http://tool.niunan.net/aesdemo/index

通过AI试过很多,都不行。

阅读 456
1 个回答

在大神网友的帮忙下解决了,他那个给的示例串需要再次base64解码
下面是代码,需要引入第三方nuget包:BouncyCastle.Cryptography

//NUGET下载第三方类库 BouncyCastle.Cryptography
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using System.Text;

namespace ConsoleApp1
{
    internal class Program
    {
        private const int BlockSize = 16; // AES 块大小为128位(16字节)

        static void Main(string[] args)
        {
            string key = "cd9f4d2ca833a29097b8af0bae8dff69";
            string data = "222";

            // 加密
            string encrypted = EncryptString(key, data);
            Console.WriteLine($"字符串[{data}]加密结果: {encrypted}");

            // 解密
            string decrypted = DecryptString(key, encrypted);
            Console.WriteLine($"字符串[{encrypted}]解密结果: {decrypted}");

            // 固定解密
            encrypted = "y_Npr5GG3bLju4UDJzerZkgGmSM";
            decrypted = DecryptString(key, encrypted);
            Console.WriteLine($"字符串【{encrypted}】解密结果: {decrypted}");
            decrypted = Encoding.UTF8.GetString(Base64UrlDecode(decrypted));
            Console.WriteLine($"把上面的再Base64解码得到: {decrypted}");
        }


        public static byte[] Encrypt(byte[] key, byte[] data)
        {
            // 创建 AES/CFB/NoPadding
            IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CFB/NoPadding");

            // 生成随机IV
            byte[] iv = new byte[BlockSize];
            SecureRandom random = new SecureRandom();
            random.NextBytes(iv);

            // 初始化加密器
            cipher.Init(true, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", key), iv));

            // 加密数据
            byte[] encryptedData = cipher.DoFinal(data);

            // 组合IV和加密数据
            byte[] result = new byte[iv.Length + encryptedData.Length];
            Array.Copy(iv, 0, result, 0, iv.Length);
            Array.Copy(encryptedData, 0, result, iv.Length, encryptedData.Length);

            return result;
        }

        public static byte[] Decrypt(byte[] key, byte[] encryptedData)
        {
            // 提取IV
            byte[] iv = new byte[BlockSize];
            Array.Copy(encryptedData, 0, iv, 0, BlockSize);

            // 提取密文
            byte[] cipherText = new byte[encryptedData.Length - BlockSize];
            Array.Copy(encryptedData, BlockSize, cipherText, 0, cipherText.Length);

            // 创建 AES/CFB/NoPadding
            IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CFB/NoPadding");

            // 初始化解密器
            cipher.Init(false, new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", key), iv));

            // 解密数据
            return cipher.DoFinal(cipherText);
        }

        // Base64URL编码
        public static string Base64UrlEncode(byte[] data)
        {
            return Convert.ToBase64String(data)
                .TrimEnd('=')
                .Replace('+', '-')
                .Replace('/', '_');
        }

        // Base64URL解码
        public static byte[] Base64UrlDecode(string base64Url)
        {
            string base64 = base64Url
                .Replace('-', '+')
                .Replace('_', '/');

            switch (base64.Length % 4)
            {
                case 2: base64 += "=="; break;
                case 3: base64 += "="; break;
            }

            return Convert.FromBase64String(base64);
        }

        // 字符串加密
        public static string EncryptString(string key, string data)
        {
            try
            {
                byte[] keyBytes = Encoding.UTF8.GetBytes(key);
                byte[] dataBytes = Encoding.UTF8.GetBytes(data);
                byte[] encrypted = Encrypt(keyBytes, dataBytes);
                return Base64UrlEncode(encrypted);
            }
            catch (Exception ex)
            {
                throw new Exception("加密失败", ex);
            }
        }

        // 字符串解密
        public static string DecryptString(string key, string encryptedData)
        {
            try
            {
                byte[] keyBytes = Encoding.UTF8.GetBytes(key);
                byte[] encryptedBytes = Base64UrlDecode(encryptedData);
                byte[] decrypted = Decrypt(keyBytes, encryptedBytes);
                return Encoding.UTF8.GetString(decrypted);
            }
            catch (Exception ex)
            {
                throw new Exception("解密失败", ex);
            }
        }
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进