转自简书,原文地址,本文介绍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
}

返回值同加密

前端RSA密钥生成和加解密——window.crypto使用相关的更多相关文章

  1. RSA密钥生成与使用

    RSA密钥生成与使用 openssl生成工具链接:http://pan.baidu.com/s/1c0v3UxE 密码:uv48 1. 打开openssl密钥生成软件打开 openssl 文件夹下的  ...

  2. openssl-0.9.8k_WIN32(RSA密钥生成工具

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha openssl-0.9.8k_WIN32(RSA密钥生成工具

  3. RSA密钥生成、加密解密、签名验签

    RSA 非对称加密公钥加密,私钥解密 私钥签名,公钥验签 下面是生成随机密钥对: //随机生成密钥对 KeyPairGenerator keyPairGen = null; try { keyPair ...

  4. windows上RSA密钥生成和使用

    一,下载安装windows平台openssl密钥生成工具,执行安装目录bin下的"openssl.exe",执行后弹出命令窗口如下 运行 二,生成私钥 输入"genrsa ...

  5. Java RSA 密钥生成工具

    MAC openssl: RSA加解密 第一条命令是生成密钥长度为1024的密钥: 第二条命令是从中生成公钥: 第三条命令是使用pkcs8编码密钥为私钥 http://blog.csdn.net/ch ...

  6. linux下OpenSSL的RSA密钥生成

    工具的安装: 一.源码安装 OpenSSL Version:openssl-1.0.0e.tar.gz ------------------------安装: 1.将下载的压缩包放在根目录, 2.在文 ...

  7. Windows下RSA密钥生成工具openssl

    下载openssl.zip 1. 生成原始 RSA私钥文件 private_key.pem openssl genrsa -out private_key.pem 1024 2. 将原始 RSA私钥转 ...

  8. windows平台RSA密钥生成

    1.安装openssl工具 下载安装openssl工具,执行安装目录bin下的"openssl.exe",执行后会弹出命令窗口. 2.生成私钥 在命令窗口输入“genrsa -ou ...

  9. 密码疑云 (3)——详解RSA的加密与解密

    上一篇文章介绍了RSA涉及的数学知识,本章将应用这些知识详解RSA的加密与解密. RSA算法的密钥生成过程 密钥的生成是RSA算法的核心,它的密钥对生成过程如下: 1. 选择两个不相等的大素数p和q, ...

  10. PHP通过OpenSSL生成证书、密钥并且加密解密数据,以及公钥,私钥和数字签名的理解

    一.公钥加密假设一下,我找了两个数字,一个是1,一个是2.我喜欢2这个数字,就保留起来,不告诉你们(私钥),然后我告诉大家,1是我的公钥. 我有一个文件,不能让别人看,我就用1加密了.别人找到了这个文 ...

随机推荐

  1. taro 使用taro中的vue来完成小程序的开发

    网址:https://taro-docs.jd.com/taro/docs/README 2.1.简介 Taro 是一个开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发 ...

  2. Vue3等比例缩放图片组件

    本文由 ChatMoney团队出品 有些情况我们需要在各种刁钻的情况下都要保持图片比例不变,比如用户缩放窗口等改变布局的情况.实现原理就是通过容器的宽度和内边距在保持你想要的比例. 以下是基础功能的组 ...

  3. Math Record

    T1.P3327 知识点:莫比乌斯反演,数论分块 我们知道 \(d(ij) = \sum_{x | i}\sum_{y | j}[\gcd(x,y) == 1]\). 所以我们就要求 \(\sum^n ...

  4. 项目管理--PMBOK 读书笔记(13)【项目相关方管理】

    1.相关方分矩阵 工具与技术 核查表 又叫检查表,计数表,收集属性数据,解决问题.   焦点小组&访谈: 特点:慢,焦点小组是一对多,访谈时多对多.   抽样统计&控制图: 控制图反应 ...

  5. maven和gradle环境变量配置及idea相关的设置

    1.maven 环境变量添加之后,重新打开cmd窗口,验证是否配置成功. idea   File >> Settings idea配置之后的验证: 2.gradle 环境变量添加之后,重新 ...

  6. Python做点击率数据预测

    点击率(Click-Through Rate, CTR)预测是推荐系统.广告系统和搜索引擎中非常重要的一个环节.在这个场景中,我们通常需要根据用户的历史行为.物品的特征.上下文信息等因素来预测用户点击 ...

  7. 可以把 FolkMQ 内嵌到 SpringBoot3 项目里(可内嵌的消息中间件,纯血国产)

    之前发了<把 FolkMQ 内嵌到 SpringBoot2 项目里(比如 "诺依" 啊)>.有人说都淘态了,有什么好内嵌的...所以再发个 SpringBoot3 Fo ...

  8. FFmpeg开发笔记(三十二)利用RTMP协议构建电脑与手机的直播Demo

    不管是传统互联网还是移动互联网,实时数据传输都是刚需,比如以QQ.微信为代表的即时通信工具,能够实时传输文本和图片.其中一对一的图文通信叫做私聊,多对多的图文通信叫做群聊. 除了常见的图文即时通信,还 ...

  9. LLM学习笔记

    1. 评估榜单 1.1. C-Eval C-Eval 是一个全面的中文基础模型评估套件.它包含了13948个多项选择题,涵盖了52个不同的学科和四个难度级别. https://cevalbenchma ...

  10. AT_abc215F 题解

    考虑二分答案. 假设当前二分的答案为 \(k\),那么对于每个点,距离大于等于 \(k\) 的点构成了平面上 \(4\) 个子平面. 那么只需查询子平面中是否存在点即可,类似于窗口的星星,把问题转换成 ...