745 lines
16 KiB
Go
745 lines
16 KiB
Go
|
package csr
|
||
|
|
||
|
import (
|
||
|
"crypto"
|
||
|
"crypto/ecdsa"
|
||
|
"crypto/elliptic"
|
||
|
"crypto/rsa"
|
||
|
"crypto/x509"
|
||
|
"encoding/asn1"
|
||
|
"encoding/pem"
|
||
|
"io/ioutil"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/cloudflare/cfssl/errors"
|
||
|
"github.com/cloudflare/cfssl/helpers"
|
||
|
)
|
||
|
|
||
|
//TestNew validate the CertificateRequest created to return with a BasicKeyRequest
|
||
|
//in KeyRequest field
|
||
|
|
||
|
func TestNew(t *testing.T) {
|
||
|
|
||
|
if cr := New(); cr.KeyRequest == nil {
|
||
|
t.Fatalf("Should create a new, empty certificate request with BasicKeyRequest")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestBasicKeyRequest ensures that key generation returns the same type of
|
||
|
// key specified in the BasicKeyRequest.
|
||
|
func TestBasicKeyRequest(t *testing.T) {
|
||
|
kr := NewBasicKeyRequest()
|
||
|
priv, err := kr.Generate()
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
switch priv.(type) {
|
||
|
case *rsa.PrivateKey:
|
||
|
if kr.Algo() != "rsa" {
|
||
|
t.Fatal("RSA key generated, but expected", kr.Algo())
|
||
|
}
|
||
|
case *ecdsa.PrivateKey:
|
||
|
if kr.Algo() != "ecdsa" {
|
||
|
t.Fatal("ECDSA key generated, but expected", kr.Algo())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestPKIXName validates building a pkix.Name structure from a
|
||
|
// CertificateRequest.
|
||
|
func TestPKIXName(t *testing.T) {
|
||
|
var cr = &CertificateRequest{
|
||
|
CN: "Test Common Name",
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare, Inc.",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
{
|
||
|
C: "GB",
|
||
|
ST: "London",
|
||
|
L: "London",
|
||
|
O: "CloudFlare, Inc",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com"},
|
||
|
KeyRequest: NewBasicKeyRequest(),
|
||
|
}
|
||
|
|
||
|
name := cr.Name()
|
||
|
if len(name.Country) != 2 {
|
||
|
t.Fatal("Expected two countries in SubjInfo.")
|
||
|
} else if len(name.Province) != 2 {
|
||
|
t.Fatal("Expected two states in SubjInfo.")
|
||
|
} else if len(name.Locality) != 2 {
|
||
|
t.Fatal("Expected two localities in SubjInfo.")
|
||
|
} else if len(name.Country) != 2 {
|
||
|
t.Fatal("Expected two countries in SubjInfo.")
|
||
|
} else if len(name.Organization) != 2 {
|
||
|
t.Fatal("Expected two organization in SubjInfo.")
|
||
|
} else if len(name.OrganizationalUnit) != 2 {
|
||
|
t.Fatal("Expected two organizational units in SubjInfo.")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestParseRequest ensures that a valid certificate request does not
|
||
|
// error.
|
||
|
func TestParseRequest(t *testing.T) {
|
||
|
var cr = &CertificateRequest{
|
||
|
CN: "Test Common Name",
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare, Inc.",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
{
|
||
|
C: "GB",
|
||
|
ST: "London",
|
||
|
L: "London",
|
||
|
O: "CloudFlare, Inc",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1", "jdoe@example.com"},
|
||
|
KeyRequest: NewBasicKeyRequest(),
|
||
|
}
|
||
|
|
||
|
_, _, err := ParseRequest(cr)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestParseRequestCA ensures that a valid CA certificate request does not
|
||
|
// error and the resulting CSR includes the BasicConstraint extension
|
||
|
func TestParseRequestCA(t *testing.T) {
|
||
|
var cr = &CertificateRequest{
|
||
|
CN: "Test Common Name",
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare, Inc.",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
{
|
||
|
C: "GB",
|
||
|
ST: "London",
|
||
|
L: "London",
|
||
|
O: "CloudFlare, Inc",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CA: &CAConfig{
|
||
|
PathLength: 0,
|
||
|
PathLenZero: true,
|
||
|
},
|
||
|
KeyRequest: NewBasicKeyRequest(),
|
||
|
}
|
||
|
|
||
|
csrBytes, _, err := ParseRequest(cr)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
block, _ := pem.Decode(csrBytes)
|
||
|
if block == nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
if block.Type != "CERTIFICATE REQUEST" {
|
||
|
t.Fatalf("Incorrect block type: %s", block.Type)
|
||
|
}
|
||
|
|
||
|
csr, err := x509.ParseCertificateRequest(block.Bytes)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
found := false
|
||
|
for _, ext := range csr.Extensions {
|
||
|
if ext.Id.Equal(asn1.ObjectIdentifier{2, 5, 29, 19}) {
|
||
|
found = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !found {
|
||
|
t.Fatalf("CSR did not include BasicConstraint Extension")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestParseRequestCANoPathlen ensures that a valid CA certificate request
|
||
|
// with an unspecified pathlen does not error and the resulting CSR includes
|
||
|
// the BasicConstraint extension
|
||
|
func TestParseRequestCANoPathlen(t *testing.T) {
|
||
|
var cr = &CertificateRequest{
|
||
|
CN: "Test Common Name",
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare, Inc.",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
{
|
||
|
C: "GB",
|
||
|
ST: "London",
|
||
|
L: "London",
|
||
|
O: "CloudFlare, Inc",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CA: &CAConfig{
|
||
|
PathLength: 0,
|
||
|
PathLenZero: false,
|
||
|
},
|
||
|
KeyRequest: NewBasicKeyRequest(),
|
||
|
}
|
||
|
|
||
|
csrBytes, _, err := ParseRequest(cr)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
block, _ := pem.Decode(csrBytes)
|
||
|
if block == nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
if block.Type != "CERTIFICATE REQUEST" {
|
||
|
t.Fatalf("Incorrect block type: %s", block.Type)
|
||
|
}
|
||
|
|
||
|
csr, err := x509.ParseCertificateRequest(block.Bytes)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
found := false
|
||
|
for _, ext := range csr.Extensions {
|
||
|
if ext.Id.Equal(asn1.ObjectIdentifier{2, 5, 29, 19}) {
|
||
|
bc := &BasicConstraints{}
|
||
|
asn1.Unmarshal(ext.Value, bc)
|
||
|
if bc.IsCA == true && bc.MaxPathLen == -1 {
|
||
|
found = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if !found {
|
||
|
t.Fatalf("CSR did not include BasicConstraint Extension")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func whichCurve(sz int) elliptic.Curve {
|
||
|
switch sz {
|
||
|
case 256:
|
||
|
return elliptic.P256()
|
||
|
case 384:
|
||
|
return elliptic.P384()
|
||
|
case 521:
|
||
|
return elliptic.P521()
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// TestECGeneration ensures that the proper curve is used depending on
|
||
|
// the bit size specified in a key request and that an appropriate
|
||
|
// signature algorithm is returned.
|
||
|
func TestECGeneration(t *testing.T) {
|
||
|
var eckey *ecdsa.PrivateKey
|
||
|
|
||
|
for _, sz := range []int{256, 384, 521} {
|
||
|
kr := &BasicKeyRequest{"ecdsa", sz}
|
||
|
priv, err := kr.Generate()
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
eckey = priv.(*ecdsa.PrivateKey)
|
||
|
if eckey.Curve != whichCurve(sz) {
|
||
|
t.Fatal("Generated key has wrong curve.")
|
||
|
}
|
||
|
if sa := kr.SigAlgo(); sa == x509.UnknownSignatureAlgorithm {
|
||
|
t.Fatal("Invalid signature algorithm!")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestRSAKeyGeneration(t *testing.T) {
|
||
|
var rsakey *rsa.PrivateKey
|
||
|
|
||
|
for _, sz := range []int{2048, 3072, 4096} {
|
||
|
kr := &BasicKeyRequest{"rsa", sz}
|
||
|
priv, err := kr.Generate()
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
rsakey = priv.(*rsa.PrivateKey)
|
||
|
if rsakey.PublicKey.N.BitLen() != kr.Size() {
|
||
|
t.Fatal("Generated key has wrong size.")
|
||
|
}
|
||
|
if sa := kr.SigAlgo(); sa == x509.UnknownSignatureAlgorithm {
|
||
|
t.Fatal("Invalid signature algorithm!")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestBadBasicKeyRequest ensures that generating a key from a BasicKeyRequest
|
||
|
// fails with an invalid algorithm, or an invalid RSA or ECDSA key
|
||
|
// size. An invalid ECDSA key size is any size other than 256, 384, or
|
||
|
// 521; an invalid RSA key size is any size less than 2048 bits.
|
||
|
func TestBadBasicKeyRequest(t *testing.T) {
|
||
|
kr := &BasicKeyRequest{"yolocrypto", 1024}
|
||
|
|
||
|
if _, err := kr.Generate(); err == nil {
|
||
|
t.Fatal("Key generation should fail with invalid algorithm")
|
||
|
} else if sa := kr.SigAlgo(); sa != x509.UnknownSignatureAlgorithm {
|
||
|
t.Fatal("The wrong signature algorithm was returned from SigAlgo!")
|
||
|
}
|
||
|
|
||
|
kr.A = "ecdsa"
|
||
|
if _, err := kr.Generate(); err == nil {
|
||
|
t.Fatal("Key generation should fail with invalid key size")
|
||
|
} else if sa := kr.SigAlgo(); sa != x509.ECDSAWithSHA1 {
|
||
|
t.Fatal("The wrong signature algorithm was returned from SigAlgo!")
|
||
|
}
|
||
|
|
||
|
kr.A = "rsa"
|
||
|
if _, err := kr.Generate(); err == nil {
|
||
|
t.Fatal("Key generation should fail with invalid key size")
|
||
|
} else if sa := kr.SigAlgo(); sa != x509.SHA1WithRSA {
|
||
|
t.Fatal("The wrong signature algorithm was returned from SigAlgo!")
|
||
|
}
|
||
|
|
||
|
kr = &BasicKeyRequest{"tobig", 9216}
|
||
|
|
||
|
kr.A = "rsa"
|
||
|
if _, err := kr.Generate(); err == nil {
|
||
|
t.Fatal("Key generation should fail with invalid key size")
|
||
|
} else if sa := kr.SigAlgo(); sa != x509.SHA512WithRSA {
|
||
|
t.Fatal("The wrong signature algorithm was returned from SigAlgo!")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestDefaultBasicKeyRequest makes sure that certificate requests without
|
||
|
// explicit key requests fall back to the default key request.
|
||
|
func TestDefaultBasicKeyRequest(t *testing.T) {
|
||
|
var req = &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CN: "cloudflare.com",
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "jdoe@example.com"},
|
||
|
}
|
||
|
_, priv, err := ParseRequest(req)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
// If the default key type changes, this will need to be changed.
|
||
|
block, _ := pem.Decode(priv)
|
||
|
if block == nil {
|
||
|
t.Fatal("Bad private key was generated!")
|
||
|
}
|
||
|
|
||
|
DefaultKeyRequest := NewBasicKeyRequest()
|
||
|
switch block.Type {
|
||
|
case "RSA PRIVATE KEY":
|
||
|
if DefaultKeyRequest.Algo() != "rsa" {
|
||
|
t.Fatal("Invalid default key request.")
|
||
|
}
|
||
|
case "EC PRIVATE KEY":
|
||
|
if DefaultKeyRequest.Algo() != "ecdsa" {
|
||
|
t.Fatal("Invalid default key request.")
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestRSACertRequest validates parsing a certificate request with an
|
||
|
// RSA key.
|
||
|
func TestRSACertRequest(t *testing.T) {
|
||
|
var req = &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CN: "cloudflare.com",
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "jdoe@example.com"},
|
||
|
KeyRequest: &BasicKeyRequest{"rsa", 2048},
|
||
|
}
|
||
|
_, _, err := ParseRequest(req)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestBadCertRequest checks for failure conditions of ParseRequest.
|
||
|
func TestBadCertRequest(t *testing.T) {
|
||
|
var req = &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CN: "cloudflare.com",
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com"},
|
||
|
KeyRequest: &BasicKeyRequest{"yolo-crypto", 2048},
|
||
|
}
|
||
|
_, _, err := ParseRequest(req)
|
||
|
if err == nil {
|
||
|
t.Fatal("ParseRequest should fail with a bad key algorithm.")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// testValidator is a stripped-down validator that checks to make sure
|
||
|
// the request has a common name. It should mimic some of the
|
||
|
// functionality expected in an actual validator.
|
||
|
func testValidator(req *CertificateRequest) error {
|
||
|
if req.CN == "" {
|
||
|
return errors.NewBadRequestMissingParameter("CN")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// TestGenerator ensures that a valid request is processed properly
|
||
|
// and returns a certificate request and key.
|
||
|
func TestGenerator(t *testing.T) {
|
||
|
g := &Generator{testValidator}
|
||
|
var req = &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CN: "cloudflare.com",
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1", "jdoe@example.com"},
|
||
|
KeyRequest: &BasicKeyRequest{"rsa", 2048},
|
||
|
}
|
||
|
|
||
|
csrBytes, _, err := g.ProcessRequest(req)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
block, _ := pem.Decode([]byte(csrBytes))
|
||
|
if block == nil {
|
||
|
t.Fatalf("bad CSR in PEM")
|
||
|
}
|
||
|
|
||
|
if block.Type != "CERTIFICATE REQUEST" {
|
||
|
t.Fatalf("bad CSR in PEM")
|
||
|
}
|
||
|
|
||
|
csr, err := x509.ParseCertificateRequest(block.Bytes)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
if len(csr.DNSNames) != 2 {
|
||
|
t.Fatal("SAN parsing error")
|
||
|
}
|
||
|
|
||
|
if len(csr.IPAddresses) != 1 {
|
||
|
t.Fatal("SAN parsing error")
|
||
|
}
|
||
|
|
||
|
if len(csr.EmailAddresses) != 1 {
|
||
|
t.Fatal("SAN parsing error")
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// TestBadGenerator ensures that a request that fails the validator is
|
||
|
// not processed.
|
||
|
func TestBadGenerator(t *testing.T) {
|
||
|
g := &Generator{testValidator}
|
||
|
missingCN := &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
// Missing CN
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com"},
|
||
|
KeyRequest: &BasicKeyRequest{"rsa", 2048},
|
||
|
}
|
||
|
|
||
|
_, _, err := g.ProcessRequest(missingCN)
|
||
|
if err == nil {
|
||
|
t.Fatalf("Request should have failed.")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestWeakCSR(t *testing.T) {
|
||
|
weakKey := &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CN: "cloudflare.com",
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "jdoe@example.com"},
|
||
|
KeyRequest: &BasicKeyRequest{"rsa", 1024},
|
||
|
}
|
||
|
g := &Generator{testValidator}
|
||
|
|
||
|
_, _, err := g.ProcessRequest(weakKey)
|
||
|
if err == nil {
|
||
|
t.Fatalf("Request should have failed.")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var testEmpty = []struct {
|
||
|
name Name
|
||
|
ok bool
|
||
|
}{
|
||
|
{
|
||
|
Name{},
|
||
|
true,
|
||
|
},
|
||
|
{
|
||
|
Name{C: "OK"},
|
||
|
false,
|
||
|
},
|
||
|
{
|
||
|
Name{ST: "OK"},
|
||
|
false,
|
||
|
},
|
||
|
{
|
||
|
Name{L: "OK"},
|
||
|
false,
|
||
|
},
|
||
|
{
|
||
|
Name{O: "OK"},
|
||
|
false,
|
||
|
},
|
||
|
{
|
||
|
Name{OU: "OK"},
|
||
|
false,
|
||
|
},
|
||
|
}
|
||
|
|
||
|
func TestIsNameEmpty(t *testing.T) {
|
||
|
for i, c := range testEmpty {
|
||
|
if IsNameEmpty(c.name) != c.ok {
|
||
|
t.Fatalf("%d: expected IsNameEmpty to return %v, but have %v", i, c.ok, !c.ok)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func TestGenerate(t *testing.T) {
|
||
|
var req = &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CN: "cloudflare.com",
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1", "jdoe@example.com"},
|
||
|
KeyRequest: &BasicKeyRequest{"ecdsa", 256},
|
||
|
}
|
||
|
|
||
|
key, err := req.KeyRequest.Generate()
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
priv, ok := key.(crypto.Signer)
|
||
|
if !ok {
|
||
|
t.Fatal("Private key is not a signer.")
|
||
|
}
|
||
|
|
||
|
csrPEM, err := Generate(priv, req)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
csr, _, err := helpers.ParseCSR(csrPEM)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
if len(csr.DNSNames) != 2 {
|
||
|
t.Fatal("SAN parsing error")
|
||
|
}
|
||
|
|
||
|
if len(csr.IPAddresses) != 1 {
|
||
|
t.Fatal("SAN parsing error")
|
||
|
}
|
||
|
|
||
|
if len(csr.EmailAddresses) != 1 {
|
||
|
t.Fatal("SAN parsing error")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestReGenerate ensures Regenerate() is abel to use the provided CSR as a template for signing a new
|
||
|
// CSR using priv.
|
||
|
func TestReGenerate(t *testing.T) {
|
||
|
var req = &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CN: "cloudflare.com",
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1"},
|
||
|
KeyRequest: &BasicKeyRequest{"ecdsa", 256},
|
||
|
}
|
||
|
|
||
|
_, key, err := ParseRequest(req)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
priv, err := helpers.ParsePrivateKeyPEM(key)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
csr, err := Generate(priv, req)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
if _, _, err = helpers.ParseCSR(csr); err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
_, err = Regenerate(priv, csr)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TestBadReGenerator ensures that a request that fails the ParseCSR is
|
||
|
// not processed.
|
||
|
func TestBadReGenerate(t *testing.T) {
|
||
|
var req = &CertificateRequest{
|
||
|
Names: []Name{
|
||
|
{
|
||
|
C: "US",
|
||
|
ST: "California",
|
||
|
L: "San Francisco",
|
||
|
O: "CloudFlare",
|
||
|
OU: "Systems Engineering",
|
||
|
},
|
||
|
},
|
||
|
CN: "cloudflare.com",
|
||
|
Hosts: []string{"cloudflare.com", "www.cloudflare.com", "192.168.0.1"},
|
||
|
KeyRequest: &BasicKeyRequest{"ecdsa", 256},
|
||
|
}
|
||
|
|
||
|
_, key, err := ParseRequest(req)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
priv, err := helpers.ParsePrivateKeyPEM(key)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
csr, err := Generate(priv, req)
|
||
|
if err != nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
|
||
|
block := pem.Block{
|
||
|
Type: "CERTIFICATE REQUEST",
|
||
|
Headers: map[string]string{
|
||
|
"Location": "UCSD",
|
||
|
},
|
||
|
Bytes: csr,
|
||
|
}
|
||
|
|
||
|
csr = pem.EncodeToMemory(&block)
|
||
|
|
||
|
_, err = Regenerate(priv, csr)
|
||
|
if err == nil {
|
||
|
t.Fatalf("%v", err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var testECDSACertificateFile = "testdata/test-ecdsa-ca.pem"
|
||
|
|
||
|
func TestExtractCertificateRequest(t *testing.T) {
|
||
|
certPEM, err := ioutil.ReadFile(testECDSACertificateFile)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
// must parse ok
|
||
|
cert, err := helpers.ParseCertificatePEM(certPEM)
|
||
|
if err != nil {
|
||
|
t.Fatal(err)
|
||
|
}
|
||
|
|
||
|
req := ExtractCertificateRequest(cert)
|
||
|
|
||
|
if req.CN != "" {
|
||
|
t.Fatal("Bad Certificate Request!")
|
||
|
}
|
||
|
|
||
|
if len(req.Names) != 1 {
|
||
|
t.Fatal("Bad Certificate Request!")
|
||
|
}
|
||
|
|
||
|
name := req.Names[0]
|
||
|
if name.C != "US" || name.ST != "California" || name.O != "CloudFlare, Inc." ||
|
||
|
name.OU != "Test Certificate Authority" || name.L != "San Francisco" {
|
||
|
t.Fatal("Bad Certificate Request!")
|
||
|
}
|
||
|
|
||
|
if req.CA == nil || req.CA.PathLength != 2 {
|
||
|
t.Fatal("Bad Certificate Request!")
|
||
|
}
|
||
|
}
|