基于node的RSA加解密

    RSA加解密,可加密的最长明文长度为1024bit,即128字节,但是某段明文长度小于128字节,就需要进行padding,因为如果没有padding,用户无法确分解密后内容的真实长度。由于padding的存在,占用了明文的11字节长度,最后一次能加密的明文长度就变为传说中的117字节。

    附上一段运用js的rsa加解密代码:

    加密:

import { Buffer } from 'buffer'
import { publicEncrypt, constants } from 'crypto'

const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDH/b8R+bDeOArUlvxe7nN1gPTO
oV3YmuwQoqH2B1TjfaADBMzZYnRJg+uBJ0dSYzGBj5yR/6jNNJG9ElM9oIXe4BZ5
YGeAeUmdars9lgdbN3sYf9pV7EZhuu7ClxSC75L0Ni8HlOhHXx6fS2VxN0Y8d5bY
VeuD+WMDoxqaTJt80QIDAQAB
-----END PUBLIC KEY-----`

export const encrypt = origin => {
  const buffer = Buffer.from(encodeURI(JSON.stringify(origin)))
  const blocks = Math.ceil(buffer.length / 117)
  const cipherBuffer = Buffer.alloc(blocks * 128)
  for (let i = 0; i < blocks; i++) {
    const chunk = buffer.slice(i * 117, (i + 1) * 117)
    publicEncrypt({
      key: publicKey,
      padding: constants.RSA_PKCS1_PADDING
    }, chunk).copy(cipherBuffer, i * 128)
  }
  return cipherBuffer.toString('base64')
}

解密:

import { privateDecrypt, constants } from 'crypto'
import { privateKey } from '../config/auth'

const blockDecrypt = block => {
  try {
    const decrypted = privateDecrypt({
      key: privateKey,
      padding: constants.RSA_PKCS1_PADDING
    }, block)
    return decrypted
  } catch (err) {
    if (block.length === 128) {
      return blockDecrypt(block.slice(0, 127))
    }

    throw err
  }
}

export const decrypt = cipher => {
  if (!cipher) {
    throw new Error('ciper cannot be null')
  }

  let rtn = ''

  const buffer = Buffer.from(cipher, 'base64')
  const blocks = Math.ceil(buffer.length / 128)

  for (let i = 0; i < blocks; i++) {
    rtn += blockDecrypt(buffer.slice(i * 128, (i + 1) * 128))
  }

  return decodeURI(rtn)
}

    公钥私钥可以自己随意生成,只要配对就好,这里着重提下,解密时blockDecrypt中的catch,在实际的操作中经常碰到,密文最后一个字符为0,这种情况下,解密就会失败,所以采用catch处理这一情形,保证解密的正常进行。(具体这个最后的0,出现的原因现在还没有很明白)

猜你喜欢

转载自blog.csdn.net/banxia561/article/details/80792232