2021-07-15 06:31 | 出处: Akash
从开始到结束,本指南将告诉你如何在Akash Network创建一个有效的x509证书,浏览器中使用ECDSA SHA-256。
第一印象感觉很枯燥,那可能是因为作为网络开发者,我们一般不会处理这种东西。然而,随着前端开发迅速发展成为全栈应用开发,原来很多是传统后端开发干的活我们也要碰到了。
这项任务的关键要求是生成一对用于签名和验证的密钥。以PEM格式导出私钥、公钥和证书,以便它们可以被存储,或传输。
通过Akash网络,我们将证书和公钥存储在链上,这样其他人就可以验证一个行为者与他们声称是用户的资金来源相连接。我们将这些PEM格式转换成uInt8数组,通过protobuf传输。
在研究时,我认为这将是一个简单的互联网搜索。然而,缺失和过时的信息结合在一起,使得我很难找到让当前的算法与我想要通信的其他客户/服务器的规格相匹配所需的信息。
让我们先从简单的东西开始。
今天我们这样做的最常见的情况是,要么验证我们机器的身份,以代替密码,如Github、AWS控制台、CryptoCoins或Web服务器。现在,我们要在浏览器中生成一个。
幸运的是生活是美好的,Chrome和其他浏览器供应商在浏览器中实现密码学库方面有一个良好的开端。我们也有一些很好的标准化库来处理多个地方的密码学问题。我们将倚重的两个库是 pkijs 和 asn1js。
这些库中的每一个都为我们提供了所需的方法/类和类型,以处理一个任务的多个方面。我们可以使用你喜欢的软件包管理器简单地安装这些库。这些都能很好地捆绑在现代网络浏览器上。我还接触了pvutils,以简化其用于将证书编码为文本格式的一些效用。这个库在整个密码学部分并不需要,所以请随意将借用的方法换成你自己喜欢的版本。
npm i pkijs asn1js pvutils
一旦安装了这些工具,我们就可以开始工作了,生成我们的第一个密钥对。
const {
getCrypto,
getAlgorithmParameters
} = require("pkijs/build");
我们将在这里使用getCrypto方法来给我们一个加密处理程序。在浏览器中,这通常映射到一个窗口。SubtleCrypto也可以推断为window.crypto.webKitSubtle,window.crypto.subtle。我们的想法是,你会得到JavaScript在整个浏览器中是如何标准化的这一点。所以我们要用getCrypto来简化。
我们还需要获取getAlgorithmParameters,这样我们就可以很容易地得到围绕需要进行的具体编码和解码的摘要信息。这大大简化了我们把所有曲线、散列数学等相关信息拉到一起的需要,使其发挥作用。值得庆幸的是,如果你能跟上pkijs的步伐,你应该可以获得现代的、最新的算法。在这里我要给你一点建议,远离预置和浏览器捆绑的模块生态系统之外的东西。如果你需要在密码学方面有所发展,你会发现它们在几年后就可能会过时。
下面是将生成一个加密密钥对的代码存根。在这里,我将指定一个使用SHA-256散列的ECDSA签名。你可能需要根据你的目标环境来改变这些。
const crypto = getWebCrypto();
const algo = getAlgorithmParameters("ECDSA", "generatekey");
const keyPair = crypto.generateKey(algorithm.algorithm, true, algorithm.usages);
就是这样,你刚刚生成了一个有效的密钥对!
generateKey方法的分类是algo、allowExport和usage。由于getAlgorithm方法,其中两个已经定义好了,我们可以自由决定是否要在代码中捕获这个密钥对。在这种情况下,我们要这样做,因为我们要生成这些备份,我们还需要用这些密钥来签署和生成一个有效的x509证书。
生成x509比我预期的要简单得多。最大的障碍是理解OIDs应用于证书创建的方式。对象ID是用来识别字段和哪种属性应该被编码到证书中的。
使用像OID信息这样的OID库,你可以找到你需要的字段的OIDs。有一些常见的字段,如组织、国家和州,你也可以进行编码。这些字段的必要性是由证书的消费实体严格决定的。他们不需要产生一个可用于验证和签名的有效证书。
为了生成x509,我们将从pkijs中抓取一些更多的助手。我们还将从asn1js中获取类型,所以我们也要把它带在身边。
const {
AttributeTypeAndValue,
Certificate,
BasicConstraints,
Extension,
ExtKeyUsage
} = require("pkijs/build");
const asn1js = require("asn1js");
证书类将被用来创建x509,其他类将被用来装饰和与证书互动。你可能不需要ExtKeyUsage,但我们会去了解它,因为这个方案也适合其他地方。
创建实际证书是超级简单的。
const cert = new Certificate();
现在,我们在内存中已经有了一个证书,我们可以正式开始构建证书所需的字段。
cert.version = 2;
cert.serialNumber = new asn1js.Integer({ value: Date.now() });
同样,这些字段中的任何一个都是可选的。我们可以直接跳过签署证书,这将使它完全有效,但你遇到的实际情况可能需要额外的字段和描述--版本和序列号是两个非常常见的字段。
它们看起来是没什么特别作用的字段,但可以被验证者用来确定证书的签发者是否以任何有意义的方式改变了它。版本是0的偏移量,这里的序列号只是发行的时间戳。根据使用情况,这可能需要更加积极(例如,JWT替换)。
为了导出私钥和公钥,我们要使用两个标准。pkcs#8标准,即公钥密码学标准。简单说就是密钥信息的base**编码版本。结合header和footer作为边界,每隔**字节有一个换行符。
我们还将使用spki标准,这意味着我们希望我们的公钥是在证书之外容易交换的格式。spki的目的是为了允许在证书颁发者之外进行密钥验证。
从浏览器中获取这两个二进制文件很简单,只需几行代码。
const spki = await crypto.exportKey("spki", keyPair.privateKey);
const pkcs8 = await crypto.exportKey("pkcs8", keyPair.privateKey);
现在,我们需要将这些二进制输出结构化为具有我们称之为边界的文本形式。在这种情况下,边界是一个带有新线的文本分界线,如下图所示。
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
在这两个边界之间,我们要把我们的证书和钥匙的base**表示法放进去。还记得pvutils吗?现在是时候去找那些工具了!
const { arrayBufferToString, toBase** } = require("pvutils");
我们还需要以**字节的行数限制来格式化PEM文件。这真的很容易做到,用一个替换的regex。
function formatPEM(pemString: any) {
return pemString.replace(/(.{**})/g, "¥1
");
}
让我们一起使用这三个辅助方法,将ArrayBuffers转换为字符串,然后我们可以对这些字符串进行Base**编码,并为创建我们的PEM文件而格式化它们。
const pems = {
csr: `-----BEGIN CERTIFICATE-----
¥{formatPEM(
toBase**(arrayBufferToString(certBER))
)}
-----END CERTIFICATE-----`,
privateKey: `-----BEGIN PRIVATE KEY-----
¥{formatPEM(
toBase**(arrayBufferToString(pkcs8))
)}
-----END PRIVATE KEY-----`,
publicKey: `-----BEGIN EC PUBLIC KEY-----
¥{formatPEM(
toBase**(arrayBufferToString(spki))
)}
-----END EC PUBLIC KEY-----`,
};
这段代码使用模板字面量,将String格式的边界与返回的base**编码结合起来。剩下的是一个拥有3个不同的PEM格式文件的对象,这些文件可以保存在内存中或写入文件中进行传输。
可以签名啦!
想让这一切变得更简单,或者也许正在寻找一种方法来生成与Akash网络兼容的证书?推荐使用 AkashJS,它旨在帮助简化浏览器和NodeJS下的这些任务。
微博: https://weibo.com/akashchina
币乎: https://bihu.com/people/1117023356
推特: https://twitter.com/AkashCommunity
QQ群: http://t.hk.uy/sqe
语雀:https://www.yuque.com/akashnetwork/index
akash官网:https://akash.network/?lang=zh-hans
Twitter: https://twitter.com/akashnet_
Facebook: https://www.facebook.com/akashnw/
LinkedIn: https://www.linkedin.com/company/akash-network/
Telegram: https://t.me/AkashNW
Github: https://github.com/ovrclk