import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
* AES加解密工具类
* @.Desc AES对称加密算法,调用方法:
* 1) 对明文进行加密,并对密文进行Base64编码:AESUtil.encrypt(plainText, keyStr); plainText为需要加密的字符串,keyStr为密钥。
* 2) 先对密文进行Base64解码,然后再进行解密:AESUtil.decrypt(secretText, keyStr); secretText为需要解密的字符串,keyStr为密钥。
public class AesCbcUtil {
* 默认AES Key
private static final String DEFAULT_AES_KEY_STR = "9815c9e69268bc2fc2085c1lc6q75a42";
private static final String CHARSET = "UTF-8";
private static final String ENCRYPT = "AES";
private static final String ENCRYPT_TYPE = "AES/CBC/PKCS7Padding";
private static final String PROVIDER = "BC";
private static final String IV = "9183296589LSCQEG";
* 加密,并对密文进行Base64编码,采用默认密钥
* @param plainText
* 明文
* @return String
* 做了Base64编码的密文
* @throws Exception
public static String encrypt(String plainText) throws Exception{
return encrypt(plainText, DEFAULT_AES_KEY_STR);
public static IvParameterSpec makeIv() throws UnsupportedEncodingException{
return new IvParameterSpec(IV.getBytes(CHARSET));
* 加密,并对密文进行Base64编码,可指定密钥
* @param plainText
* 明文
* @param keyStr
* 密钥
* @return String
* 做了Base64编码的密文
* @throws Exception
public static String encrypt(String plainText, String keyStr) throws Exception{
try {
byte[] keyBytes = keyStr.getBytes(CHARSET);
Key ckey = new SecretKeySpec(keyBytes, ENCRYPT);
Security.addProvider(new BouncyCastleProvider());
Cipher cp = Cipher.getInstance(ENCRYPT_TYPE,PROVIDER);
IvParameterSpec iv = makeIv();
cp.init(Cipher.ENCRYPT_MODE, ckey,iv);
byte[] inputByteArray = plainText.getBytes(CHARSET);
byte[] cipherBytes = cp.doFinal(inputByteArray);
String result = Base64.encodeBase64String(cipherBytes);
result = result.replace("+", "%2b");
result = result.replace("\r\n", "").replace("\n", "");
return result;
} catch (Exception e) {
throw e;
* 对做了Base64编码的密文进行解密,采用默认密钥
* @param secretText
* 做了Base64编码的密文
* @return String
* 解密后的字符串
* @throws Exception
public static String decrypt(String secretText) throws Exception{
return decrypt(secretText, DEFAULT_AES_KEY_STR);
* 对做了Base64编码的密文进行解密
* @param secretText
* 做了Base64编码的密文
* @param keyStr
* 密钥
* @return String
* 解密后的字符串
* @throws Exception
public static String decrypt(String secretText, String keyStr) throws Exception{
secretText = secretText.replace("%2b", "+");
byte[] cipherByte = Base64.decodeBase64(secretText);
byte[] keyBytes = keyStr.getBytes(CHARSET);
try {
Key ckey = new SecretKeySpec(keyBytes, ENCRYPT);
Security.addProvider(new BouncyCastleProvider());
Cipher cp = Cipher.getInstance(ENCRYPT_TYPE,PROVIDER);
IvParameterSpec iv = makeIv();
cp.init(Cipher.DECRYPT_MODE, ckey,iv);
byte[] decryptBytes = cp.doFinal(cipherByte);
return new String(decryptBytes, CHARSET).replace("", "");
} catch (Exception e) {
throw e;
public static void main(String[] args) {
try {
String content = "hello world";
System.out.println("加密前:" + content);
String encryptResult = encrypt(content);
System.out.println("加密后:" + encryptResult);
String decryptResult = decrypt(encryptResult);
System.out.println("解密后:" + decryptResult);
} catch (Exception ex) {
ex.printStackTrace();
目录Node代码Java代码Node代码/** * 加密,解密方法 * */let crypto = require('crypto');/** * 加密解密方式 */let algorithm = 'aes-256-cbc';let key = '9815c9e69268bc2fc2085c1lc6q75a42';let charset = 'utf8';let cipherEncoding = 'base64';let iv = '9183296589LSCQEG'.
好像jdk1.8.0_162及以后是不需要替换的。
public String encryyptstr(byte[] iv,String key,String text){
String algorithm = "AES";
String transform = "AES/CBC/PKCS5Padding";//
Cipher cipher = null;
String result =
钉钉小程序后台接收钉钉开放平台的回调比较重要,比如通讯录变动的回调,审批流程的回调都是在业务上十分需要的。回调接口时打通钉钉平台和内部系统的重要渠道。
但是给回调的接口增加了一些障碍,它需要支持回调的服务器的接口支持AES-CBC加解密。不然无法成功注册或解析内容。
钉钉官方文档中给出了JAVA,PHP,C#的后台SDK和demo,但是却没有Node服务器的代码支持,这让占有率很高的node服务器非常尴尬,难道node就不能作为钉钉平台的回调服务器么
好在钉钉已经开放了其加密算法,可以通过加密流程自己写一套JavaScript版的加解密程序,然后将node服务器注册为钉钉的回调接口。
// Nodejs encryption with CTR
const crypto = require('crypto');
const algorithm = 'aes-256-cbc';
const keyStr = '2ba27190770c3203a3094b1d212f5e2f'
const ivStr = keyStr.substr(0, 16)
const keyByte = Buffer.from(keyStr)
const
// 密钥长度支持为128/192/256bits。
// 用户密钥长度不足时,平台将以0x00自动填充。
// IV也一样,自动填充,超出部分将被忽略。
// 加密时会将明文数据按16byte进行分组,
真正需要用到的只有一个结构体和三个函数,注释如下:
unsigned char key[32];//密钥字符串,最长32位
unsigned char iv[16];//向量字符串,最长16位
AES_KEY aesKey;//
对称加密算法就是传统的用一个密码进行加密和解密。例如,我们常用的WinZIP和WinRAR对压缩包的加密和解密,就是使用对称加密算法:
从程序的角度看,所谓加密,就是这样一个函数,它接收密码和明文,然后输出密文:
secret = encrypt(key, message);
而解密则相反,它接收密码和密文,然后输出明文:
plain = decrypt(key, secret);
在软件开发中,常用的对称加密算法有:
密钥长度直接决定加密强度,而工作模式和填充模式可以看成是对称加密算法的参数和格式
了解了,您想在前端使用`crypto-js`库对数据进行AES加密,然后在后端使用Node.js的`crypto`模块进行解密。下面是一个示例:
前端加密(使用`crypto-js`库):
```javascript
const CryptoJS = require('crypto-js');
const data = 'exampleData';
const key = 'exampleKey';
const encrypted = CryptoJS.AES.encrypt(data, key).toString();
console.log(encrypted);
在前端,我们使用`CryptoJS.AES.encrypt`方法对数据进行AES加密,并使用指定的密钥(`key`)。最后,我们将加密结果转换为字符串并打印出来。
后端解密(使用Node.js的`crypto`模块):
```javascript
const crypto = require('crypto');
const encryptedData = 'encryptedData';
const key = 'exampleKey';
const decipher = crypto.createDecipheriv('aes-256-cbc', key, '');
let decrypted = decipher.update(encryptedData, 'base64', 'utf8');
decrypted += decipher.final('utf8');
console.log(decrypted);
在后端,我们使用Node.js的`crypto.createDecipheriv`方法创建一个AES算法的解密器,指定算法为`aes-256-cbc`,同时传入密钥(`key`)和空的初始化向量。然后,我们使用解密器的`update`方法将加密数据进行解密,并使用`final`方法获取最终的解密结果。
请注意,确保在前端和后端使用相同的密钥和相同的加密算法(AES)来确保正确的解密结果。