Current section
Files
Jump to
Current section
Files
lib/site_encrypt/acme/server/crypto.ex
defmodule SiteEncrypt.Acme.Server.Crypto do
@moduledoc false
alias X509.{CSR, PrivateKey, PublicKey, Certificate}
alias X509.Certificate.Extension
@spec sign_csr!(binary(), SiteEncrypt.Acme.Server.domains()) :: binary() | no_return()
def sign_csr!(der, domains) do
csr = CSR.from_der!(der)
unless CSR.valid?(csr), do: raise("CSR validation failed")
{ca_key, ca_cert} = ca_key_and_cert()
signed_csr =
csr
|> CSR.public_key()
|> server_cert(ca_key, ca_cert, domains)
|> Certificate.to_pem()
"#{signed_csr}\n#{Certificate.to_pem(ca_cert)}\n"
end
def self_signed_chain(domains) do
{ca_key, ca_cert} = ca_key_and_cert()
server_key = PrivateKey.new_rsa(2048)
server_cert =
server_key
|> PublicKey.derive()
|> server_cert(ca_key, ca_cert, domains)
%{
ca_cert: Certificate.to_pem(ca_cert),
server_cert: Certificate.to_pem(server_cert),
server_key: PrivateKey.to_pem(server_key)
}
end
defp ca_key_and_cert() do
ca_key = PrivateKey.new_rsa(2048)
ca_cert = Certificate.self_signed(ca_key, "/O=Site Encrypt/CN=Acme Server CA", template: :ca)
{ca_key, ca_cert}
end
defp server_cert(public_key, ca_key, ca_cert, domains) do
Certificate.new(
public_key,
"/O=Site Encrypt/CN=#{hd(domains)}",
ca_cert,
ca_key,
validity: 1000 * 365,
extensions: [subject_alt_name: Extension.subject_alt_name(domains)]
)
end
end