Skip to content

Commit

Permalink
tls-alpn: add a function to return PEM blocks. (#579)
Browse files Browse the repository at this point in the history
* feature(tls-alpn): add function to return PEM blocks.
  • Loading branch information
ldez committed Jun 18, 2018
1 parent d457f70 commit 57782ac
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 26 deletions.
55 changes: 32 additions & 23 deletions acme/tls_alpn_challenge.go
Expand Up @@ -11,9 +11,8 @@ import (
"github.com/xenolf/lego/log"
)

// idPeAcmeIdentifierV1 is the SMI Security for PKIX Certification Extension
// OID referencing the ACME extension. Reference:
// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-5.1
// idPeAcmeIdentifierV1 is the SMI Security for PKIX Certification Extension OID referencing the ACME extension.
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-5.1
var idPeAcmeIdentifierV1 = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 30, 1}

type tlsALPNChallenge struct {
Expand Down Expand Up @@ -46,31 +45,20 @@ func (t *tlsALPNChallenge) Solve(chlng challenge, domain string) error {
return t.validate(t.jws, domain, chlng.URL, challenge{Type: chlng.Type, Token: chlng.Token, KeyAuthorization: keyAuth})
}

// TLSALPNChallengeCert returns a certificate with the acmeValidation-v1
// extension and domain name for the `tls-alpn-01` challenge.
func TLSALPNChallengeCert(domain, keyAuth string) (*tls.Certificate, error) {
// Generate a new RSA key for the certificates.
tempPrivKey, err := generatePrivateKey(RSA2048)
if err != nil {
return nil, err
}

// Encode the private key into a PEM format. We'll need to use it to
// generate the x509 keypair.
rsaPrivKey := tempPrivKey.(*rsa.PrivateKey)
rsaPrivPEM := pemEncode(rsaPrivKey)

// TLSALPNChallengeBlocks returns PEM blocks (certPEMBlock, keyPEMBlock) with the acmeValidation-v1 extension
// and domain name for the `tls-alpn-01` challenge.
func TLSALPNChallengeBlocks(domain, keyAuth string) ([]byte, []byte, error) {
// Compute the SHA-256 digest of the key authorization.
zBytes := sha256.Sum256([]byte(keyAuth))

value, err := asn1.Marshal(zBytes[:sha256.Size])
if err != nil {
return nil, err
return nil, nil, err
}

// Add the keyAuth digest as the acmeValidation-v1 extension (marked as
// critical such that it won't be used by non-ACME software). Reference:
// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-3
// Add the keyAuth digest as the acmeValidation-v1 extension
// (marked as critical such that it won't be used by non-ACME software).
// Reference: https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-3
extensions := []pkix.Extension{
{
Id: idPeAcmeIdentifierV1,
Expand All @@ -79,9 +67,30 @@ func TLSALPNChallengeCert(domain, keyAuth string) (*tls.Certificate, error) {
},
}

// Generate the PEM certificate using the provided private key, domain, and
// extra extensions.
// Generate a new RSA key for the certificates.
tempPrivKey, err := generatePrivateKey(RSA2048)
if err != nil {
return nil, nil, err
}

rsaPrivKey := tempPrivKey.(*rsa.PrivateKey)

// Generate the PEM certificate using the provided private key, domain, and extra extensions.
tempCertPEM, err := generatePemCert(rsaPrivKey, domain, extensions)
if err != nil {
return nil, nil, err
}

// Encode the private key into a PEM format. We'll need to use it to generate the x509 keypair.
rsaPrivPEM := pemEncode(rsaPrivKey)

return tempCertPEM, rsaPrivPEM, nil
}

// TLSALPNChallengeCert returns a certificate with the acmeValidation-v1 extension
// and domain name for the `tls-alpn-01` challenge.
func TLSALPNChallengeCert(domain, keyAuth string) (*tls.Certificate, error) {
tempCertPEM, rsaPrivPEM, err := TLSALPNChallengeBlocks(domain, keyAuth)
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions acme/tls_alpn_challenge_server.go
Expand Up @@ -8,8 +8,8 @@ import (
)

const (
// acmeTLS1Protocol is the ALPN Protocol ID for the ACME-TLS/1 Protocol.
acmeTLS1Protocol = "acme-tls/1"
// ACMETLS1Protocol is the ALPN Protocol ID for the ACME-TLS/1 Protocol.
ACMETLS1Protocol = "acme-tls/1"

// defaultTLSPort is the port that the TLSALPNProviderServer will default to
// when no other port is provided.
Expand Down Expand Up @@ -55,7 +55,7 @@ func (t *TLSALPNProviderServer) Present(domain, token, keyAuth string) error {
// We must set that the `acme-tls/1` application level protocol is supported
// so that the protocol negotiation can succeed. Reference:
// https://tools.ietf.org/html/draft-ietf-acme-tls-alpn-01#section-5.2
tlsConf.NextProtos = []string{acmeTLS1Protocol}
tlsConf.NextProtos = []string{ACMETLS1Protocol}

// Create the listener with the created tls.Config.
t.listener, err = tls.Listen("tcp", net.JoinHostPort(t.iface, t.port), tlsConf)
Expand Down

0 comments on commit 57782ac

Please sign in to comment.