乐趣区

关于后端:新开源HTML5单文件网页版ACME客户端可在线申请Lets-EncryptZeroSSL免费HTTPS通配符泛域名证书

之前写了两篇对于 HTTPS 证书的文章,一篇是本地自签证书,另一篇是 Let’s Encrypt 开始反对收费通配符证书时通过 diafygi/gethttpsforfree 网页来申请证书,步骤均很繁琐;于 2022 年 9 月我写了我开发了一个操作非常简单的网页版 ACME 客户端:ACME-HTML-Web-Browser-Client,并在 GitHub、Gitee 上进行了开源。

整个源码仅一个动态 HTML 网页文件,能够间接保留到本地应用,或通过在线网址应用;反对向 Let's EncryptZeroSSL 等反对 ACME 协定的证书颁发机构,收费申请取得用于 HTTPS 的 SSL/TLS 域名证书(RSAECC/ECDSA),反对多域名和通配符泛域名;只需在古代浏览器上操作即可取得 PEM 格局纯文本的域名证书,不依赖操作系统环境,无需下载和装置软件,无需注册登录,纯手动操作,只专一于申请取得证书这一件事

证书过期危险揭示: 因为本网页客户端只能纯手动操作,不反对主动续期,需注意在证书过期前从新生申请新证书(收费证书广泛 90 天有效期,届时只需反复操作一遍即可),或应用 acme.sh 等客户端自动化续期。

开源我的项目的起源

我本人次要是在 Windows 外面用的多,并不介意甚至更偏差于纯手动操作取得证书,但官网 ACME 客户端列表外面的能单纯提供合乎我需要的寥寥无几:依赖特定操作系统环境、须要装置特定的运行环境、要本人写代码开发、甚至有的还必须捆绑线上生产环境;而我需要仅仅是单纯的想取得一个证书文件而已,但带来的是一整套全家桶,很难专一于只申请取得证书这一件事。

常见的 ACME 客户端要么是须要 Bash 脚本环境,要么就是不同开发语言的源代码或者第三方库须要本人写代码;新近 Let’s Encrypt 的列表外面还有提供网页版的客户端列表(我在外面找到的 gethttpsforfree),当初官网因为“一些浏览器内 ACME 客户端可用,但咱们未在此处列出它们,因为它们激励手动续订工作流程,这会导致蹩脚的用户体验并减少错过续订的危险” 而不再展现网页版客户端列表,我很悲观;也有局部反对 Windows 的桌面程序能够间接应用,比方win-acme,不过看了文档也很难上手;有局部客户端或网站甚至会要求注册并登陆账户能力应用,还帮你治理私钥(存储到他们的服务器,巴不得把通讯录都拿走),哈 ~ 呸 ~~

长时间我都是应用 fszlin/certes 这个.Net 的库来签发证书,本人 C#写的一个控制台程序,双击程序就能间接达到验证阶段,配置好 DNS 验证记录就能申请到证书文件,但要给他人用就麻烦了,要改 C# 代码;更重要的是 EXE 程序还有一个信赖的问题,双击一个 EXE 程序须要承当的危险很大;网页版就齐全不同了,网页自身就带有很大水平的开放性,咱们齐全能够审查代码是否有加料,网页人造适宜做 UI,人机交互的敌对性远超脚本控制台程序 ,对于用不上自动化续期、或自动化在服务器进行部署证书的需要,在网页上进行申请是最现实的操作形式;比方diafygi/gethttpsforfree 咱们齐全能够看到他的网页源码,还能通过浏览器控制台齐全监控到网络数据流向,最为简略和牢靠,尽管这个网页也是开源的,但它须要的操作太繁琐了,新近我还给他提了个我本人在用的简化签名操作的办法 issues/164。

为了能用上一个合乎我心里预期的并且操作简略的网页版 ACME 客户端,依靠于古代浏览器对 RSAECC 加密、签名的间接反对,因而我决定本人写!好在以前积攒了点根底的密码学常识,编写本客户端不存在常识盲点,很顺利的写完了全副 HTML 代码,并进行了开源。

我的项目地址

GitHub: https://github.com/xiangyuecn/ACME-HTML-Web-Browser-Client
Gitee: https://gitee.com/xiangyuecn/ACME-HTML-Web-Browser-Client

在线应用本客户端:
国内拜访 gitee.io: https://xiangyuecn.gitee.io/acme-html-web-browser-client/ACME-HTML-Web-Browser-Client.html
不太稳固 github.io: https://xiangyuecn.github.io/ACME-HTML-Web-Browser-Client/ACME-HTML-Web-Browser-Client.html

应用办法

这里介绍的是残缺的操作流程,请依据步骤进行操作,很容易就能申请失去证书文件;本文图片中显示的数据都是演示用的并非实在数据。

第一步:抉择 Let’s Encrypt、ZeroSSL 或其余证书颁发机构

依据下面的我的项目地址,关上本网页客户端(下载保留惟一的这一个 html 文件并双击关上、或者应用在线网址);只有是反对 ACME 协定的证书颁发机构,都能够在第一步操作中填写对应地址,目前默认提供了 Let's EncryptZeroSSL 两家的地址,依据本人须要间接抉择即可。

不同证书颁发机构须要的操作不肯定雷同,请依据提醒进行操作;Let's Encrypt间接到第二步操作,ZeroSSL因为他们的 ACME 服务对浏览器反对很不敌对存在跨域问题,须要多操作几下(复制源码到他们服务地址页面中运行,打消跨域问题)。

第二步:证书配置,填写域名

在网页的第二步中填写须要申请证书的域名(反对多域名、通配符),和密钥等信息配置;不同证书颁发机构须要填写的配置不肯定雷同,请依据提醒进行操作。

填写域名列表: 比方要给你的域名 test123.com 申请证书,在域名中能够间接填写:test123.com, *.test123.com,带了一个通配符,这申请进去的证书在 test123.comwww.test123.comapp.test123.com 等域名都能够应用。留神:如果须要 xxx.app.test123.com 这种域名也能应用,需减少填写 *.app.test123.com 相似这种才行。

证书私钥: 倡议间接点击创立新的 RSA 私钥。

ACME 账户私钥: 如果你之前申请过,倡议填写之前用过的私钥,没有申请过也同样的创立新的 RSA 私钥。

ACME 分割邮箱: 填写一个你罕用的邮箱,证书颁发机构会在证书到期前给你推送邮件揭示续期,乱填邮箱收不到揭示。

EAB 凭据: 有些 ACME 服务会要求提供内部账号绑定凭据(External Account BindingexternalAccountBindingexternalAccountRequired),比方 ZeroSSL:你能够在 ZeroSSL 的治理控制台的 Developer 中取得此凭据,所以你须要先注册一个 ZeroSSL 的账号;Let’s Encrypt 没有此选项。

第三步:实现域名所有权的验证

依据网页内显示的第三步内容,给每个域名配置好适合的域名所有权验证形式;常见的验证形式有:DNS 解析中配置 TXT 记录进行验证、上传文件到服务器进行验证,通配符域名个别仅反对 DNS 验证;等全副配置实现后开始验证,验证通过后就能下载失去证书了。

举荐应用 DNS 验证形式 ,只须要登录你的域名解析治理后盾,在域名解析中填写子域名 TXT 记录就行,简略快捷,并且不容易出错;比方*.test123.com,咱们须要给子域名_acme-challenge.test123.com 增加一条 TXT 记录(这一个子域名下能够增加多条 TXT 记录)。

通过上传文件来验证,不太举荐这个形式,因为必须要有服务器,不然 ACME 拜访不到文件就会验证不通过;为了让上传的文件能失常拜访,可能须要在服务器内进行一些配置(请自行搜寻解决办法),测试 URL 地址你本人也能失常拜访后,能力开始验证。

第四步:下载保留证书 PEM 文件

等域名所有权验证通过后,网页会显示第四步,提供证书文件下载,下载保留好;有 3 个文件须要下载(都是纯文本,能够用记事本关上):

  1. 证书文件(含残缺证书链)
  2. 证书私钥文件
  3. 日志记录文件,下次申请时间接拖拽此文件进页面,主动填写雷同配置

证书文件的后缀 .pem 能够改成 .crt.cer,这样在 Windows 外面能够间接双击关上查看此证书。

最初将下载保留的证书和私钥配置到你的网站中即可,不同零碎程序的配置办法不同,请自行查找对应配置办法。

源码中一些能够把玩的代码

为了在浏览器上实现 RSAECC 签名操作,源码中用纯 js 代码实现了:

  • PKCS#1的解析,PEM 格局公钥和私钥
  • PKCS#8的解析和生成,PEM 格局公钥和私钥
  • PKCS#10的生成,PEM 格局证书申请 CSR 文件(Certification Request)

对应的性能封装在本客户端内的 X509 对象中,用 X509.CreateCSR 来生成 CSR,用 X509.KeyGenerate 来创立 PEM 格局密钥,用 X509.KeyParse 来解析 PEM 格局密钥,用 X509.KeyExport 来导出 PEM 格局密钥。

这些性能都是依据相应的规范用 js 代码在二进制层面上实现的,二进制数据操作封装在了 ASN1 对象中:实现了 ASN.1 规范的二进制解析和封包,应用 ASN1.ParsePEM 办法能够解析任意的 PEM 格局密钥或证书。

请关上本网页客户端,在浏览器控制台内执行一下代码参观:

console.log("生成一个 512 位的 RSA 私钥 PKCS#8:");
X509.DefaultType2_RSA="512";
privateKey=await new Promise(function(resolve,reject){X509.KeyGenerate("RSA", function(pem){resolve(pem)}, function(err){reject(new Error(err))})
});
console.log(privateKey);

console.log("解析一个 pem 格局密钥:");
keyInfo=await new Promise(function(resolve,reject){X509.KeyParse(privateKey, function(info){resolve(info)}, function(err){reject(new Error(err))})
});
console.log(keyInfo);

console.log("导出私钥的公钥 PKCS#8:");
publicKey=X509.KeyExport(keyInfo, true);
console.log(publicKey);

console.log("用私钥创立一个证书申请 CSR PKCS#10:");
csr=await new Promise(function(resolve,reject){
    X509.CreateCSR(keyInfo, "test123.com"
        , ["test.com","*.test.com","*.app.test.com","test123.com","*.test123.com"]
        , function(csr){resolve(csr)}, function(err){reject(new Error(err))})
});
console.log(csr);

console.log("用 ASN1 解析 CSR 失去二进制构造:");
csrASN1=ASN1.ParsePEM(csr);
console.log(csrASN1);

console.log("用 ASN1 解析私钥失去二进制构造:");
privateKeyASN1=ASN1.ParsePEM(privateKey);
console.log(privateKeyASN1);

console.log("用 ASN1 解析公钥失去二进制构造:");
publicKeyASN1=ASN1.ParsePEM(publicKey);
console.log(publicKeyASN1);

【END】

退出移动版