Skip to content
This repository has been archived by the owner on Jun 25, 2024. It is now read-only.

[WIP] Update External SSL Support for Unified RPC #3

Open
wants to merge 1 commit into
base: volt-encrypt-tls-key
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
63 changes: 45 additions & 18 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 @@ -16,7 +17,7 @@ import (
"time"

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

const (
Expand Down Expand Up @@ -210,7 +211,7 @@ func IsOutdated(cert *x509.Certificate, tlsExtraIPs,
func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
tlsExtraDomains []string, tlsDisableAutofill bool,
certValidity time.Duration, encryptKey bool,
keyRing keychain.KeyRing) ([]byte, []byte, error) {
keyRing keychain.KeyRing, keyType string) ([]byte, []byte, error) {

now := time.Now()
validUntil := now.Add(certValidity)
Expand All @@ -234,12 +235,6 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
return nil, nil, err
}

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

// Construct the certificate template.
template := x509.Certificate{
SerialNumber: serialNumber,
Expand All @@ -260,10 +255,46 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
IPAddresses: ipAddresses,
}

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)
// 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{}
Expand All @@ -273,13 +304,9 @@ func GenCertPair(org, certFile, keyFile string, tlsExtraIPs,
return nil, nil, fmt.Errorf("failed to encode certificate: %v", err)
}

keybytes, err := x509.MarshalECPrivateKey(priv)
if err != nil {
return nil, nil, 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 nil, nil, fmt.Errorf("failed to encode private key: %v", err)
}
Expand Down
10 changes: 5 additions & 5 deletions cert/selfsigned_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestIsOutdatedCert(t *testing.T) {
_, _, err = cert.GenCertPair(
"lnd autogenerated cert", certPath, keyPath, extraIPs[:2],
extraDomains[:2], false, cert.DefaultAutogenValidity,
false, keyRing,
false, keyRing, "ec",
)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -108,7 +108,7 @@ func TestIsOutdatedPermutation(t *testing.T) {
_, _, err = cert.GenCertPair(
"lnd autogenerated cert", certPath, keyPath, extraIPs[:],
extraDomains[:], false, cert.DefaultAutogenValidity,
false, keyRing,
false, keyRing, "ec",
)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -185,7 +185,7 @@ func TestTLSDisableAutofill(t *testing.T) {
_, _, err = cert.GenCertPair(
"lnd autogenerated cert", certPath, keyPath, extraIPs[:2],
extraDomains[:2], true, cert.DefaultAutogenValidity,
false, keyRing,
false, keyRing, "ec",
)
require.NoError(
t, err,
Expand Down Expand Up @@ -253,7 +253,7 @@ func TestTlsConfig(t *testing.T) {
_, _, err = cert.GenCertPair(
"lnd autogenerated cert", certPath, keyPath, []string{extraIPs[0]},
[]string{extraDomains[0]}, false, cert.DefaultAutogenValidity,
false, keyRing,
false, keyRing, "ec",
)
if err != nil {
t.Fatal(err)
Expand Down Expand Up @@ -325,7 +325,7 @@ func TestEncryptedTlsConfig(t *testing.T) {
_, _, err = cert.GenCertPair(
"lnd autogenerated cert", certPath, keyPath, []string{extraIPs[0]},
[]string{extraDomains[0]}, false, cert.DefaultAutogenValidity,
true, keyRing,
true, keyRing, "ec",
)
if err != nil {
t.Fatal(err)
Expand Down
37 changes: 32 additions & 5 deletions cert/tls.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"strings"
"sync"
)

Expand All @@ -24,6 +25,10 @@ var (
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
}
tlsRSACipherSuites = []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
}
)

type TlsReloader struct {
Expand Down Expand Up @@ -72,12 +77,34 @@ func LoadCert(certBytes, keyBytes []byte) (tls.Certificate, *x509.Certificate,

// TLSConfFromCert returns the default TLS configuration used for a server,
// using the given certificate as identity.
func TLSConfFromCert(certData tls.Certificate) *tls.Config {
return &tls.Config{
Certificates: []tls.Certificate{certData},
CipherSuites: tlsCipherSuites,
MinVersion: tls.VersionTLS12,
func TLSConfFromCert(certData []tls.Certificate) *tls.Config {
var config *tls.Config

getCertificate := func(h *tls.ClientHelloInfo) (*tls.Certificate, error) {
defaultCertList := []string{"localhost", "127.0.0.1"}
for _, host := range defaultCertList {
if strings.Contains(h.ServerName, host) {
return &certData[0], nil
}
}
return &certData[1], nil
}

if len(certData) > 1 {
config = &tls.Config{
Certificates: []tls.Certificate{certData[0]},
GetCertificate: getCertificate,
CipherSuites: tlsRSACipherSuites,
MinVersion: tls.VersionTLS12,
}
} else {
config = &tls.Config{
Certificates: []tls.Certificate{certData[0]},
CipherSuites: tlsCipherSuites,
MinVersion: tls.VersionTLS12,
}
}
return config
}

// NewTLSReloader is used to create a new TLS Reloader that will be used
Expand Down
Loading