网友给的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试过很多,都不行。
在大神网友的帮忙下解决了,他那个给的示例串需要再次base64解码
下面是代码,需要引入第三方nuget包:BouncyCastle.Cryptography