有两个工具需要用到,很方便
AES在线加密解密工具
JS在线编辑器
1 C++端
1.1 时区问题
因为c++处理事件没有java那么容易,故而经常有时区的问题
Tue, 01 Mar 2022 05:08:40 GMT
,需要转换格式为2022-03-01 13:08:40
const getChinaTime = date =>{
var dateee = new Date(date).toJSON();
return new Date(+new Date(dateee) + 8 * 3600 * 1000)
.toISOString()
.replace(/T/g, " ")
.replace(/\.[\d]{3}Z/, "");
}
1.2 中文字节长度问题
AES加密,补位计算中文是按照3个字节来计算,
function byteLength(str){
var b = 0;
var l = str.length; //初始化字节数递加变量并获取字符串参数的字符个数
if(l) { //如果存在字符串,则执行计划
for(var i = 0; i < l; i ++) { //遍历字符串,枚举每个字符
var c = str.charAt(i);
if (/^[\u0000-\u00ff]$/.test(c)) {
b ++;
} else {
// 中文为3字节
b += 3;
}
}
return b; //返回字节数
} else {
return 0; //如果参数为空,则返回0个
}
}
1.3 AES加、解密
const CryptoJs = require('crypto-js');
const mode = CryptoJs.mode.ECB
const padding = CryptoJs.pad.NoPadding
function encrypt(str, key, iv) {
const flag = isBase64(str);
if (!flag){
str = fillBlank(str.toString())
}
const keyStr = key ? encParse(key) : encParse(defaultKey);
const ivStr = iv ? encParse(iv) : encParse(defaultIv);
const encryptedStr = CryptoJs.AES.encrypt(str, keyStr, {
// iv: ivStr,
mode: mode,
padding: padding
});
// 直接toString()是base64格式的字符串
// ciphertext.toString() 是128位的字符串
return encryptedStr.toString();
}
/**
* 空格补位
* @param {*} p
*/
function fillBlank(p){
if (p%16 != 0){
let nAddCount = 16-byteLength(p)%16;
for (let i=0; i<nAddCount; i++){
p += ' ';
}
}
return p;
}
function decrypt(str, key, iv) {
const keyStr = key ? encParse(key) : encParse(defaultKey);
const ivStr = iv ? encParse(iv) : encParse(defaultIv);
// 判断str是否为base64,如果不是就要转base64,是了就不能再转
const flag = isBase64(str);
if (!flag) {
// 转为base64之前要先转16进制
str = CryptoJs.enc.Hex.parse(str);
// console.log('转为base64之前要先转16进制')
// str = CryptoJs.enc.Base64.parse(str);
// 只有base64格式的字符才能被解密
str = CryptoJs.enc.Base64.stringify(str);
}
2 java
2.1 pkcs#8 和 pkcs#1
PKCS#8密钥格式,多用于JAVA、PHP程序加解密中,为目前用的比较多的密钥、证书格式,也用于微信RSA等程序;
PKCS#1密钥格式,多用于JS等其它程序加解密,属于比较老的格式标准。
这要是比较头大的问题
使用jsrsasign
就没有这个问题,他支持pkcs#8
const jsrsasign = require('jsrsasign')
export function signVerify(src){
// 公钥
let publicKey = 'xx';
let pk = "-----BEGIN PUBLIC KEY-----"+publicKey+"-----END PUBLIC KEY-----";
// 私钥
let privateKey='xx';
let priK = "-----BEGIN PRIVATE KEY-----" +privateKey +"-----END PRIVATE KEY-----";
// 方式1: 先建立 key 对象, 构建 signature 实例, 传入 key 初始化 -> 签名
var key = jsrsasign.KEYUTIL.getKey(priK);
console.log(key);
// 创建 Signature 对象
let signature=new jsrsasign.KJUR.crypto.Signature({alg:"SHA256withRSA"});
// 传入key实例, 初始化signature实例
signature.init(key);
// 传入待签明文
signature.updateString(src);
// 签名, 得到16进制字符结果
let a = signature.sign();
let sign = jsrsasign.hextob64(a);
console.log(sign);
// 验签
// 验签
// !要重新new 一个Signature, 否则, 取摘要和签名时取得摘要不一样, 导致验签误报失败(原因不明)!
let signatureVf = new jsrsasign.KJUR.crypto.Signature({alg:"SHA256withRSA",prvkeypem:pk});
signatureVf.updateString(src);
// !接受的参数是16进制字符串!
let b = signatureVf.verify(jsrsasign.b64tohex(sign));
console.log("jsrsasign verify: "+b);
}
如果要转换也可以通过java来实现的,参考BouncyCastle 密钥转换 - Java