RSA 加密解密

顾正初
2023-12-01

 RSA是一种块加密的算法,所以对于明文需要将他们分成固定的块长度,考虑到输入的数据长度的问题,所以加解密的填充有好几种:

  1. 无填充,就是直接对明文进行加密

  2. PKCS1。将数据长度分成密钥长度-11byte,比如密钥是1024bit,那么长度就是1024/8-11=117bytes,具体的格式:先填0,2,然后随机生成其他的byte,后面才是真正的数据

  3. PKCS1_OAEP将数据长度分成密钥长度-41byte,比如密钥是1024bit,那么长度就是1024/8-41=77bytes,先填0,随机或者是固定的测试向量加20个bytes,然后加20个数字签名的数据,最后才是数据

  4. SSLV23,将数据长度分成密钥长度-11byte,比如密钥是1024bit,那么长度就是1024/8-11=117bytes,具体的格式:先填0,2,填入8个3,填入一个'\0',最后才是真正的数据。

1、前端

//在node-rsa模块中加解密默认使用 pkcs1_oaep填充方式 ,而在js中加密解密默认使用的是 pkcs1  
encrypt(text: string) {
    let rsa = new NodeRSA(this.key,'pkcs8-public-pem');
    rsa.setOptions({encryptionScheme: 'pkcs1'}) //和后端的填充模式要一致
    let res = rsa.encrypt(text, "base64");
    return res;
  }
  decrypt(text: string) {
    let rsa = new NodeRSA(this.key, 'pkcs8-private-pem');
    rsa.setOptions({encryptionScheme: 'pkcs1'}) //和后端的填充模式要一致
    return rsa.decrypt(text,"utf8");
  }

2、后端

异常

javax.crypto.IllegalBlockSizeException: Data must not be longer than 128 bytes

处理:超长问题需要分组处理

异常

javax.crypto.BadPaddingException: Decryption error

 处理:填充问题

  private static byte[] rsaGroupFinal(Cipher cipher, int opmode, byte[] inputArray) throws Exception{
        // 最大加密字节数,超出最大字节数需要分组加密
        int MAX_ENCRYPT_BLOCK = Cipher.DECRYPT_MODE == opmode ? 128 : 117; //解密最大长度128,加密最大长度117,不够会被填充报错
        // 标识
        int offSet = 0;
        byte[] resultBytes = {};
        byte[] cache = {};
        int inputLength = inputArray.length;
        while (inputLength - offSet > 0) {
            if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK);
                offSet += MAX_ENCRYPT_BLOCK;
            } else {
                cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                offSet = inputLength;
            }
            resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
            System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
        }
        return resultBytes;
    }

参考:

Decryption error

 类似资料: