js与后端联调加解密的麻烦

有两个工具需要用到,很方便
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

warrah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值