关于后端:新开源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】

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理