Deterministic private key with Go 1.20 #427

commit 234a8f6b8c
Author: cmeng <cmenginnz@gmail.com>
Date:   Tue May 16 10:26:19 2023 +1200

    allow users to specify a private key file

commit 85a7d96b0c
Author: cmeng <cmenginnz@gmail.com>
Date:   Tue May 16 10:25:20 2023 +1200

    generate deterministic key with a given seed
This commit is contained in:
Jaime Pillora
2023-07-09 21:53:02 +10:00
parent 79a5e78015
commit 60165db50a
3 changed files with 33 additions and 7 deletions
+7 -2
View File
@@ -3,7 +3,6 @@ package main
import (
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
@@ -87,7 +86,7 @@ var commonHelp = `
func generatePidFile() {
pid := []byte(strconv.Itoa(os.Getpid()))
if err := ioutil.WriteFile("chisel.pid", pid, 0644); err != nil {
if err := os.WriteFile("chisel.pid", pid, 0644); err != nil {
log.Fatal(err)
}
}
@@ -109,6 +108,11 @@ var serverHelp = `
of man-in-the-middle attacks (defaults to the CHISEL_KEY environment
variable, otherwise a new key is generate each run).
--key-file, An optional path to a PEM-encoded SSH private key. When
this flag is set, the --key option is ignored. A private key file
can be generated by:
openssl ecparam -name prime256v1 -genkey -out private_key.pem
--authfile, An optional path to a users.json file. This file should
be an object with users defined like:
{
@@ -170,6 +174,7 @@ func server(args []string) {
config := &chserver.Config{}
flags.StringVar(&config.KeySeed, "key", "", "")
flags.StringVar(&config.KeyFile, "key-file", "", "")
flags.StringVar(&config.AuthFile, "authfile", "", "")
flags.StringVar(&config.Auth, "auth", "", "")
flags.DurationVar(&config.KeepAlive, "keepalive", 25*time.Second, "")
+18 -4
View File
@@ -7,6 +7,7 @@ import (
"net/http"
"net/http/httputil"
"net/url"
"os"
"regexp"
"time"
@@ -23,6 +24,7 @@ import (
// Config is the configuration for the chisel service
type Config struct {
KeySeed string
KeyFile string
AuthFile string
Auth string
Proxy string
@@ -73,11 +75,23 @@ func NewServer(c *Config) (*Server, error) {
server.users.AddUser(u)
}
}
//generate private key (optionally using seed)
key, err := ccrypto.GenerateKey(c.KeySeed)
if err != nil {
log.Fatal("Failed to generate key")
var key []byte
var err error
if c.KeyFile != "" {
//read private key from the file specified path
key, err = os.ReadFile(c.KeyFile)
if err != nil {
log.Fatal("Failed to read private key from disk")
}
} else {
//generate private key (optionally using seed)
key, err = ccrypto.GenerateKey(c.KeySeed)
if err != nil {
log.Fatal("Failed to generate key")
}
}
//convert into ssh.PrivateKey
private, err := ssh.ParsePrivateKey(key)
if err != nil {
+8 -1
View File
@@ -34,7 +34,14 @@ func (d *determRand) Read(b []byte) (int, error) {
for n < l {
next, out := hash(d.next)
n += copy(b[n:], out)
d.next = next
// In Golang 1.20, ecdsa.GenerateKey() introduced a function called
// MaybeReadRand() which reads 1 byte from the determRand reader
// with 50% chance. As a result, GenerateKey() generates
// nondeterministic keys.
// The following conditional check neutralizes this effect.
if l > 1 {
d.next = next
}
}
return n, nil
}