Skip to content

Commit

Permalink
Merge pull request #32 from dinghram/ipsan
Browse files Browse the repository at this point in the history
enable IP addresses in SAN
  • Loading branch information
necheffa authored Jan 22, 2024
2 parents 57c8b8d + 8fbca27 commit 88f8d10
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 3 deletions.
6 changes: 5 additions & 1 deletion ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/pem"
"errors"
"io/fs"
"net"
"os"
"path/filepath"
"time"
Expand All @@ -32,6 +33,7 @@ type Identity struct {
Province string `json:"province" example:"Veldhoven"` // Province name
EmailAddresses string `json:"email" example:"sec@company.com"` // Email Address
DNSNames []string `json:"dns_names" example:"ca.example.com,root-ca.example.com"` // DNS Names list
IPAddresses []net.IP `json:"ip_addresses,omitempty" example:"127.0.0.1,192.168.0.1"` // IP Address list
Intermediate bool `json:"intermediate" example:"false"` // Intermendiate Certificate Authority (default is false)
KeyBitSize int `json:"key_size" example:"2048"` // Key Bit Size (defaul: 2048)
Valid int `json:"valid" example:"365"` // Minimum 1 day, maximum 825 days -- Default: 397
Expand Down Expand Up @@ -138,6 +140,7 @@ func (c *CA) create(commonName, parentCommonName string, id Identity) error {
id.EmailAddresses,
id.Valid,
id.DNSNames,
id.IPAddresses,
privKey,
pubKey,
storage.CreationTypeCA,
Expand Down Expand Up @@ -167,6 +170,7 @@ func (c *CA) create(commonName, parentCommonName string, id Identity) error {
id.EmailAddresses,
id.Valid,
id.DNSNames,
id.IPAddresses,
privKey,
parentPrivateKey,
parentCertificate,
Expand Down Expand Up @@ -367,7 +371,7 @@ func (c *CA) issueCertificate(commonName string, id Identity) (certificate Certi
certificate.publicKey = *pubKey
certificate.PublicKey = string(publicKeyString)

csrBytes, err := cert.CreateCSR(c.CommonName, commonName, id.Country, id.Province, id.Locality, id.Organization, id.OrganizationalUnit, id.EmailAddresses, id.DNSNames, privKey, storage.CreationTypeCertificate)
csrBytes, err := cert.CreateCSR(c.CommonName, commonName, id.Country, id.Province, id.Locality, id.Organization, id.OrganizationalUnit, id.EmailAddresses, id.DNSNames, id.IPAddresses, privKey, storage.CreationTypeCertificate)
if err != nil {
return certificate, err
}
Expand Down
11 changes: 9 additions & 2 deletions cert/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"encoding/pem"
"errors"
"math/big"
"net"
"path/filepath"
"time"

Expand Down Expand Up @@ -72,7 +73,7 @@ func newSerialNumber() (serialNumber *big.Int) {
// CreateCSR creates a Certificate Signing Request returning certData with CSR.
//
// The CSR is also stored in $CAPATH with extension .csr
func CreateCSR(CACommonName, commonName, country, province, locality, organization, organizationalUnit, emailAddresses string, dnsNames []string, priv *rsa.PrivateKey, creationType storage.CreationType) (csr []byte, err error) {
func CreateCSR(CACommonName, commonName, country, province, locality, organization, organizationalUnit, emailAddresses string, dnsNames []string, ipAddresses []net.IP, priv *rsa.PrivateKey, creationType storage.CreationType) (csr []byte, err error) {
var oidEmailAddress = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}

subject := pkix.Name{
Expand All @@ -93,6 +94,7 @@ func CreateCSR(CACommonName, commonName, country, province, locality, organizati
RawSubject: asn1Subj,
EmailAddresses: []string{emailAddresses},
SignatureAlgorithm: x509.SHA256WithRSA,
IPAddresses: ipAddresses,
}

dnsNames = append(dnsNames, commonName)
Expand Down Expand Up @@ -184,6 +186,7 @@ func CreateRootCert(
emailAddresses string,
valid int,
dnsNames []string,
ipAddresses []net.IP,
privateKey *rsa.PrivateKey,
publicKey *rsa.PublicKey,
creationType storage.CreationType,
Expand All @@ -199,6 +202,7 @@ func CreateRootCert(
emailAddresses,
valid,
dnsNames,
ipAddresses,
privateKey,
nil, // parentPrivateKey
nil, // parentCertificate
Expand All @@ -223,6 +227,7 @@ func CreateCACert(
emailAddresses string,
validDays int,
dnsNames []string,
ipAddresses []net.IP,
privateKey,
parentPrivateKey *rsa.PrivateKey,
parentCertificate *x509.Certificate,
Expand Down Expand Up @@ -250,6 +255,7 @@ func CreateCACert(
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
BasicConstraintsValid: true,
IPAddresses: ipAddresses,
}
dnsNames = append(dnsNames, commonName)
caCert.DNSNames = dnsNames
Expand Down Expand Up @@ -346,7 +352,8 @@ func CASignCSR(CACommonName string, csr x509.CertificateRequest, caCert *x509.Ce
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(0, 0, valid),
KeyUsage: x509.KeyUsageDigitalSignature,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
IPAddresses: csr.IPAddresses,
}

csrTemplate.DNSNames = csr.DNSNames
Expand Down
13 changes: 13 additions & 0 deletions goca_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package goca

import (
"fmt"
"net"
"os"
"path/filepath"
"slices"
"testing"
)

Expand Down Expand Up @@ -106,6 +108,7 @@ func TestFunctionalRootCAIssueNewCertificate(t *testing.T) {
Province: "Veldhoven",
Intermediate: true,
DNSNames: []string{"w3.intranet.go-root.ca"},
IPAddresses: []net.IP{net.IPv4(192, 168, 17, 243)},
}

RootCA, err := Load("go-root.ca")
Expand Down Expand Up @@ -135,6 +138,16 @@ func TestFunctionalRootCAIssueNewCertificate(t *testing.T) {
if fi.Mode() != GoodKeyPerms {
t.Errorf("Expected key.pem permissions " + fmt.Sprint(GoodKeyPerms) + " but got: " + fmt.Sprint(fi.Mode()))
}

if !slices.Contains(intranetCert.certificate.DNSNames, intranteIdentity.DNSNames[0]) {
t.Errorf("Expected issued certificate to have DNS SAN %q but got: %q", intranteIdentity.DNSNames[0], intranetCert.certificate.DNSNames)
}

if !slices.ContainsFunc(intranetCert.certificate.IPAddresses, func(ip net.IP) bool {
return ip.Equal(intranteIdentity.IPAddresses[0])
}) {
t.Errorf("Expected issued certificate to have IP SAN %q but got: %q", intranteIdentity.IPAddresses[0], intranetCert.certificate.IPAddresses)
}
}

func TestFunctionalRootCALoadCertificates(t *testing.T) {
Expand Down

0 comments on commit 88f8d10

Please sign in to comment.