#tls-certificate #acme #letsencrypt #async #encryption #private-key #api-bindings

hyperacme

异步库,用于从 ACME 提供商请求证书(acme-micro 分支)

1 个不稳定版本

0.0.3 2022年4月14日
0.0.2 2022年4月13日
0.0.1 2022年4月13日

#2029 in 网页编程

Download history 9/week @ 2024-03-10 3/week @ 2024-03-24 58/week @ 2024-03-31 1/week @ 2024-04-07 6/week @ 2024-05-19 46/week @ 2024-06-02 6/week @ 2024-06-09 13/week @ 2024-06-16 1/week @ 2024-06-23

66 每月下载次数
用于 certsd

MIT 许可证

87KB
1.5K SLoC

hyperacme

hyperacme 是 acme-micro 的分支,而 acme-lib 又是它的分支,允许使用 ReqwestTokio 以异步方式访问 ACME(自动证书管理环境)服务,如 Let's Encrypt

使用 ACME v2 版本颁发/更新证书。

示例

 use hyperacme::{Error, Certificate, Directory, DirectoryUrl};
 use hyperacme::create_p384_key;
 use std::time::Duration;

 async fn request_cert() -> Result<Certificate, Error> {

 // Use DirectoryUrl::LetsEncrypStaging for dev/testing.
 let url = DirectoryUrl::LetsEncrypt;

 // Create a directory entrypoint.
 let dir = Directory::from_url(url).await?;

 // Your contact addresses, note the `mailto:`
 let contact = vec!["mailto:[email protected]".to_string()];

 // Generate a private key and register an account with your ACME provider.
 // You should write it to disk any use `load_account` afterwards.
 let acc = dir.register_account(contact.clone()).await?;

 // Example of how to load an account from string:
 let privkey = acc.acme_private_key_pem().await?;
 let acc = dir.load_account(&privkey, contact).await?;

 // Order a new TLS certificate for a domain.
 let mut ord_new = acc.new_order("example.com", &[]).await?;

 // If the ownership of the domain(s) have already been
 // authorized in a previous order, you might be able to
 // skip validation. The ACME API provider decides.
 let ord_csr = loop {
     // are we done?
     if let Some(ord_csr) = ord_new.confirm_validations().await {
         break ord_csr;
     }

     // Get the possible authorizations (for a single domain
     // this will only be one element).
     let auths = ord_new.authorizations().await?;

     // For HTTP, the challenge is a text file that needs to
     // be placed in your web server's root:
     //
     // /var/www/.well-known/acme-challenge/<token>
     //
     // The important thing is that it's accessible over the
     // web for the domain(s) you are trying to get a
     // certificate for:
     //
     // http://example.com/.well-known/acme-challenge/<token>
     let chall = auths[0].http_challenge().await.unwrap();

     // The token is the filename.
     let token = chall.http_token().await;
     let path = format!(".well-known/acme-challenge/{}", token);

     // The proof is the contents of the file
     let proof = chall.http_proof().await?;

     // Here you must do "something" to place
     // the file/contents in the correct place.
     // update_my_web_server(&path, &proof);

     // After the file is accessible from the web, the calls
     // this to tell the ACME API to start checking the
     // existence of the proof.
     //
     // The order at ACME will change status to either
     // confirm ownership of the domain, or fail due to the
     // not finding the proof. To see the change, we poll
     // the API with 5000 milliseconds wait between.
     chall.validate(Duration::from_millis(5000)).await?;

     // Update the state against the ACME API.
     ord_new.refresh().await?;
 };

 // Ownership is proven. Create a private key for
 // the certificate. These are provided for convenience, you
 // can provide your own keypair instead if you want.
 let pkey_pri = create_p384_key()?;

 // Submit the CSR. This causes the ACME provider to enter a
 // state of "processing" that must be polled until the
 // certificate is either issued or rejected. Again we poll
 // for the status change.
 let ord_cert =
     ord_csr.finalize_pkey(pkey_pri, Duration::from_millis(5000)).await?;

 // Now download the certificate. Also stores the cert in
 // the persistence.
 let cert = ord_cert.download_cert().await?;
 println!("{:?}", cert);

 Ok(cert)
 }

域名所有权

大多数网站 TLS 证书试图证明对颁发给它们的域的所有权/控制权。对于 ACME,这意味着证明您控制着响应域 HTTP 请求的 web 服务器,或者响应域名称查询的 DNS 服务器。

要使用此库,流程中有需要修改 web 服务器或 DNS 服务器才能继续获取证书的点。

请参阅 http_challengedns_challenge

多个域名

在创建新订单时,可以提供多个备选名称,它们也将成为证书的一部分。ACME API 要求您证明对每个此类域的所有权。请参阅 authorizations

速率限制

ACME API提供者Let's Encrypt使用速率限制以确保API不被滥用。在库的一些轮询调用中降低delay_millis可能很有诱惑力,但请权衡这种做法可能带来的实际风险,即访问被切断。

使用测试环境进行开发!

特别小心使用Let`s Encrypt的测试环境进行开发,那里的速率限制更为宽松。

请参见DirectoryUrl::LetsEncryptStaging

实现细节

它遵循ACME草案规范18编写,并大量依赖于openssl crate来生成JWK/JWT和向API发送签名请求。未来可能出现RusTLS/BoringSSL版本。

许可:MIT

依赖项

~8–24MB
~337K SLoC