From 035f8f82b73178580e229327fd8bcf20202686eb Mon Sep 17 00:00:00 2001
From: Josh Rickmar <jrick@conformal.com>
Date: Fri, 10 Jan 2014 14:45:04 -0500
Subject: [PATCH] Switch to btcutil for certificate generation.

---
 blockmanager.go |  2 +-
 rpcserver.go    | 97 ++++++-------------------------------------------
 2 files changed, 13 insertions(+), 86 deletions(-)

diff --git a/blockmanager.go b/blockmanager.go
index 0ad5c6ac..6d40051f 100644
--- a/blockmanager.go
+++ b/blockmanager.go
@@ -252,7 +252,7 @@ func (b *blockManager) handleDonePeerMsg(peers *list.List, p *peer) {
 	// Attempt to find a new peer to sync from if the quitting peer is the
 	// sync peer.
 	if b.syncPeer != nil && b.syncPeer == p {
-		if b.fetchingHeaders  {
+		if b.fetchingHeaders {
 			b.fetchingHeaders = false
 			b.startBlock = nil
 			b.fetchBlock = nil
diff --git a/rpcserver.go b/rpcserver.go
index 6a353ef9..018727c0 100644
--- a/rpcserver.go
+++ b/rpcserver.go
@@ -8,18 +8,11 @@ import (
 	"bytes"
 	"code.google.com/p/go.net/websocket"
 	"container/list"
-	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
 	"crypto/sha256"
-	_ "crypto/sha512" // for cert generation
 	"crypto/subtle"
 	"crypto/tls"
-	"crypto/x509"
-	"crypto/x509/pkix"
 	"encoding/base64"
 	"encoding/hex"
-	"encoding/pem"
 	"errors"
 	"fmt"
 	"github.com/conformal/btcchain"
@@ -28,6 +21,7 @@ import (
 	"github.com/conformal/btcscript"
 	"github.com/conformal/btcutil"
 	"github.com/conformal/btcwire"
+	"io/ioutil"
 	"math/big"
 	"net"
 	"net/http"
@@ -215,94 +209,27 @@ func (s *rpcServer) Stop() error {
 	return nil
 }
 
-// genkey generates a key/cert pair to the paths provided.
-// TODO(oga) wrap errors with fmt.Errorf for more context?
-func genKey(key, cert string) error {
+// genCertPair generates a key/cert pair to the paths provided.
+func genCertPair(certFile, keyFile string) error {
 	rpcsLog.Infof("Generating TLS certificates...")
-	priv, err := ecdsa.GenerateKey(elliptic.P521(), rand.Reader)
+
+	org := "btcd autogenerated cert"
+	validUntil := time.Now().Add(10 * 365 * 24 * time.Hour)
+	cert, key, err := btcutil.NewTLSCertPair(org, validUntil, nil)
 	if err != nil {
 		return err
 	}
 
-	notBefore := time.Now()
-	notAfter := notBefore.Add(10 * 365 * 24 * time.Hour)
-
-	// end of ASN.1 time
-	endOfTime := time.Date(2049, 12, 31, 23, 59, 59, 0, time.UTC)
-	if notAfter.After(endOfTime) {
-		notAfter = endOfTime
-	}
-
-	template := x509.Certificate{
-		SerialNumber: new(big.Int).SetInt64(0),
-		Subject: pkix.Name{
-			Organization: []string{"btcd autogenerated cert"},
-		},
-		NotBefore: notBefore,
-		NotAfter:  notAfter,
-
-		KeyUsage:    x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign,
-		ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
-		IsCA:        true, // so can sign self.
-		BasicConstraintsValid: true,
-	}
-
-	host, err := os.Hostname()
-	if err != nil {
+	// Write cert and key files.
+	if err = ioutil.WriteFile(certFile, cert, 0666); err != nil {
 		return err
 	}
-	template.DNSNames = append(template.DNSNames, host, "localhost")
-
-	needLocalhost := true
-	addrs, err := net.InterfaceAddrs()
-	if err != nil {
+	if err = ioutil.WriteFile(keyFile, key, 0600); err != nil {
+		os.Remove(certFile)
 		return err
 	}
-	for _, a := range addrs {
-		ip, _, err := net.ParseCIDR(a.String())
-		if err == nil {
-			if ip.String() == "127.0.0.1" {
-				needLocalhost = false
-			}
-			template.IPAddresses = append(template.IPAddresses, ip)
-		}
-	}
-	if needLocalhost {
-		localHost := net.ParseIP("127.0.0.1")
-		template.IPAddresses = append(template.IPAddresses, localHost)
-	}
-
-	derBytes, err := x509.CreateCertificate(rand.Reader, &template,
-		&template, &priv.PublicKey, priv)
-	if err != nil {
-		fmt.Fprintf(os.Stderr, "Failed to create certificate: %v\n", err)
-		os.Exit(-1)
-	}
-
-	certOut, err := os.Create(cert)
-	if err != nil {
-		return err
-	}
-	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
-	certOut.Close()
-
-	keyOut, err := os.OpenFile(key, os.O_WRONLY|os.O_CREATE|os.O_TRUNC,
-		0600)
-	if err != nil {
-		os.Remove(cert)
-		return err
-	}
-	keybytes, err := x509.MarshalECPrivateKey(priv)
-	if err != nil {
-		os.Remove(key)
-		os.Remove(cert)
-		return err
-	}
-	pem.Encode(keyOut, &pem.Block{Type: "EC PRIVATE KEY", Bytes: keybytes})
-	keyOut.Close()
 
 	rpcsLog.Infof("Done generating TLS certificates")
-
 	return nil
 }
 
@@ -326,7 +253,7 @@ func newRPCServer(listenAddrs []string, s *server) (*rpcServer, error) {
 	// check for existence of cert file and key file
 	if !fileExists(cfg.RPCKey) && !fileExists(cfg.RPCCert) {
 		// if both files do not exist, we generate them.
-		err := genKey(cfg.RPCKey, cfg.RPCCert)
+		err := genCertPair(cfg.RPCCert, cfg.RPCKey)
 		if err != nil {
 			return nil, err
 		}