1 个不稳定版本
0.1.0 | 2021年7月26日 |
---|
#1811 in 加密学
71KB
918 行
acme-client
易于使用且兼容Let's Encrypt的ACME客户端,用于颁发、续订和吊销TLS证书。
分支
这个分支的分支发布为 acmev02
。由于升级了reqwest,所以去掉了openssl 0.9的依赖,这解决了我的rust-musl-builder构建问题。尚未更新README。
内容
安装
默认情况下,acme-client包附带一个方便的命令行界面。您可以使用以下命令安装acme-client: cargo install acme-client
或者您可以在 发布页面 下载预构建的Linux acme-client二进制文件。
使用
acme-client使用OpenSSL库生成所有必需的密钥和证书签名请求。您不需要运行任何openssl命令。如果您想要使用已经生成的密钥和CSR,并且不需要在运行acme-client时拥有root权限。
acme-client使用简单的HTTP验证来通过Let's Encrypt的DNS验证挑战。您需要一个工作的HTTP服务器来托管挑战文件。
签名证书
acme-client sign -D example.org -P /var/www -k domain.key -o domain.crt
此命令将生成用户密钥、域名密钥和X509证书签名请求。它将注册一个新用户账户,并通过将所需的挑战令牌放入 /var/www/.well-known/acme-challenge/
来识别域名所有权。如果一切顺利,它将把域名私钥保存到 domain.key
并将签名的证书保存到 domain.crt
。
您还可以使用 --email
选项在注册时提供联系地址。
使用自己的密钥和CSR
您可以使用自己的RSA密钥进行用户注册和域名设置。例如
acme-client sign \
--user-key user.key \
--domain-key domain.key \
--domain-csr domain.csr \
-P /var/www \
-o domain.crt
这不会生成任何密钥,而是使用提供的密钥来签署证书。它还将从提供的CSR文件中获取域名。
使用DNS验证
您可以使用--dns
标志来触发DNS验证,而不是HTTP。此选项要求用户为域名生成一个TXT记录。以下是一个DNS验证示例
$ acme-client sign --dns -D onur.im -E [email protected] \
-k /tmp/onur.im.key -o /tmp/onur.im.crt
Please create a TXT record for _acme-challenge.onur.im: fDdTmWl4RMuGqj9acJiTC13hF6dVOZUNm3FujCIz3jc
Press enter to continue
吊销已签名的证书
acme-client也可以撤销已签名的证书。您需要使用您的用户密钥和已签名的证书来撤销。
acme-client revoke --user-key user.key --signed-crt signed.crt
选项
您可以使用acme-client sign --help
和acme-client revoke --help
来获取所有可用选项的列表
$ acme-client sign --help
acme-client-sign
Signs a certificate
USAGE:
acme-client sign [FLAGS] [OPTIONS]
FLAGS:
-d, --dns Use DNS challenge instead of HTTP. This option requires
user to generate a TXT record for domain.
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-A, --directory <DIRECTORY>
Set ACME directory URL [default: https://acme-v01.api.letsencrypt.org/directory]
-D, --domain <DOMAIN>...
Domain name to obtain certificate. You can use more than one domain name.
-P, --public-dir <PUBLIC_DIR>
Directory to save ACME simple HTTP challenge. This option is
required unless --dns option is being used.
-U, --user-key <USER_KEY_PATH>
Path to load user private key to use it in account registration.
This is optional and acme-client will generate one if it's not supplied.
-C, --csr <DOMAIN_CSR>
Path to load domain certificate signing request. acme-client can also use CSR to get domain names.
This is optional and acme-client will generate one if it's not supplied.
-K, --domain-key <DOMAIN_KEY_PATH>
Path to load private domain key.
This is optional and acme-client will generate one if it's not supplied.
-E, --email <EMAIL>
Contact email address (optional).
-c, --save-chained-crt <SAVE_CHAINED_CERTIFICATE>
Chain signed certificate with Let's Encrypt Authority X3
(IdenTrust cross-signed) intermediate certificate and save to given path.
-r, --save-csr <SAVE_DOMAIN_CSR>
Path to save domain certificate signing request generated by acme-client.
-k, --save-domain-key <SAVE_DOMAIN_KEY>
Path to save domain private key generated by acme-client.
-i, --save-intermediate-crt <SAVE_INTERMEDIATE_CERTIFICATE>
Path to save intermediate certificate.
-o, --save-crt <SAVE_SIGNED_CERTIFICATE>
Path to save signed certificate. Default is STDOUT.
-u, --save-user-key <SAVE_USER_KEY>
Path to save private user key.
$ acme-client revoke --help
acme-client-revoke
Revokes a signed certificate
USAGE:
acme-client revoke --user-key <USER_KEY> --signed-crt <SIGNED_CRT>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-C, --signed-crt <SIGNED_CRT> Path to signed domain certificate to revoke.
-K, --user-key <USER_KEY> User or domain private key path.
还有genkey
和gencsr
子命令用于生成RSA私钥和CSR。您可以使用多个-v
标志以获得详细输出。
库
您可以在docs.rs中阅读整个API文档。您可以通过在Cargo.toml
中添加以下行来使用acme-client库
[dependencies]
acme-client = "0.5"
默认情况下acme-client
将构建CLI。您可以使用以下命令禁用此操作
[dependencies.acme-client]
version = "0.5"
default-features = false
API概述
要成功为域名签署SSL证书,您需要识别域名的所有权。您还可以为多个域名识别并签署证书,并显式使用您自己的私钥和证书签名请求(CSR),否则此库将生成它们。acme-client的基本用法
use acme_client::Directory;
let directory = Directory::lets_encrypt()?;
let account = directory.account_registration().register()?;
// Create a identifier authorization for example.com
let authorization = account.authorization("example.com")?;
// Validate ownership of example.com with http challenge
let http_challenge = authorization.get_http_challenge().ok_or("HTTP challenge not found")?;
http_challenge.save_key_authorization("/var/www")?;
http_challenge.validate()?;
let cert = account.certificate_signer(&["example.com"]).sign_certificate()?;
cert.save_signed_certificate("certificate.pem")?;
cert.save_private_key("certificate.key")?;
acme-client
支持使用SAN签署多个域名的证书。您需要验证每个域名的所有权
use acme_client::Directory;
let directory = Directory::lets_encrypt()?;
let account = directory.account_registration().register()?;
let domains = ["example.com", "example.org"];
for domain in domains.iter() {
let authorization = account.authorization(domain)?;
// ...
}
let cert = account.certificate_signer(&domains).sign_certificate()?;
cert.save_signed_certificate("certificate.pem")?;
cert.save_private_key("certificate.key")?;
账户注册
use acme_client::Directory;
let directory = Directory::lets_encrypt()?;
let account = directory.account_registration()
.email("[email protected]")
.register()?;
联系电子邮件地址是可选的。您也可以在注册时使用自己的私钥。有关更多信息,请参阅AccountRegistration辅助器。
如果您之前已经使用自己的密钥注册,您仍然需要使用register
方法,在这种情况下,它将识别您的用户帐户而不是创建一个新的帐户。
识别域名所有权
在向ACME服务器发送证书签名请求之前,您需要识别您想要为其签署证书的域名的所有权。为此,您需要为域名创建一个授权对象并至少完成一个挑战(http或dns用于Let's Encrypt)。
要为域名创建授权对象
let authorization = account.authorization("example.com")?;
Authorization对象将包含ACME服务器创建的挑战。您可以根据需要创建任意多的Authorization对象来验证域名的所有权。例如,如果您想为example.com
和example.org
签署证书
let domains = ["example.com", "example.org"];
for domain in domains.iter() {
let authorization = account.authorization(domain)?;
// ...
}
标识验证挑战
当您向ACME服务器发送授权请求时,它将生成标识验证挑战以提供保证,即账户持有人也是控制该标识的实体。
HTTP挑战
使用HTTP验证时,ACME事务中的客户端通过证明它可以在响应该域名的HTTP服务器上提供资源来证明其对域名控制权。
acme-client
具有save_key_authorization
方法来将验证文件保存到公共目录。此目录必须对外界可访问。
let authorization = account.authorization("example.com")?;
let http_challenge = authorization.get_http_challenge().ok_or("HTTP challenge not found")?;
// This method will save key authorization into
// /var/www/.well-known/acme-challenge/ directory.
http_challenge.save_key_authorization("/var/www")?;
// Validate ownership of example.com with http challenge
http_challenge.validate()?;
在验证过程中,ACME 服务器将检查 http://example.com/.well-known/acme-challenge/{token}
以识别域名所有权。您需要确保令牌是公开可访问的。
DNS挑战
DNS 挑战要求客户端在特定的验证域名下配置一个包含指定值的 TXT 记录。
acme-client
可以使用 signature
方法生成此值。
用户通过在待验证的域名前添加 "_acme-challenge" 标签来构建验证域名,然后在那个名称下配置一个包含摘要值的 TXT 记录。例如,如果待验证的域名是 "example.com",则客户端将配置以下 DNS 记录
_acme-challenge.example.com: dns_challenge.signature()
DNS 挑战示例验证
let authorization = account.authorization("example.com")?;
let dns_challenge = authorization.get_dns_challenge().ok_or("DNS challenge not found")?;
let signature = dns_challenge.signature()?;
// User creates a TXT record for _acme-challenge.example.com with the value of signature.
// Validate ownership of example.com with DNS challenge
dns_challenge.validate()?;
签名证书
验证所有域名后,您可以发送签名证书请求。 acme-client
提供了 CertificateSigner
助手来帮助您。您可以使用自己的密钥和 CSR,或者让 CertificateSigner
为您生成它们。
let domains = ["example.com", "example.org"];
// ... validate ownership of domain names
let certificate_signer = account.certificate_signer(&domains);
let cert = certificate_signer.sign_certificate()?;
cert.save_signed_certificate("certificate.pem")?;
cert.save_private_key("certificate.key")?;
吊销已签名的证书
您可以使用 revoke_certificate
或 revoke_certificate_from_file
方法撤销已签名的证书。您需要使用之前注册的相同私钥才能成功撤销已签名的证书。您还可以使用生成 CSR 的私钥。
let account = directory.account_registration()
.pkey_from_file("user.key")?
.register()?;
account.revoke_certificate_from_file("certificate.pem")?;
参考资料
依赖项
~12–26MB
~421K SLoC