Merge pull request #30 from bifurcation/mkstuff

Add mkroot and mkcrl
This commit is contained in:
bifurcation 2015-03-13 12:52:34 -07:00
commit 62cd2682be
3 changed files with 228 additions and 0 deletions

View File

@ -13,6 +13,9 @@ before_install:
- go get github.com/mattn/goveralls - go get github.com/mattn/goveralls
- go get github.com/modocache/gover - go get github.com/modocache/gover
install:
- go get -t -v -tags "pkcs11" ./...
script: script:
- go vet -x ./... - go vet -x ./...
- $HOME/gopath/bin/golint ./... - $HOME/gopath/bin/golint ./...

93
cmd/mkcrl/main.go Normal file
View File

@ -0,0 +1,93 @@
package main
import (
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"encoding/pem"
"flag"
"fmt"
"io/ioutil"
"time"
"github.com/cloudflare/cfssl/crypto/pkcs11key"
"github.com/cloudflare/cfssl/log"
)
var certFile = flag.String("ca", "", "JSON file for subject and validity")
var listFile = flag.String("revoked", "", "JSON file with a list of pkix.RevokedCertificate objects")
var module = flag.String("pkcs11-module", "", "PKCS#11 module")
var pin = flag.String("pkcs11-pin", "", "PKCS#11 password")
var token = flag.String("pkcs11-token", "", "PKCS#11 token name")
var label = flag.String("pkcs11-label", "", "PKCS#11 key label")
type Config struct {
ThisUpdate time.Time
NextUpdate time.Time
RevokedCerts []pkix.RevokedCertificate
}
func main() {
// Validate input
// All flags are required
flag.Parse()
missing := false
flag.VisitAll(func(f *flag.Flag) {
if len(f.Value.String()) == 0 {
missing = true
}
})
if missing {
log.Critical("All flags must be provided.")
flag.Usage()
return
}
// Read the issuer cert
certPEM, err := ioutil.ReadFile(*certFile)
if err != nil {
log.Criticalf("Unable to read certificate: %v", err)
return
}
certBlock, _ := pem.Decode(certPEM)
cert, err := x509.ParseCertificate(certBlock.Bytes)
if err != nil {
log.Criticalf("Unable to parse certificate: %v", err)
return
}
// Read the list of revoked certs
jsonConfig, err := ioutil.ReadFile(*listFile)
if err != nil {
log.Criticalf("Unable to read list of revoked certs: %v", err)
return
}
var config Config
err = json.Unmarshal(jsonConfig, &config)
if err != nil {
log.Criticalf("Unable to parse list of revoked certs: %v", err)
return
}
// Set up PKCS#11 key
priv, err := pkcs11key.New(*module, *token, *pin, *label)
if err != nil {
log.Criticalf("Unable to instantiate PKCS#11 private key: %v", err)
return
}
// Sign the CRL
crlDER, err := cert.CreateCRL(rand.Reader, priv, config.RevokedCerts, config.ThisUpdate, config.NextUpdate)
if err != nil {
log.Criticalf("Error signing certificate: %v", err)
return
}
fmt.Println(string(pem.EncodeToMemory(&pem.Block{
Type: "X509 CRL",
Bytes: crlDER,
})))
}

132
cmd/mkroot/main.go Normal file
View File

@ -0,0 +1,132 @@
package main
import (
"crypto/rand"
"crypto/sha1"
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"encoding/pem"
"flag"
"fmt"
"io/ioutil"
"math/big"
"time"
"github.com/cloudflare/cfssl/crypto/pkcs11key"
"github.com/cloudflare/cfssl/log"
)
var configFile = flag.String("config", "", "JSON file for subject and validity")
var module = flag.String("pkcs11-module", "", "PKCS#11 module")
var pin = flag.String("pkcs11-pin", "", "PKCS#11 password")
var token = flag.String("pkcs11-token", "", "PKCS#11 token name")
var label = flag.String("pkcs11-label", "", "PKCS#11 key label")
type Config struct {
Name struct {
C string
O string
OU string
CN string
}
NotBefore time.Time
NotAfter time.Time
}
func main() {
// Validate input
// All flags are required
flag.Parse()
missing := false
flag.VisitAll(func(f *flag.Flag) {
if len(f.Value.String()) == 0 {
missing = true
}
})
if missing {
log.Critical("All flags must be provided.")
flag.Usage()
return
}
jsonConfig, err := ioutil.ReadFile(*configFile)
if err != nil {
log.Criticalf("Unable to read config: %v", err)
return
}
var config Config
err = json.Unmarshal(jsonConfig, &config)
if err != nil {
log.Criticalf("Unable to parse config: %v", err)
return
}
if len(config.Name.C) == 0 || len(config.Name.O) == 0 ||
len(config.Name.CN) == 0 {
log.Criticalf("Config must provide country, organizationName, and commonName")
return
}
if config.NotBefore.After(config.NotAfter) {
log.Criticalf("Invalid validity: notAfter is before notBefore")
return
}
// Set up PKCS#11 key
priv, err := pkcs11key.New(*module, *token, *pin, *label)
if err != nil {
log.Criticalf("Unable to instantiate PKCS#11 private key: %v", err)
return
}
pub := priv.Public()
// Generate serial number
serialLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialLimit)
if err != nil {
log.Criticalf("Error generating serial number: %v", err)
return
}
// Generate subject key ID
pubDER, err := x509.MarshalPKIXPublicKey(pub)
if err != nil {
log.Criticalf("Error serializing public key: %v", err)
return
}
h := sha1.New()
h.Write(pubDER)
keyID := h.Sum(nil)
// Sign the certificate
rootTemplate := &x509.Certificate{
SignatureAlgorithm: x509.SHA256WithRSA,
SerialNumber: serialNumber,
Subject: pkix.Name{
Country: []string{config.Name.C},
Organization: []string{config.Name.O},
CommonName: config.Name.CN,
},
NotBefore: config.NotBefore,
NotAfter: config.NotAfter,
BasicConstraintsValid: true,
IsCA: true,
SubjectKeyId: keyID,
}
rootDER, err := x509.CreateCertificate(rand.Reader, rootTemplate, rootTemplate, pub, priv)
if err != nil {
log.Criticalf("Error signing certificate: %v", err)
return
}
fmt.Println(string(pem.EncodeToMemory(&pem.Block{
Type: "CERTIFICATE",
Bytes: rootDER,
})))
}