需求:Java和C#进行数据交互,互相采用AES/CBC/PKCS5Padding进行加解密

Java加密和解密的代码如下:

/**
* 加密 1.构造密钥生成器 2.根据 ecnodeRules 规则初始化密钥生成器 3.产生密钥 4.创建和初始化密码器 5.内容加密 6.返回字符串
* @param encodeRules 密钥规则,类似于密钥
* @param content 待加密内容
* @return
*/
public static String AESEncode(String encodeRules, String content) {
// 初始化向量,必须 16 位
String ivStr = "AESCBCPKCS5Paddi";
try {
// 1.构造密钥生成器,指定为 AES 算法,不区分大小写
KeyGenerator keygen = KeyGenerator.getInstance("AES");
// 新增下面两行,处理 Linux 操作系统下随机数生成不一致的问题
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(encodeRules.getBytes());
keygen.init(128, secureRandom);
// 3.产生原始对称密钥
SecretKey original_key = keygen.generateKey();
// 4.获得原始对称密钥的字节数组
byte[] raw = original_key.getEncoded();
System.out.println(Base64.getEncoder().encodeToString(raw)); // 5.根据字节数组生成 AES 密钥
SecretKey key = new SecretKeySpec(raw, "AES");
// 6.根据指定算法 AES 自成密码器
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的 KEY
//// 指定一个初始化向量 (Initialization vector,IV), IV 必须是 16 位
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivStr.getBytes("UTF-8")));
// 8.获取加密内容的字节数组(这里要设置为 utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
byte[] byte_encode = content.getBytes("utf-8");
// 9.根据密码器的初始化方式--加密:将数据加密
byte[] byte_AES = cipher.doFinal(byte_encode);
// 10.将加密后的数据转换为字符串
// 这里用 Base64Encoder 中会找不到包
// 解决办法:
// 在项目的 Build path 中先移除 JRE System Library,再添加库 JRE System
// Library,重新编译后就一切正常了。
String AES_encode = new String(Base64.getEncoder().encode(byte_AES));
// 11.将字符串返回
return AES_encode;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
// 如果有错就返加 nulll
return null;
} /**
* 解密 解密过程: 1.同加密1-4步 2.将加密后的字符串反纺成byte[]数组 3.将加密内容解密
* @param encodeRules 密钥规则,类似于密钥
* @param content 待加密内容
* @return
*/
public static String AESDecode(String encodeRules, String content) {
// 初始化向量,必须16位
String ivStr = "AESCBCPKCS5Paddi";
try {
// 1.构造密钥生成器,指定为AES算法,不区分大小写
KeyGenerator keygen = KeyGenerator.getInstance("AES");
// 新增下面两行,处理 Linux 操作系统下随机数生成不一致的问题
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(encodeRules.getBytes());
keygen.init(128, secureRandom);
// 3.产生原始对称密钥
SecretKey original_key = keygen.generateKey();
// 4.获得原始对称密钥的字节数组
byte[] raw = original_key.getEncoded();
// 5.根据字节数组生成AES密钥
SecretKey key = new SecretKeySpec(raw, "AES");
// 6.根据指定算法AES自成密码器
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
// 7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
//// 指定一个初始化向量 (Initialization vector,IV), IV 必须是16位
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivStr.getBytes("UTF-8")));
// 8.将加密并编码后的内容解码成字节数组
byte[] byte_content = Base64.getDecoder().decode(content);
/*
* 解密
*/
byte[] byte_decode = cipher.doFinal(byte_content);
String AES_decode = new String(byte_decode, "utf-8");
return AES_decode;
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
// 如果有错就返加nulll
return null;
}

这里面有一个情况,就是构建密钥生成器,C#里面有一个类库BouncyCastle.Crypto.dll完全可以把Java的代码翻译过来,但是翻译过来就卡在了密钥生成器这里,大家可以百度“java SecureRandom”就会知道其中的原因。后来通过不断查找资料并参考了:https://www.cnblogs.com/sheng9hhd/articles/11125705.html

最终实现了如下的C#加解密代码:

public class AESHelper
{
/// <summary>
/// 用种子获取密钥字节
/// </summary>
/// <param name="strKey">密钥种子</param>
/// <param name="encoding">编码格式</param>
/// <param name="nLen">密钥长度(一般为16,不清楚时不要随意动)</param>
/// <returns></returns>
public static byte[] GetKeyBySeed(string strKey, Encoding encoding,int nLen =)
{
byte[] bySeed = encoding.GetBytes(strKey);
byte[] byKeyArray = null;
using (var st = new SHA1CryptoServiceProvider())
{
using (var nd = new SHA1CryptoServiceProvider())
{
var rd = nd.ComputeHash(st.ComputeHash(bySeed));
byKeyArray = rd.Take(nLen).ToArray();
}
}
return byKeyArray;
} /// <summary>
/// 加密 参数:string
/// </summary>
/// <param name="strCon">加密内容</param>
/// <param name="byteKey">密钥字节数组</param>
/// <param name="strIv">向量(注意目前只研究支持16位长度)</param>
/// <param name="encoding">编码方式</param>
/// <returns>string:密文</returns>
public static string Encrypt(string strCon, byte[] byteKey, string strIv, Encoding encoding)
{
try
{
if (string.IsNullOrWhiteSpace(strCon))
{
return null;
} byte[] byCon = encoding.GetBytes(strCon);
var rm = new RijndaelManaged
{
IV = encoding.GetBytes(strIv),
Key = byteKey,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(byCon, , byCon.Length);
return Convert.ToBase64String(resultArray, , resultArray.Length);
}
catch
{
return "";
}
} public static string Decrypt(string strCon, byte[] byteKey, string strIv, Encoding encoding)
{
try
{
if (string.IsNullOrWhiteSpace(strCon))
{
return null;
} byte[] byCon =Convert.FromBase64String(strCon);
var rm = new RijndaelManaged
{
IV = encoding.GetBytes(strIv),
Key = byteKey,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
};
ICryptoTransform cTransform = rm.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(byCon, , byCon.Length);
return encoding.GetString(resultArray);
}
catch
{
return "";
}
} }

上面的C#代码和Java代码可以实现互相加解密,同时也要感谢我的同事”陈江”的鼎立支持。

AES加密(java和C#)的更多相关文章

  1. AES加密解密通用版Object-C / C# / JAVA

    1.无向量 128位 /// <summary> /// AES加密(无向量) /// </summary> /// <param name="plainByt ...

  2. Java aes加密C#解密的取巧方法

    摘要: 项目开发过程中遇到一个棘手的问题:A系统使用java开发,通过AES加密数据,B系统使用C#开发,需要从A系统获取数据,但在AES解密的时候遇到麻烦.Java的代码和C#的代码无法互通. Ja ...

  3. [Java 实现AES加密解密]

    今天同学请教我这个问题,被坑了次…… 实现的功能是2个Java类:一个读取源文件生成加密文件,另一个类读取加密文件来解密. 整个过程其实很简单,java有AES的工具包,设好秘钥,设好输入内容,就得到 ...

  4. PHP、Java对称加密中的AES加密方法

    PHP AES加密 <?php ini_set('default_charset','utf-8'); class AES{ public $iv = null; public $key = n ...

  5. C#, Java, PHP, Python和Javascript几种语言的AES加密解密实现[转载]

    原文:http://outofmemory.cn/code-snippet/35524/AES-with-javascript-java-csharp-python-or-php c#里面的AES加密 ...

  6. Java 环境下使用 AES 加密的特殊问题处理

    在 Java 环境下使用 AES 加密,在密钥长度和字节填充方面有一些比较特殊的处理. 1. 密钥长度问题 默认 Java 中仅支持 128 位密钥,当使用 256 位密钥的时候,会报告密钥长度错误 ...

  7. Java AES加密

    Java AES 加密 加密 /** * * @description 加密 * * @param content 需要加密的内容 * @param password 加密密码 * @return * ...

  8. android开发 java与c# 兼容AES加密

    由于android客户端采用的是AES加密,服务器用的是asp.net(c#),所以就造成了不一致的加密与解密问题,下面就贴出代码,已经试验过. using System; using System. ...

  9. Php AES加密、解密与Java互操作的问题

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...

随机推荐

  1. Vue中在组件销毁时清除定时器(setInterval)

    在mounted中创建并执行定时器,然后在beforeDestroy或者destroyed中清除定时器 <template> <div class="about" ...

  2. P1462 通往奥格瑞玛的道路[最短路+二分+堆优化]

    题目来源:洛谷 题目背景 在艾泽拉斯大陆上有一位名叫歪嘴哦的神奇术士,他是部落的中坚力量 有一天他醒来后发现自己居然到了联盟的主城暴风城 在被众多联盟的士兵攻击后,他决定逃回自己的家乡奥格瑞玛 题目描 ...

  3. Selenium(十五)cookie

    有时候我们需要验证浏览器中是否存在某个 cookie,因为基于真实的 cookie 的测试是无法通过集成测试完成的.WebDriver 提供了操作 Cookie 的相关方法可以读取.添加和删除 coo ...

  4. [TypeScript] vs code TSLint常见错误解决方案

    TSLint是一个Typescrip{过滤}t验证工具,用于检测代码. TSLint: comment must start with a space (comment-format) 注释必须从一个 ...

  5. pid 及参数调试方法

    所谓PID指的是Proportion-Integral-Differential.翻译成中文是比例-积分-微分. 记住两句话: 1.PID是经典控制(使用年代久远) 2.PID是误差控制() 对直流电 ...

  6. [NOIP 2018]旅行

    题目链接 题意简介:现有一个图,小Y要把它走完,每个点只去一次,路径字典序最小. 分析:这道题我认为很重要的一个点就是它的数据范围.它只有两种 m=n-1 或 m=n.我们先考虑第一种:m=n-1也就 ...

  7. sql server 交集,差集的用法 (集合运算)

    概述 为什么使用集合运算: 在集合运算中比联接查询和EXISTS/NOT EXISTS更方便. 并集运算(UNION) 并集:两个集合的并集是一个包含集合A和B中所有元素的集合. 在T-SQL中.UN ...

  8. ICPC 2019-2020 North-Western Russia Regional Contest

    目录 Contest Info Solutions Problem A. Accurate Movement Problem B. Bad Treap Problem E. Equidistant P ...

  9. [转]引用模板类中定义的类型(用typedef或using)以及auto、decltype、typename的使用

    一.背景 使用typedef或者using定义类型别名是非常常见的手段,在c++里面,有时为了封装性,模块性等原因还会在某一个namespace或者class内部定义类型别名. 最近在写c++代码的时 ...

  10. 搭建自己的博客(十七):添加每日阅读量并使用highcharts通过图表显示

    之前写了单篇博客的阅读量统计,今天添加了博客总阅读量统计,并且使用highcharts图表显示. 1.变化的部分