web crypto

需要对网站进行反爬处理

使用浏览器原生的api crypto 进行加密解密

function base64ToUint8Array(base64) {
  const byteString = atob(base64)
  const bytes = new Uint8Array(byteString.length)
  for (let i = 0; i < byteString.length; i++) {
    bytes[i] = byteString.charCodeAt(i)
  }
  return bytes
}

function arrayBufferToBase64(buffer) {
  let binary = ''
  const bytes = new Uint8Array(buffer)
  for (let i = 0; i < bytes.byteLength; i++) {
    binary += String.fromCharCode(bytes[i])
  }
  return btoa(binary)
}

async function importPublicKey(pem) {
  const pemHeader = `-----BEGIN PUBLIC KEY-----`
  const pemFooter = `-----END PUBLIC KEY-----`
  const pemContent = pem
    .replace(pemHeader, '')
    .replace(pemFooter, '')
    .replace(/\n/g, '')
  const publicKeyData = base64ToUint8Array(pemContent)
  const publicKey = await crypto.subtle.importKey(
    'spki',
    publicKeyData,
    {
      name: 'RSA-OAEP',
      hash: 'SHA-256'
    },
    false,
    ['encrypt']
  )
  return publicKey
}

async function importPrivateKey(pem) {
  const pemHeader = `-----BEGIN PRIVATE KEY-----`
  const pemFooter = `-----END PRIVATE KEY-----`
  const pemContent = pem
    .replace(pemHeader, '')
    .replace(pemFooter, '')
    .replace(/\n/g, '')
  const privateKeyData = base64ToUint8Array(pemContent)
  const privateKey = await crypto.subtle.importKey(
    'pkcs8',
    privateKeyData,
    {
      name: 'RSA-OAEP',
      hash: 'SHA-256'
    },
    false,
    ['decrypt']
  )
  return privateKey
}

export async function encryptRSA(plainText, pk) {
  const publicKey = await importPublicKey(pk)
  const encryptedBuffer = await crypto.subtle.encrypt(
    {
      name: 'RSA-OAEP'
    },
    publicKey,
    new TextEncoder().encode(plainText)
  )
  const encrypted = arrayBufferToBase64(encryptedBuffer)
  return encrypted
}

export async function decryptRSA(ciphertext, sk) {
  const privateKey = await importPrivateKey(sk)
  const decryptedBuffer = await crypto.subtle.decrypt(
    {
      name: 'RSA-OAEP'
    },
    privateKey,
    base64ToUint8Array(ciphertext)
  )
  const decrypted = new TextDecoder().decode(decryptedBuffer)
  return decrypted
}

遇到的问题

需要在https的网站上才可以使用,一开始在mdn上没看到这个提示,还以为是依赖重写crypto,绕了半天

测试环境 换成https 就好了 就是麻烦些

本地开发的时候 使用localhost 也是 有crypto这个api的

最后更新于

这有帮助吗?