首页 > 其他分享 >前端RSA密钥生成和加解密——window.crypto使用相关

前端RSA密钥生成和加解密——window.crypto使用相关

时间:2024-08-03 14:33:00浏览次数:7  
标签:const 加解密 RSA crypto window ----- subtle

转自简书,原文地址,本文介绍window.crypto关于RSA方面的API。


crypto API支持常用的rsa、aes加解密,这边介绍rsa的应用。

浏览器兼容性

window.crypto需要chrome 37版本,ie 11,safari 11才支持全部API而基本的加解密在safari 7就可以。

生成公私钥

crypto.subtle.generateKey(algorithm, extractable, keyUsages),其中:
1.algorithm参数根据不同算法填入对应的参数对,rsa需要填入RsaHashedKeyGenParams对象包含有:

  • name,可选RSASSA-PKCS1-v1_5, RSA-PSS, or RSA-OAEP,这边如果用于加解密是不支持旧的RSAES-PKCS1-v1_5的(jsencrypt.js支持),RSASSA-PKCS1-v1_5用于签名

  • modulusLength,为rsa位数,推荐至少2048位(相当于112位的aes)才能较为安全,此参数最为影响性能,比如1024比2048快非常多,NIST建议目前的RSA秘钥安全强度是2048位,如果需要工作到2030年之后,就使用3072位的秘钥

  • publicExponent,一般直接为[0x01, 0x00, 0x01]

  • hash,摘要方式,可选SHA-256SHA-384SHA-512,这边也允许SHA-1,但是因为其安全性所以基本不建议

2.extractable一般是true,表示是否允许以文本的方式导出key

3.keyUsages是一个数组,里面可选encryptdecryptsign

window.crypto.subtle.generateKey(
    {
        name: "RSA-OAEP",
        modulusLength: 2048,
        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
        hash: {
            name: "SHA-512" // 这边如果后端使用公钥加密,要注意与前端一致
        },
    },
    true,
    ["encrypt", "decrypt"] // must be ["encrypt", "decrypt"] or ["wrapKey", "unwrapKey"]
)

函数结果返回一个promise对象,如果是对称加密会得到一个密钥CryptoKey类型,这边rsa会得到一个密钥对CryptoKeyPair,它有2个CryptoKey成员,privateKeypublicKey,我们导出密钥为文本或者加解密都将通过这2个成员对象。

导出公私钥

window.crypto.subtle.exportKey(format, key),其中:
1.format可选rawpkcs8spkijwk,我们这边在导出公钥时选spki,私钥选pkcs8

2.key就是上面CryptoKeyPairprivateKey或者publicKey
函数返回一个promise对象,结果是一个ArrayBuffer,这边转成pem风格。

// 导出私钥
 window.crypto.subtle.exportKey(
    "pkcs8", // 公钥的话这边填spki
    key.privateKey // 公钥这边是publicKey
).then(function(keydata2) {
    let privateKey = RSA2text(keydata1, 1) // 私钥pem
}).catch(function(err) {
    console.error(err)
})
// pem格式文本
function RSA2text(buffer, isPrivate = 0) {
    let binary = ''
    const bytes = new Uint8Array(buffer)
    const len = bytes.byteLength
    for (let i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i])
    }
    const base64 = window.btoa(binary)
    let text = "-----BEGIN " + (isPrivate ? "PRIVATE" : "PUBLIC") + " KEY-----\n" // 这里-----BEGIN和-----是固定的
    text += base64.replace(/[^\x00-\xff]/g, "$&\x01").replace(/.{64}\x01?/g, "$&\n") // 中间base64编码
    text += "\n-----END " + (isPrivate ? "PRIVATE" : "PUBLIC") + " KEY-----" // 这里-----END和-----是固定的
    return text
}

导入公私钥

window.crypto.subtle.importKey(
format,
keyData,
algorithm,
extractable,
keyUsages
)
,其中:
1.format可选rawpkcs8spkijwk,对应之前生成时的选择,我们这边在导入公钥时选spki,私钥选pkcs8

2.keyData,即window.crypto.subtle.exportKey获得的ArrayBuffer,由于在这里时我们一般只有pem文本的,所以还需要做转换成ArrayBuffer。

3.algorithm这边我们是rsa,需要填入一个RsaHashedImportParams对象,这边对应crypto.subtle.generateKey所需的RsaHashedKeyGenParams对象,含有:

  • name,都保持与之前一致
  • hash

4.extractablecrypto.subtle.generateKey

5.keyUsagescrypto.subtle.generateKey
函数返回一个promise对象,结果是一个CryptoKey

// 导入公钥
const pub = "-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo5NwYVVSg6rmAIKoxvCI
4Rn7FYh0mOFrnr0q2+r99/ZGuYCj5b6FQ8BwaaU8XpRn/y3W7W2bCggNRwllWQ2r
dHIM+6vN2Yi/QYntKqbcRNlK1s02G2lw9pERaWi15+5P8+AFR8IHANm/Dd/19OlM
5FZ9hh+qG7FXFhV2i4r62pUZxhk6ykItOT16IH5poK9eEDhqsXZ+3UW6cGlxANgO
jHJEnZpNCI5tS/4kFhLogHvEd88MoapljL6cZXk3ZafvxgUwxI6BZIhlw0adh2sj
bByIHitjRxqKMDH7uSdV9zf8t5Wa0bZFcUpcb5Jx2QBWIlO1qP+Q4LLMbNvEHeBC
4wIDAQAB
-----END PUBLIC KEY-----"

const pemHeader = "-----BEGIN PUBLIC KEY-----" // 之前RSA2text函数里面的头尾标识,这个是公钥的
const pemFooter = "-----END PUBLIC KEY-----"
const pemContents = pub.substring(pemHeader.length, pub.length - pemFooter.length) // 去除pem头尾
// base64解码
const binaryDer = window.atob(pemContents)
// 转为ArrayBuffer二进制字符串
const binary = str2ab(binaryDer)
window.crypto.subtle.importKey(
    "spki", // 这边如果私钥则是pkcs8
    binary , 
    {
        name: "RSA-OAEP",
        hash: "SHA-512" // 保持一致
    },
    true, 
    ["encrypt"] // 用于加密所以是公钥,私钥就是decrypt
)

function str2ab(str) {
    const buf = new ArrayBuffer(str.length)
    const bufView = new Uint8Array(buf)
    for (let i = 0, strLen = str.length; i < strLen; i++) {
        bufView[i] = str.charCodeAt(i)
    }
    return buf
}

加密解密

加密crypto.subtle.encrypt(algorithm, key, data),其中:
1.algorithm,加解密只支持RSA-OAEP不支持RSAES-PKCS1-v1_5

2.key即公钥的CryptoKey对象

3.data是一个BufferSource对象,不能直接是要加密的字符串。
结果是一个ArrayBuffer,可以使用window.btoa(String.fromCharCode(...new Uint8Array(e)))输出为base64字符串

const enc = new TextEncoder()
const data = enc.encode("sucks") // 这边将要加密的字符串转为utf-8的Uint8Array
window.crypto.subtle.encrypt(
    {
        name: "RSA-OAEP"
    },
    publicKey, // 生成或者导入的CryptoKey对象
    data
)

解密crypto.subtle.decrypt(algorithm, key, data),基本同加密,这边data对应为加密返回的ArrayBuffer,如果是base64字符串比如从后端加密过来的,就需要转为Uint8Array。

function base64ToUint8Array(base64String) {
    const padding = '='.repeat((4 - base64String.length % 4) % 4)
    const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/')

    const rawData = window.atob(base64)
    const outputArray = new Uint8Array(rawData.length)

    for (let i = 0; i < rawData.length; ++i) {
        outputArray[i] = rawData.charCodeAt(i)
    }
    return outputArray
}

返回值同加密

标签:const,加解密,RSA,crypto,window,-----,subtle
From: https://www.cnblogs.com/charleschwang/p/18331401

相关文章

  • 【Linux或者Windows中相关网络工具使用介绍】nc、ping、ifconfig、ipaddr、tcpdump、l
    在实际的网络排错、运维诊断、或者是开发过程中,熟练运用Linux或者Windows当中的有关网络工具,能够助力我们更迅速更精准地定位故障。因而,今天给大家分享几款必掌握的网络利器。1.nc命令在Linux中,nc命令即netcat命令,它被称为网络工具中的“瑞士军刀”,是一个功能强大的......
  • 1、 window平台opencv下载编译, 基于cmake和QT工具链
    1.环境准备,源码下载1.1前置环境qt下载安装cmake安装,可参考:https://blog.csdn.net/qq_51355375/article/details/1391866811.2opencv源码下载官网地址:https://opencv.org/releases/下载源码:2.opencv编译这里使用cmakegui图形化配置,操作简答些。2.1源......
  • Windows的Docker安装RustDesk自建服务
    一、安装DockerDesktopInstaller 二、CMD拉取RustDesk镜像dockerimagepullrustdesk/rustdesk-server三、创建docker-compose.yml文件services:hbbs:container_name:hbbsimage:rustdesk/rustdesk-server:latestcommand:hbbs-r公网IP:端口(21117......
  • Burp Suite Professional 2024.7 for Windows x64 - 领先的 Web 渗透测试软件
    BurpSuiteProfessional2024.7forWindowsx64-领先的Web渗透测试软件世界排名第一的Web渗透测试工具包请访问原文链接:https://sysin.org/blog/burp-suite-pro-win/,查看最新版。原创作品,转载请保留出处。BurpSuiteProfessionalTheworld’s#1webpenetrationtes......
  • Windows图形界面(GUI)-MFC-C/C++ - 静态文本框(Static Text) - CStatic
    公开视频-> 链接点击跳转公开课程博客首页-> ​​​链接点击跳转博客主页目录静态文本框(StaticText)-CStatic基本概念成员函数示例代码静态文本框(StaticText)-CStatic基本概念静态文本框是一种用于显示文本的控件,用户不能编辑其中的文本。静态文本框......
  • window配置onnxruntime,运行c++版本
    为了使用ONNX-Runtime-Inference这个项目,但是我缺少onnxruntime这个库,网上找了很多教程,但是大多数都是关于linux的,这里简单记录一下我的配置流程找到onnxruntime的release版本开始想着自己去找源码编译,发现这对于新手来说,是个坑,因为源码里面有些库是缺失的,需要自己去下载,并更改......
  • 在windows上用docker编译ceph
    Why为什么要在windows上跑docker去编译ceph的代码?是松鼠哥吃太饱了吗?当然不是~在实际生产问题处理中,很多时候会遇到棘手的情况,需要快速修改并编译得到可用的二进制程序,例如上篇中,松鼠哥处理多个osd连续的down时,就需要导出其中的一些pg,但是pg的数据导出会因为其中的一些对......
  • windows 命令行 pip 安装报错
    pipinstalltkWARNING:Retrying(Retry(total=4,connect=None,read=None,redirect=None,status=None))afterconnectionbrokenby'ProxyError('Cannotconnecttoproxy.',OSError(0,'Error'))':/simple/tk/WARNING:Retrying(R......
  • 等保测评计算机环境-windows
    等保测评计算机环境-windows对Windows操作系统进行等保测评的原因在于确保系统在信息安全方面达到一定的标准和要求。通过评估系统的安全性、访问控制、身份认证、日志和审计、数据保护、应用程序安全、网络安全以及安全管理和应急响应等方面,可以有效识别系统存在的安全风险和......
  • 在Windows Server上启用MIC (Enable microphone on VPS with Windows Server)
    在WindowsServer上启用MICEnablemicrophoneonVPSwithWindowsServer我有一台云主机,装有WindowsServer2012R2系统。现有个需求是需要通过本地电脑的麦克风录制音频。找了好多方法,未果,包括微软社区的回答和园内的博客。但下午脑瓜一转弯,更换了下关键词,找到了这篇文章,问......