前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Web Crypto API简介

Web Crypto API简介

原创
作者头像
王沛文
发布于 2018-07-31 07:43:34
发布于 2018-07-31 07:43:34
6.2K0
举报
文章被收录于专栏:王沛文的专栏王沛文的专栏

早年在web端做对称/非对称的加解密还是个很复杂的操作,由于没有js层面的基础库。很多基础设施只能从头开始。

QQ登录注册之前使用的RSA加密算法就是参考http://www-cs-students.stanford.edu/~tjw/jsbn/的实现。

还有各种aes/md5/sha等常用算法的js库也是层出不穷。但是由于大多都是个人项目,很多库并没有很好的维护,对于不同的算法支持也不是很完整。比如基于https://github.com/travist/jsencrypt就缺少RSA/OEAP的支持,https://github.com/ricmoo/aes-js也缺少AES/GCM的支持。

当然近些年来Web标准突飞猛进。对于常用密码学套件来说,最大的新增特性就是Web Crypto API了。

Web Crypto API提供了常用算法的加密/解密/签名/验证/摘要/key生成/协商等操作,功能上和nodejs中的crypto模块基本等同,也就是Web端的OpenSSL了。

但是由于接口和nodejs中的crypto不同,Web Crypto API统一采用的Promise来处理异步逻辑,而不是nodejs中的回调。这样可以很方便的使用await/async简化代码。

摘要算法

针对摘要算法提供的是disgest接口,这个接口可以提供SHA-1/SHA-256/SHA-384/SHA-512的摘要算法。

对于MD5等老旧的算法是不支持的。SHA-1这里也很特殊标准之前是规定支持这个算法,但是由于SHA-1本身存在缺陷,已经建议不使用,从浏览器来看就是移除SHA-1的支持。

代码语言:txt
AI代码解释
复制
window.crypto.subtle.digest(
    {
        name: "SHA-256",
    },
    new Uint8Array([1,2,3,4])
)
.then(function(hash){
    console.log(new Uint8Array(hash));
})
.catch(function(err){
    console.error(err);
});

这里比较特殊的就是接口的输入和输出都是ArrayBuffer相关的类

密钥操作

除了摘要算法之外,加解密签名都需要密钥来操作。涉及到的主要就是密钥生成/导入/导出。、

下面是生成密钥的示例代码

代码语言:txt
AI代码解释
复制
window.crypto.subtle.generateKey(
    {
        name: "RSASSA-PKCS1-v1_5",//算法名称
        hash: {name: "SHA-256"}, //签名时的hash算法
        //RSA参数
        modulusLength: 2048, //私钥长度
        publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
        //EC参数
        namedCurve: "P-256",//曲线名字
        //AES参数
        length: 256, //密钥长度
    },
    false, //是否可以被导出
    ["sign", "verify"] //该key支持的操作
)
.then(function(key){
    //这里获取的key可以用于后续加解密签名等操作
    console.log(key);
})
.catch(function(err){
    console.error(err);
});

当然除了本地生成密钥还有导入外部密钥

代码语言:txt
AI代码解释
复制
window.crypto.subtle.importKey(
    "jwk", //密钥格式
    {   //密钥内容
        kty: "oct",
        k: "Y0zt37HgOx-BY7SQjYVmrqhPkO44Ii2Jcb9yydUDPfE",
        alg: "A256CTR",
        ext: true,
    },
    {   //密钥算法
        name: "AES-CTR",
    },
    false, //是否能被导出
    ["encrypt", "decrypt"] //支持的操作模式
)

这里比较让人疑惑的就是密钥格式和密钥内容两个参数了

密钥格式和密钥内容

通常我们使用的密钥格式为PEM/DER。而上述例子中的jwk指的是JSON Web Key。具体可以参见rfc7517

对于常见的PEM格式我们需要使用其中有效内容部分。即BEGIN/END之间的部分所以我们可以将其中内容提取出来之后base64解码。

代码语言:txt
AI代码解释
复制
function convertPemToBinary(pem) {
    var lines = pem.split('\n')
    var encoded = ''
    for (var i = 0; i < lines.length; i++) {
        if (lines[i].trim().length > 0 &&
            !/-----BEGIN .*-----/.test(lines[i]) &&
            !/-----END .*-----/.test(lines[i])) {
            encoded += lines[i].trim()
        }
    }
    return base64StringToArrayBuffer(encoded)
}
function base64StringToArrayBuffer(b64str) {
    var byteStr = atob(b64str)
    var bytes = new Uint8Array(byteStr.length)
    for (var i = 0; i < byteStr.length; i++) {
        bytes[i] = byteStr.charCodeAt(i)
    }
    return bytes.buffer
}

DER格式则就是PEM中具体的内容。

对于EC/RSA公钥使用pkcs8的PEM/DER格式的实际数据配合密钥格式spki就可以导入了。

而私钥则是pkcs8格式的实际数据配合密钥格式pkcs8

对称密钥则可以通过raw加上实际密钥内容导入。

导出操作则相对简单

代码语言:txt
AI代码解释
复制
window.crypto.subtle.exportKey(
    "jwk", //密钥格式
    key //密钥
)
.then(function(keydata){
    console.log(keydata);
})
.catch(function(err){
    console.error(err);
});

加解密

代码语言:txt
AI代码解释
复制
window.crypto.subtle.encrypt(
    {
        name: "RSA-OAEP",
    },
    publicKey,
    data
)
.then(function(encrypted){
    console.log(new Uint8Array(encrypted));
})
.catch(function(err){
    console.error(err);
});

window.crypto.subtle.decrypt(
    {
        name: "RSA-OAEP",
    },
    privateKey,
    data
)
.then(function(decrypted){
    console.log(new Uint8Array(decrypted));
})
.catch(function(err){
    console.error(err);
});

加解密的接口都类似,输入算法/密钥/数据,输出结果。这里输入输出的数据也都是ArrayBuffer的格式

签名验签

代码语言:txt
AI代码解释
复制
window.crypto.subtle.sign(
    {
        name: "RSASSA-PKCS1-v1_5",
    },
    privateKey,
    data
)
.then(function(signature){
    console.log(new Uint8Array(signature));
})
.catch(function(err){
    console.error(err);
});

window.crypto.subtle.verify(
    {
        name: "RSASSA-PKCS1-v1_5",
    },
    publicKey,
    signature,
    data
)
.then(function(isvalid){
    console.log(isvalid);
})
.catch(function(err){
    console.error(err);
});

签名和验证签名的接口也是类似。

总结

Web Crypto API的入口是window.crypto.subtle

所有的接口都是window.crypto.subtle的方法。所有接口的返回都是Promise对象。

涉及密钥操作的算法需要先生成或导入密钥。导入密钥的格式有raw,spki,pkcs8,jwk。raw用于对称密钥直接导入的情况,spki则是DER格式的公钥,pkcs8时DER格式的pkcs8私钥,jwk则支持所有的场景,但是需要转换。

所有算法输入输出均为ArrayBuffer

补充

具体浏览器支持可以参见https://caniuse.com/#feat=cryptography

针对旧浏览器的polyfill/shim可以看https://github.com/vibornoff/webcrypto-shimhttps://github.com/PeculiarVentures/webcrypto-liner

常见的样例代码可以参见https://github.com/diafygi/webcrypto-examples

最后Web Crypto API由于属于安全接口,在非https的页面上可能不可用(chrome中)。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
Excel: 通过VBA代码打开ppt文件
文章背景:使用Excel的Userform时,有时想要打开指定路径的ppt文件。下面介绍两种打开ppt文件的方式。
Exploring
2022/09/20
3.6K0
Excel: 通过VBA代码打开ppt文件
VBA: 统计各个文件夹内的指定文件个数
文章背景:某台仪器测量结束后,测试数据以pdf格式保存在日期文件夹内。想要通过获取12月份的pdf总数,计算当月产量。需要遍历各个日期文件夹,进行文件的统计汇总工作。
Exploring
2022/09/20
3.2K0
VBA: 统计各个文件夹内的指定文件个数
VBA: 打开带密码的Excel文件
文章背景:想要通过VBA打开一份带密码的Excel文件,然后在文件内填入信息。前述要求可以借助workbook.open来实现。
Exploring
2022/09/20
4.7K0
VBA: DTPicker日期控件的使用
文章背景:最近在查看同事写的VBA代码时,发现了DTPicker日期控件。DTPicker是日期选择控件,自Win7开始,它就不是Windows系统自带的,需要下载MSCOMCT2.OCX,并在电脑上注册后才能使用。
Exploring
2022/09/20
9.8K0
VBA: DTPicker日期控件的使用
VBA: Excel文件批量转化为pdf (2)
文章背景:测试仪器的数据有些会以Excel文件的形式保存,有时需要将测试数据转化为pdf格式。上篇文章(见文末的延伸阅读)通过VBA代码,采用ExportAsFixedFormat函数将excel文件转化为pdf文件,对于部分excel文件的转化效果不太好,有些谱图显示不完整,如下图所示。
Exploring
2022/09/20
2.6K0
VBA:  Excel文件批量转化为pdf (2)
VBA: 多份Excel文件的批量顺序打印
文章背景:测试仪器的数据有时会以Excel文件形式保存,工作量大时会选中多份文件进行批量打印。当office升级后,批量打印时可能会出现顺序错乱,这时需要手动排序,费事费力。现在以批量打印Excel文件(.xlsx格式)为例,采用VBA编程,进行任务的实现。
Exploring
2022/09/20
2.7K0
VBA:  多份Excel文件的批量顺序打印
VBA: 禁止单元格移动,防止单元格公式引用失效
文章背景: 在工作生活中,存在文件共享的情况。在数据处理时,单元格公式中往往要引用原始数据源。多人操作时,每个人的操作习惯不同,如果数据源的单元格不小心被人为移动或删除,会导致单元格公式引用失效,产生#REF! 错误。如果进行的是跨表引用,这种错误往往还很难发现。
Exploring
2022/09/20
8210
VBA:根据指定列删除重复行
文章背景:在工作生活中,有时需要进行删除重复行的操作。比如样品测试时,难免存在复测数据,一般需要删除第一行数据,保留后一行的数据。
Exploring
2022/09/20
3.4K0
在Excel中透视表+VBA玩转TopN&Others分析
http://mpvideo.qpic.cn/0bc3meaaoaaaaualwlxssfqvayoda5qqabya.f10002.mp4?dis_k=ae949b883b3e655a94875f0
Excel催化剂
2022/03/31
1.6K0
ppt: 快速将幻灯片逆序排列
文章背景:在工作中,有时遇到一份ppt,顺序正好是乱的。现在想要将最后一页放在开头,倒数第二页放在开头第二页...。如果一份ppt有多页幻灯片,手动操作特别费劲。在网上查阅资料后,发现可以通过宏命令来实现批量操作,下面介绍两种方式。
Exploring
2022/09/20
2.9K0
ppt: 快速将幻灯片逆序排列
Python:用了这个库,就可以跟 Excel 说再见了
今天分享一个个比 Excel 更好用的 Python 工具,看完后,估计你要跟 Excel 说拜拜了。它就是 Mito
somenzz
2022/10/25
8410
VBA: 定时保存Excel文件
文章背景:有一份文件的数据更新比较频繁,而其他电脑需要随时查看该文件的最新数据,因此,需要经常保存该文件。
Exploring
2022/09/20
2.5K0
VBA:  定时保存Excel文件
OpenAI又整活:ChatGPT再扛起数据分析大旗,Excel、Word全部拿下
距离 GPT-4o 发布几天后,OpenAI 又上新了。这次,他们瞄准 ChatGPT 的数据分析功能,那些折线图、柱状图、饼图等分析起来毫无压力。
统计学家
2024/05/20
1750
OpenAI又整活:ChatGPT再扛起数据分析大旗,Excel、Word全部拿下
VBA: 运行时错误‘424’:要求对象(设置坐标轴标题时)
文章背景:有一组x-y的数据,想通过录制宏的方式,实现画图的自动化。本文以散点图为例,需要在图中添加坐标轴的标题。录制好宏后,运行代码时,报错如下:
Exploring
2022/09/20
4.7K0
VBA: 运行时错误‘424’:要求对象(设置坐标轴标题时)
VBA: 在工作簿内复制用户窗体
文章背景:Excel中,在创建完一个用户窗体(Userform)后,有时想要在此基础上,创建针对另一场景的用户窗体。那么,如何在工作簿内复制用户窗体呢?下面介绍两种办法。
Exploring
2022/09/20
1.6K0
VBA: 判断动态数组是否为空
文章背景:在VBA代码中,有时需要创建动态数组,然后对该动态数组进行操作。如果该数组为空,在使用一些函数(如Lbound,Ubound等)时,代码会报错。因此,需要事先判断动态数组是否为空。下面介绍一个判断动态数组是否为空的自定义函数。
Exploring
2022/09/20
5K0
Rez Academy
今天要向大家分享的是全网现阶段最详细的Rez入门教程 作者是Colin Kennedy
用户9897904
2022/07/14
3720
Rez Academy
VBA: 多份文件的批量顺序打印(2)
文章背景:测试仪器的数据有些会以Excel文件的形式保存,工作量大时测试员会选中多份文件进行批量打印,同时可能需要删除一些无需打印的测试数据(比如空白样,错误数据等)。现在以批量打印Excel文件(.xlsx格式)为例,采用VBA编程,进行任务的实现。
Exploring
2022/09/20
1.4K0
VBA:  多份文件的批量顺序打印(2)
Excel: 通过Countif函数识别重复的数据
文章背景:在数据处理时,有时候需要判断某个数据是否重复出现;在录入数据时,有时需要避免数据的重复输入。此时,可以借助Excel的countif函数进行功能的实现。
Exploring
2022/09/20
1.5K0
Excel: 通过Countif函数识别重复的数据
VBA: 冒泡排序法的代码实现
文章背景:冒泡排序(Bubble Sort)是排序算法里面比较简单的一个排序,在工作中用到的并不多,主要是想了解其中的算法思想,从而让我们的思维更加开阔。
Exploring
2022/09/20
8490
VBA:  冒泡排序法的代码实现
推荐阅读
相关推荐
Excel: 通过VBA代码打开ppt文件
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档