Skip to content

Commit

Permalink
main,gencerts: Punycode non-ASCII hostnames
Browse files Browse the repository at this point in the history
When a certificate is autogenerated by dcrd or with gencerts, errors would
occur if any hostname contained non-ASCII characters.  While X509 certificates
do support UTF8 strings, Go does not yet support creating these.

Instead, as a workaround and to keep certificate generation working to avoid
errors at dcrd startup, convert hostnames with non-ASCII Unicode characters to
their IDNA form, which uses Punycode to ASCII-encode the problematic Unicode
characters.
  • Loading branch information
jrick authored and davecgh committed Aug 21, 2024
1 parent 820c0fa commit bd6e4f4
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 2 deletions.
24 changes: 24 additions & 0 deletions certgen/certgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,21 @@ import (
"net"
"os"
"time"
"unicode"

"github.com/decred/dcrd/crypto/rand"
"golang.org/x/net/idna"
)

func isASCII(s string) bool {
for _, c := range s {
if c > unicode.MaxASCII {
return false
}
}
return true
}

// NewTLSCertPair returns a new PEM-encoded x.509 certificate pair with new
// ECDSA keys. The machine's local interface addresses and all variants of IPv4
// and IPv6 localhost are included as valid IP addresses.
Expand Down Expand Up @@ -50,6 +61,12 @@ func NewTLSCertPair(curve elliptic.Curve, organization string, validUntil time.T
if err != nil {
return nil, nil, err
}
if !isASCII(host) {
host, err = idna.ToASCII(host)
if err != nil {
return nil, nil, err
}
}

ipAddresses := []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}
dnsNames := []string{host}
Expand All @@ -71,6 +88,13 @@ func NewTLSCertPair(curve elliptic.Curve, organization string, validUntil time.T
return
}
}
if !isASCII(host) {
var err error
host, err = idna.ToASCII(host)
if err != nil {
return
}
}
dnsNames = append(dnsNames, host)
}

Expand Down
6 changes: 5 additions & 1 deletion certgen/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ module github.com/decred/dcrd/certgen

go 1.18

require github.com/decred/dcrd/crypto/rand v1.0.0
require (
github.com/decred/dcrd/crypto/rand v1.0.0
golang.org/x/net v0.21.0
)

require (
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
)
4 changes: 4 additions & 0 deletions certgen/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ github.com/decred/dcrd/crypto/rand v1.0.0 h1:Ah9Asl36OZt09sGSMbJZuL1HfwGdlC38q/Z
github.com/decred/dcrd/crypto/rand v1.0.0/go.mod h1:coa7BbxSTiKH6esi257plGfMFYuGL4MTbQlLYnOdzpE=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
26 changes: 26 additions & 0 deletions cmd/gencerts/gencerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ import (
"net"
"os"
"time"
"unicode"

"github.com/decred/dcrd/crypto/rand"
flags "github.com/jessevdk/go-flags"
"golang.org/x/net/idna"
)

func fatalf(format string, args ...interface{}) {
Expand Down Expand Up @@ -212,6 +214,15 @@ type certWithPEM struct {
Cert *x509.Certificate
}

func isASCII(s string) bool {
for _, c := range s {
if c > unicode.MaxASCII {
return false
}
}
return true
}

func newTemplate(hosts []string, org string, validUntil time.Time) (*x509.Certificate, error) {
now := time.Now()
if validUntil.After(endOfTime) {
Expand All @@ -229,13 +240,28 @@ func newTemplate(hosts []string, org string, validUntil time.Time) (*x509.Certif
var hostnames []string
var ips []net.IP
for _, h := range hosts {
if !isASCII(h) {
var err error
h, err = idna.ToASCII(h)
if err != nil {
return nil, err
}
}
if ip := net.ParseIP(h); ip != nil {
ips = append(ips, ip)
continue
}
hostnames = append(hostnames, h)
}

if !isASCII(cn) {
var err error
cn, err = idna.ToASCII(cn)
if err != nil {
return nil, err
}
}

template := &x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ require (
github.com/jrick/bitset v1.0.0
github.com/jrick/logrotate v1.0.0
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
golang.org/x/net v0.25.0
golang.org/x/sys v0.21.0
golang.org/x/term v0.21.0
lukechampine.com/blake3 v1.3.0
Expand All @@ -55,8 +56,8 @@ require (
github.com/golang/snappy v0.0.4 // indirect
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/text v0.16.0 // indirect
)

replace (
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
Expand Down

0 comments on commit bd6e4f4

Please sign in to comment.