Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cert expired checker #2

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cert/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@ module github.com/lightningnetwork/lnd/cert

go 1.13

require github.com/stretchr/testify v1.5.1
require (
github.com/btcsuite/btcd v0.21.0-beta
github.com/lightningnetwork/lnd v0.11.0-beta.rc4.0.20201120035502-0e14e0d904ce
github.com/stretchr/testify v1.5.1
)
296 changes: 296 additions & 0 deletions cert/go.sum

Large diffs are not rendered by default.

104 changes: 74 additions & 30 deletions cert/selfsigned.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
Expand All @@ -14,6 +15,9 @@ import (
"net"
"os"
"time"

"github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnencrypt"
)

const (
Expand Down Expand Up @@ -194,8 +198,10 @@ func IsOutdated(cert *x509.Certificate, tlsExtraIPs,
return false, nil
}

// GenCertPair generates a key/cert pair to the paths provided. The
// auto-generated certificates should *not* be used in production for public
// GenCertPair generates a key/cert pair to the paths provided if defined.
// The bytes of the generated certificate and private key are returned.
//
// The auto-generated certificates should *not* be used in production for public
// access as they're self-signed and don't necessarily contain all of the
// desired hostnames for the service. For production/public use, consider a
// real PKI.
Expand All @@ -204,7 +210,8 @@ func IsOutdated(cert *x509.Certificate, tlsExtraIPs,
// https://github.com/btcsuite/btcutil
func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
tlsExtraDomains []string, tlsDisableAutofill bool,
certValidity time.Duration) error {
certValidity time.Duration, encryptKey bool,
keyRing keychain.KeyRing, keyType string) ([]byte, []byte, error) {

now := time.Now()
validUntil := now.Add(certValidity)
Expand All @@ -217,21 +224,15 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
// Generate a serial number that's below the serialNumberLimit.
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return fmt.Errorf("failed to generate serial number: %s", err)
return nil, nil, fmt.Errorf("failed to generate serial number: %s", err)
}

// Get all DNS names and IP addresses to use when creating the
// certificate.
host, dnsNames := dnsNames(tlsExtraDomains, tlsDisableAutofill)
ipAddresses, err := ipAddresses(tlsExtraIPs, tlsDisableAutofill)
if err != nil {
return err
}

// Generate a private key for the certificate.
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return err
return nil, nil, err
}

// Construct the certificate template.
Expand All @@ -254,38 +255,81 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
IPAddresses: ipAddresses,
}

derBytes, err := x509.CreateCertificate(rand.Reader, &template,
&template, &priv.PublicKey, priv)
if err != nil {
return fmt.Errorf("failed to create certificate: %v", err)
// Generate a private key for the certificate.
var derBytes []byte
var keyBytes []byte
var encodeString string
if keyType == "ec" {
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return nil, nil, err
}

derBytes, err = x509.CreateCertificate(rand.Reader, &template,
&template, &priv.PublicKey, priv)
if err != nil {
return nil, nil, fmt.Errorf("failed to create certificate: %v", err)
}

keyBytes, err = x509.MarshalECPrivateKey(priv)
if err != nil {
return nil, nil, fmt.Errorf("unable to encode privkey: %v", err)
}
encodeString = "EC PRIVATE KEY"
} else if keyType == "rsa" {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, err
}

derBytes, err = x509.CreateCertificate(rand.Reader, &template,
&template, &priv.PublicKey, priv)
if err != nil {
return nil, nil, fmt.Errorf("failed to create certificate: %v", err)
}

keyBytes = x509.MarshalPKCS1PrivateKey(priv)
if err != nil {
return nil, nil, fmt.Errorf("unable to encode privkey: %v", err)
}
encodeString = "RSA PRIVATE KEY"
} else {
return nil, nil, fmt.Errorf("Unknown keyType: %s", keyType)
}

certBuf := &bytes.Buffer{}
err = pem.Encode(certBuf, &pem.Block{Type: "CERTIFICATE",
Bytes: derBytes})
if err != nil {
return fmt.Errorf("failed to encode certificate: %v", err)
return nil, nil, fmt.Errorf("failed to encode certificate: %v", err)
}

keybytes, err := x509.MarshalECPrivateKey(priv)
if err != nil {
return fmt.Errorf("unable to encode privkey: %v", err)
}
keyBuf := &bytes.Buffer{}
err = pem.Encode(keyBuf, &pem.Block{Type: "EC PRIVATE KEY",
Bytes: keybytes})
err = pem.Encode(keyBuf, &pem.Block{Type: encodeString,
Bytes: keyBytes})
if err != nil {
return fmt.Errorf("failed to encode private key: %v", err)
return nil, nil, fmt.Errorf("failed to encode private key: %v", err)
}

// Write cert and key files.
if err = ioutil.WriteFile(certFile, certBuf.Bytes(), 0644); err != nil {
return err
// Write cert and key files. Ensures the paths are defined before writing.
if certFile != "" {
if err = ioutil.WriteFile(certFile, certBuf.Bytes(), 0644); err != nil {
return nil, nil, err
}
}
if err = ioutil.WriteFile(keyFile, keyBuf.Bytes(), 0600); err != nil {
os.Remove(certFile)
return err
if keyFile != "" {
keyPayload := keyBuf.Bytes()
// If the user requests the TLS key to be encrypted on disk we do so
if encryptKey {
var b bytes.Buffer
lnencrypt.EncryptPayloadToWriter(*keyBuf, &b, keyRing)
keyPayload = b.Bytes()
}
if err = ioutil.WriteFile(keyFile, keyPayload, 0600); err != nil {
os.Remove(certFile)
return nil, nil, err
}
}

return nil
return certBuf.Bytes(), keyBuf.Bytes(), nil
}
Loading