vendor
This commit is contained in:
94
vendor/github.com/cloudflare/cfssl/auth/auth.go
generated
vendored
Normal file
94
vendor/github.com/cloudflare/cfssl/auth/auth.go
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
// Package auth implements an interface for providing CFSSL
|
||||
// authentication. This is meant to authenticate a client CFSSL to a
|
||||
// remote CFSSL in order to prevent unauthorised use of the signature
|
||||
// capabilities. This package provides both the interface and a
|
||||
// standard HMAC-based implementation.
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// An AuthenticatedRequest contains a request and authentication
|
||||
// token. The Provider may determine whether to validate the timestamp
|
||||
// and remote address.
|
||||
type AuthenticatedRequest struct {
|
||||
// An Authenticator decides whether to use this field.
|
||||
Timestamp int64 `json:"timestamp,omitempty"`
|
||||
RemoteAddress []byte `json:"remote_address,omitempty"`
|
||||
Token []byte `json:"token"`
|
||||
Request []byte `json:"request"`
|
||||
}
|
||||
|
||||
// A Provider can generate tokens from a request and verify a
|
||||
// request. The handling of additional authentication data (such as
|
||||
// the IP address) is handled by the concrete type, as is any
|
||||
// serialisation and state-keeping.
|
||||
type Provider interface {
|
||||
Token(req []byte) (token []byte, err error)
|
||||
Verify(aReq *AuthenticatedRequest) bool
|
||||
}
|
||||
|
||||
// Standard implements an HMAC-SHA-256 authentication provider. It may
|
||||
// be supplied additional data at creation time that will be used as
|
||||
// request || additional-data with the HMAC.
|
||||
type Standard struct {
|
||||
key []byte
|
||||
ad []byte
|
||||
}
|
||||
|
||||
// New generates a new standard authentication provider from the key
|
||||
// and additional data. The additional data will be used when
|
||||
// generating a new token.
|
||||
func New(key string, ad []byte) (*Standard, error) {
|
||||
if splitKey := strings.SplitN(key, ":", 2); len(splitKey) == 2 {
|
||||
switch splitKey[0] {
|
||||
case "env":
|
||||
key = os.Getenv(splitKey[1])
|
||||
case "file":
|
||||
data, err := ioutil.ReadFile(splitKey[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key = string(data)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown key prefix: %s", splitKey[0])
|
||||
}
|
||||
}
|
||||
|
||||
keyBytes, err := hex.DecodeString(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Standard{keyBytes, ad}, nil
|
||||
}
|
||||
|
||||
// Token generates a new authentication token from the request.
|
||||
func (p Standard) Token(req []byte) (token []byte, err error) {
|
||||
h := hmac.New(sha256.New, p.key)
|
||||
h.Write(req)
|
||||
h.Write(p.ad)
|
||||
return h.Sum(nil), nil
|
||||
}
|
||||
|
||||
// Verify determines whether an authenticated request is valid.
|
||||
func (p Standard) Verify(ad *AuthenticatedRequest) bool {
|
||||
if ad == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Standard token generation returns no error.
|
||||
token, _ := p.Token(ad.Request)
|
||||
if len(ad.Token) != len(token) {
|
||||
return false
|
||||
}
|
||||
|
||||
return hmac.Equal(token, ad.Token)
|
||||
}
|
159
vendor/github.com/cloudflare/cfssl/auth/auth_test.go
generated
vendored
Normal file
159
vendor/github.com/cloudflare/cfssl/auth/auth_test.go
generated
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
testProvider Provider
|
||||
testProviderAD Provider
|
||||
testKey = "0123456789ABCDEF0123456789ABCDEF"
|
||||
testAD = []byte{1, 2, 3, 4} // IP address 1.2.3.4
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
_, err := New("ABC", nil)
|
||||
if err == nil {
|
||||
t.Fatal("expected failure with improperly-hex-encoded key")
|
||||
}
|
||||
|
||||
testProvider, err = New(testKey, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
testProviderAD, err = New(testKey, testAD)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
testRequest1A = &AuthenticatedRequest{
|
||||
Request: []byte(`testing 1 2 3`),
|
||||
}
|
||||
testRequest1B = &AuthenticatedRequest{
|
||||
Request: []byte(`testing 1 2 3`),
|
||||
}
|
||||
testRequest2 = &AuthenticatedRequest{
|
||||
Request: []byte(`testing 3 2 1`),
|
||||
}
|
||||
)
|
||||
|
||||
// Sanity check: can a newly-generated token be verified?
|
||||
func TestVerifyTrue(t *testing.T) {
|
||||
var err error
|
||||
|
||||
testRequest1A.Token, err = testProvider.Token(testRequest1A.Request)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
testRequest1B.Token, err = testProviderAD.Token(testRequest1B.Request)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
if !testProvider.Verify(testRequest1A) {
|
||||
t.Fatal("failed to verify request 1A")
|
||||
}
|
||||
|
||||
if !testProviderAD.Verify(testRequest1B) {
|
||||
t.Fatal("failed to verify request 1B")
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check: ensure that additional data is actually used in
|
||||
// verification.
|
||||
func TestVerifyAD(t *testing.T) {
|
||||
if testProvider.Verify(testRequest1B) {
|
||||
t.Fatal("no-AD provider verifies request with AD")
|
||||
}
|
||||
|
||||
if testProviderAD.Verify(testRequest1A) {
|
||||
t.Fatal("AD provider verifies request without AD")
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check: verification fails if tokens are not the same length.
|
||||
func TestTokenLength(t *testing.T) {
|
||||
token := testRequest1A.Token[:]
|
||||
testRequest1A.Token = testRequest1A.Token[1:]
|
||||
|
||||
if testProvider.Verify(testRequest1A) {
|
||||
t.Fatal("invalid token should not be verified")
|
||||
}
|
||||
|
||||
testRequest1A.Token = token
|
||||
}
|
||||
|
||||
// Sanity check: token fails validation if the request is changed.
|
||||
func TestBadRequest(t *testing.T) {
|
||||
testRequest2.Token = testRequest1A.Token
|
||||
if testProvider.Verify(testRequest2) {
|
||||
t.Fatal("bad request should fail verification")
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check: a null request should fail to verify.
|
||||
func TestNullRequest(t *testing.T) {
|
||||
if testProvider.Verify(nil) {
|
||||
t.Fatal("null request should fail verification")
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check: verify a pre-generated authenticated request.
|
||||
func TestPreGenerated(t *testing.T) {
|
||||
in, err := ioutil.ReadFile("testdata/authrequest.json")
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
var req AuthenticatedRequest
|
||||
err = json.Unmarshal(in, &req)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
if !testProvider.Verify(&req) {
|
||||
t.Fatal("failed to verify pre-generated request")
|
||||
}
|
||||
}
|
||||
|
||||
var bmRequest []byte
|
||||
|
||||
func TestLoadBenchmarkRequest(t *testing.T) {
|
||||
in, err := ioutil.ReadFile("testdata/request.json")
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
bmRequest = in
|
||||
}
|
||||
|
||||
func BenchmarkToken(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := testProvider.Token(bmRequest)
|
||||
if err != nil {
|
||||
b.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkVerify(b *testing.B) {
|
||||
token, _ := testProvider.Token(bmRequest)
|
||||
req := &AuthenticatedRequest{
|
||||
Token: token,
|
||||
Request: bmRequest,
|
||||
}
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
if !testProvider.Verify(req) {
|
||||
b.Fatal("failed to verify request")
|
||||
}
|
||||
}
|
||||
}
|
1
vendor/github.com/cloudflare/cfssl/auth/testdata/authrequest.json
generated
vendored
Normal file
1
vendor/github.com/cloudflare/cfssl/auth/testdata/authrequest.json
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"token": "tSU1WTE/322iXrOBfJSQ9/u1dleqpwUmCj1LXYHw07Y=", "request": "ewoJImhvc3RuYW1lIjogImt5bGVpc29tLm5ldCIsCgkicmVxdWVzdCI6ICItLS0tLUJFR0lOIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQoJICAgIE1JSUQwVENDQWpzQ0FRQXdZREVMTUFrR0ExVUVCaE1DVlZNeEVqQVFCZ05WQkFvVENXUnliM0J6YjI1a1pURVEKCSAgICBNQTRHQTFVRUN4TUhRMFl0UTJoaGRERVdNQlFHQTFVRUJ4TU5VMkZ1SUVaeVlXNWphWE5qYnpFVE1CRUdBMVVFCgkgICAgQ0JNS1EyRnNhV1p2Y201cFlUQ0NBYUl3RFFZSktvWklodmNOQVFFQkJRQURnZ0dQQURDQ0FZb0NnZ0dCQU1jQwoJICAgIEdCbDVMVHJla0dGV2hvdGtkYlorUjFNbG9hcld4UXY5alA0QWVrdDhVT2ljeXBIdkZPNnhPdFN3SG8rcjMyaUUKCSAgICBxblM1eXYvMDFQMk1KdXlxbmRuY1RTTXNPbFQvN242N1RNMDB1MDFLLzljL3NvZ0tFS2pseXBsVFA3eUZkRy9jCgkgICAgT3UvOXFLYi9KYWxkMndFTEZZRTZ4cTJSREZ5eHlpWk9CM2c3WjdGeGE1ZDZhZGZHUndaek50VUw0LzhzK0x5aQoJICAgIHFkdzlJMWZrUWQ2MDRwb1pGTjB3clFzNGxmaFdUVWZnMHJIdWg1d2dHS1AzVnpacGJ0OEZiMXZOamZiSHRvaHgKCSAgICBHMlBDVTZKeStEYzFiU2ZVeldjUW5lbnA4NThXNEY4ejdwRjV5YmRuRlIzMTNIam9zcVhuRzI4eklUck9hZE1UCgkgICAgSGFKNnpPaGdFYWZVT1dYT3pqTm9mRkJGYTJJdUNBVCtJVFJZMXRDL2dxcHhHd0gveXVWTjE5Qkc4VXBuMCtIQQoJICAgIGllMm1LQ0hmU0JBS1QvWGU0dW1QZWF4U2JJcVdzVzhjaytkM2I0b3I5Ulp2NWNaUmNUM29pa0p0K1NRRzY5cFcKCSAgICA0T0FiYitBQnNzL05JdXJpNnowZTdERWVJTDV6bXlTSnFkdFlIZE5ZTjcrK3Y5eEJOc0w0SXNVNklFeTMrUUlECgkgICAgQVFBQm9DNHdMQVlKS29aSWh2Y05BUWtPTVI4d0hUQWJCZ05WSFJFRUZEQVNnaEJqWmk1a2NtOXdjMjl1WkdVdQoJICAgIGJtVjBNQXNHQ1NxR1NJYjNEUUVCREFPQ0FZRUFoTUFxQmlySStrMWFVM2xmQUdRaVNtOHl0T3paaWozODloSXIKCSAgICBuVXA4K1duVHVWVGI4WFozL1YrTDlFblRJbUY2dTF3ZWFqWGQzU3VlNDk1NzBMYlltSXV4QmtHcDUwL0JkVUR6CgkgICAgdUI2eHNoaEpXczEySnhVYjkxSW1tMGJUUncyek1xZXdnYTZmdHpaL0FLNG1zeFFBMlVJYmNXWmRzS2J1TTdzbwoJICAgIEpUZlZXOWlPd3FIdC82NFpqNHRCWmY5THpPRHI3a051S0tMbndqaXpIMTg3eGZJSWhkcmpGOFdTN0g5QVBCMU8KCSAgICBTdUVVRGZxaDBTV1IzbHRXdUF1VVdlbzZTS2NIVnVzeS9HNFlFK1BCeXcxZVY3RzRTYmVHNVowbytHT1VVSy9GCgkgICAgYjU1R21XMXhhNExBcnMxQSt6ZUZidkovQkFwc2JVMmI2V1ZtTmE3V3BIejdXWElGT0p1WUpnRWtWS1BKbkt1cwoJICAgIHFxczNGZ1VxejBadjdUSzhtTWlFVEpvWFpzNnpDdk15c1FldTNKL29qZ3RBanZNaHpRYzZQUy9udk90SmRJZysKCSAgICBIMHFYNDlmaHAxQnJZeXNsYWx6UUlGMCtIMHFTVWV5b1V5VjJ3YkxCQUxhcHhNZnZUVmxoTnduYWN0Y0tReHE0CgkgICAgK3dUKzJQVEowYk0vNUFWMFRPMVNQVDBBVmlKaAoJICAgIC0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLSIsCgkicHJvZmlsZSI6ICIiLAoJInJlbW90ZSI6ICIiLAoJImxhYmVsIjogInByaW1hcnkiCn0KCg=="}
|
30
vendor/github.com/cloudflare/cfssl/auth/testdata/request.json
generated
vendored
Normal file
30
vendor/github.com/cloudflare/cfssl/auth/testdata/request.json
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"hostname": "kyleisom.net",
|
||||
"request": "-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIID0TCCAjsCAQAwYDELMAkGA1UEBhMCVVMxEjAQBgNVBAoTCWRyb3Bzb25kZTEQ
|
||||
MA4GA1UECxMHQ0YtQ2hhdDEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UE
|
||||
CBMKQ2FsaWZvcm5pYTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAMcC
|
||||
GBl5LTrekGFWhotkdbZ+R1MloarWxQv9jP4Aekt8UOicypHvFO6xOtSwHo+r32iE
|
||||
qnS5yv/01P2MJuyqndncTSMsOlT/7n67TM00u01K/9c/sogKEKjlyplTP7yFdG/c
|
||||
Ou/9qKb/Jald2wELFYE6xq2RDFyxyiZOB3g7Z7Fxa5d6adfGRwZzNtUL4/8s+Lyi
|
||||
qdw9I1fkQd604poZFN0wrQs4lfhWTUfg0rHuh5wgGKP3VzZpbt8Fb1vNjfbHtohx
|
||||
G2PCU6Jy+Dc1bSfUzWcQnenp858W4F8z7pF5ybdnFR313HjosqXnG28zITrOadMT
|
||||
HaJ6zOhgEafUOWXOzjNofFBFa2IuCAT+ITRY1tC/gqpxGwH/yuVN19BG8Upn0+HA
|
||||
ie2mKCHfSBAKT/Xe4umPeaxSbIqWsW8ck+d3b4or9RZv5cZRcT3oikJt+SQG69pW
|
||||
4OAbb+ABss/NIuri6z0e7DEeIL5zmySJqdtYHdNYN7++v9xBNsL4IsU6IEy3+QID
|
||||
AQABoC4wLAYJKoZIhvcNAQkOMR8wHTAbBgNVHREEFDASghBjZi5kcm9wc29uZGUu
|
||||
bmV0MAsGCSqGSIb3DQEBDAOCAYEAhMAqBirI+k1aU3lfAGQiSm8ytOzZij389hIr
|
||||
nUp8+WnTuVTb8XZ3/V+L9EnTImF6u1weajXd3Sue49570LbYmIuxBkGp50/BdUDz
|
||||
uB6xshhJWs12JxUb91Imm0bTRw2zMqewga6ftzZ/AK4msxQA2UIbcWZdsKbuM7so
|
||||
JTfVW9iOwqHt/64Zj4tBZf9LzODr7kNuKKLnwjizH187xfIIhdrjF8WS7H9APB1O
|
||||
SuEUDfqh0SWR3ltWuAuUWeo6SKcHVusy/G4YE+PByw1eV7G4SbeG5Z0o+GOUUK/F
|
||||
b55GmW1xa4LArs1A+zeFbvJ/BApsbU2b6WVmNa7WpHz7WXIFOJuYJgEkVKPJnKus
|
||||
qqs3FgUqz0Zv7TK8mMiETJoXZs6zCvMysQeu3J/ojgtAjvMhzQc6PS/nvOtJdIg+
|
||||
H0qX49fhp1BrYyslalzQIF0+H0qSUeyoUyV2wbLBALapxMfvTVlhNwnactcKQxq4
|
||||
+wT+2PTJ0bM/5AV0TO1SPT0AViJh
|
||||
-----END CERTIFICATE REQUEST-----",
|
||||
"profile": "",
|
||||
"remote": "",
|
||||
"label": "primary"
|
||||
}
|
||||
|
75
vendor/github.com/cloudflare/cfssl/certdb/README.md
generated
vendored
Normal file
75
vendor/github.com/cloudflare/cfssl/certdb/README.md
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
# certdb usage
|
||||
|
||||
Using a database enables additional functionality for existing commands when a
|
||||
db config is provided:
|
||||
|
||||
- `sign` and `gencert` add a certificate to the certdb after signing it
|
||||
- `serve` enables database functionality for the sign and revoke endpoints
|
||||
|
||||
A database is required for the following:
|
||||
|
||||
- `revoke` marks certificates revoked in the database with an optional reason
|
||||
- `ocsprefresh` refreshes the table of cached OCSP responses
|
||||
- `ocspdump` outputs cached OCSP responses in a concatenated base64-encoded format
|
||||
|
||||
## Setup/Migration
|
||||
|
||||
This directory stores [goose](https://bitbucket.org/liamstask/goose/) db migration scripts for various DB backends.
|
||||
Currently supported:
|
||||
- MySQL in mysql
|
||||
- PostgreSQL in pg
|
||||
- SQLite in sqlite
|
||||
|
||||
### Get goose
|
||||
|
||||
go get bitbucket.org/liamstask/goose/cmd/goose
|
||||
|
||||
### Use goose to start and terminate a MySQL DB
|
||||
To start a MySQL using goose:
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/mysql up
|
||||
|
||||
To tear down a MySQL DB using goose
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/mysql down
|
||||
|
||||
Note: the administration of MySQL DB is not included. We assume
|
||||
the databases being connected to are already created and access control
|
||||
is properly handled.
|
||||
|
||||
### Use goose to start and terminate a PostgreSQL DB
|
||||
To start a PostgreSQL using goose:
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/pg up
|
||||
|
||||
To tear down a PostgreSQL DB using goose
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/pg down
|
||||
|
||||
Note: the administration of PostgreSQL DB is not included. We assume
|
||||
the databases being connected to are already created and access control
|
||||
is properly handled.
|
||||
|
||||
### Use goose to start and terminate a SQLite DB
|
||||
To start a SQLite DB using goose:
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite up
|
||||
|
||||
To tear down a SQLite DB using goose
|
||||
|
||||
goose -path $GOPATH/src/github.com/cloudflare/cfssl/certdb/sqlite down
|
||||
|
||||
## CFSSL Configuration
|
||||
|
||||
Several cfssl commands take a -db-config flag. Create a file with a
|
||||
JSON dictionary:
|
||||
|
||||
{"driver":"sqlite3","data_source":"certs.db"}
|
||||
|
||||
or
|
||||
|
||||
{"driver":"postgres","data_source":"postgres://user:password@host/db"}
|
||||
|
||||
or
|
||||
|
||||
{"driver":"mysql","data_source":"user:password@tcp(hostname:3306)/db?parseTime=true"}
|
42
vendor/github.com/cloudflare/cfssl/certdb/certdb.go
generated
vendored
Normal file
42
vendor/github.com/cloudflare/cfssl/certdb/certdb.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
package certdb
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// CertificateRecord encodes a certificate and its metadata
|
||||
// that will be recorded in a database.
|
||||
type CertificateRecord struct {
|
||||
Serial string `db:"serial_number"`
|
||||
AKI string `db:"authority_key_identifier"`
|
||||
CALabel string `db:"ca_label"`
|
||||
Status string `db:"status"`
|
||||
Reason int `db:"reason"`
|
||||
Expiry time.Time `db:"expiry"`
|
||||
RevokedAt time.Time `db:"revoked_at"`
|
||||
PEM string `db:"pem"`
|
||||
}
|
||||
|
||||
// OCSPRecord encodes a OCSP response body and its metadata
|
||||
// that will be recorded in a database.
|
||||
type OCSPRecord struct {
|
||||
Serial string `db:"serial_number"`
|
||||
AKI string `db:"authority_key_identifier"`
|
||||
Body string `db:"body"`
|
||||
Expiry time.Time `db:"expiry"`
|
||||
}
|
||||
|
||||
// Accessor abstracts the CRUD of certdb objects from a DB.
|
||||
type Accessor interface {
|
||||
InsertCertificate(cr CertificateRecord) error
|
||||
GetCertificate(serial, aki string) ([]CertificateRecord, error)
|
||||
GetUnexpiredCertificates() ([]CertificateRecord, error)
|
||||
GetRevokedAndUnexpiredCertificates() ([]CertificateRecord, error)
|
||||
GetRevokedAndUnexpiredCertificatesByLabel(label string) ([]CertificateRecord, error)
|
||||
RevokeCertificate(serial, aki string, reasonCode int) error
|
||||
InsertOCSP(rr OCSPRecord) error
|
||||
GetOCSP(serial, aki string) ([]OCSPRecord, error)
|
||||
GetUnexpiredOCSPs() ([]OCSPRecord, error)
|
||||
UpdateOCSP(serial, aki, body string, expiry time.Time) error
|
||||
UpsertOCSP(serial, aki, body string, expiry time.Time) error
|
||||
}
|
659
vendor/github.com/cloudflare/cfssl/config/config.go
generated
vendored
Normal file
659
vendor/github.com/cloudflare/cfssl/config/config.go
generated
vendored
Normal file
@ -0,0 +1,659 @@
|
||||
// Package config contains the configuration logic for CFSSL.
|
||||
package config
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/asn1"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cfssl/auth"
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
ocspConfig "github.com/cloudflare/cfssl/ocsp/config"
|
||||
)
|
||||
|
||||
// A CSRWhitelist stores booleans for fields in the CSR. If a CSRWhitelist is
|
||||
// not present in a SigningProfile, all of these fields may be copied from the
|
||||
// CSR into the signed certificate. If a CSRWhitelist *is* present in a
|
||||
// SigningProfile, only those fields with a `true` value in the CSRWhitelist may
|
||||
// be copied from the CSR to the signed certificate. Note that some of these
|
||||
// fields, like Subject, can be provided or partially provided through the API.
|
||||
// Since API clients are expected to be trusted, but CSRs are not, fields
|
||||
// provided through the API are not subject to whitelisting through this
|
||||
// mechanism.
|
||||
type CSRWhitelist struct {
|
||||
Subject, PublicKeyAlgorithm, PublicKey, SignatureAlgorithm bool
|
||||
DNSNames, IPAddresses, EmailAddresses bool
|
||||
}
|
||||
|
||||
// OID is our own version of asn1's ObjectIdentifier, so we can define a custom
|
||||
// JSON marshal / unmarshal.
|
||||
type OID asn1.ObjectIdentifier
|
||||
|
||||
// CertificatePolicy represents the ASN.1 PolicyInformation structure from
|
||||
// https://tools.ietf.org/html/rfc3280.html#page-106.
|
||||
// Valid values of Type are "id-qt-unotice" and "id-qt-cps"
|
||||
type CertificatePolicy struct {
|
||||
ID OID
|
||||
Qualifiers []CertificatePolicyQualifier
|
||||
}
|
||||
|
||||
// CertificatePolicyQualifier represents a single qualifier from an ASN.1
|
||||
// PolicyInformation structure.
|
||||
type CertificatePolicyQualifier struct {
|
||||
Type string
|
||||
Value string
|
||||
}
|
||||
|
||||
// AuthRemote is an authenticated remote signer.
|
||||
type AuthRemote struct {
|
||||
RemoteName string `json:"remote"`
|
||||
AuthKeyName string `json:"auth_key"`
|
||||
}
|
||||
|
||||
// CAConstraint specifies various CA constraints on the signed certificate.
|
||||
// CAConstraint would verify against (and override) the CA
|
||||
// extensions in the given CSR.
|
||||
type CAConstraint struct {
|
||||
IsCA bool `json:"is_ca"`
|
||||
MaxPathLen int `json:"max_path_len"`
|
||||
MaxPathLenZero bool `json:"max_path_len_zero"`
|
||||
}
|
||||
|
||||
// A SigningProfile stores information that the CA needs to store
|
||||
// signature policy.
|
||||
type SigningProfile struct {
|
||||
Usage []string `json:"usages"`
|
||||
IssuerURL []string `json:"issuer_urls"`
|
||||
OCSP string `json:"ocsp_url"`
|
||||
CRL string `json:"crl_url"`
|
||||
CAConstraint CAConstraint `json:"ca_constraint"`
|
||||
OCSPNoCheck bool `json:"ocsp_no_check"`
|
||||
ExpiryString string `json:"expiry"`
|
||||
BackdateString string `json:"backdate"`
|
||||
AuthKeyName string `json:"auth_key"`
|
||||
RemoteName string `json:"remote"`
|
||||
NotBefore time.Time `json:"not_before"`
|
||||
NotAfter time.Time `json:"not_after"`
|
||||
NameWhitelistString string `json:"name_whitelist"`
|
||||
AuthRemote AuthRemote `json:"auth_remote"`
|
||||
CTLogServers []string `json:"ct_log_servers"`
|
||||
AllowedExtensions []OID `json:"allowed_extensions"`
|
||||
CertStore string `json:"cert_store"`
|
||||
|
||||
Policies []CertificatePolicy
|
||||
Expiry time.Duration
|
||||
Backdate time.Duration
|
||||
Provider auth.Provider
|
||||
RemoteProvider auth.Provider
|
||||
RemoteServer string
|
||||
RemoteCAs *x509.CertPool
|
||||
ClientCert *tls.Certificate
|
||||
CSRWhitelist *CSRWhitelist
|
||||
NameWhitelist *regexp.Regexp
|
||||
ExtensionWhitelist map[string]bool
|
||||
ClientProvidesSerialNumbers bool
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals a JSON string into an OID.
|
||||
func (oid *OID) UnmarshalJSON(data []byte) (err error) {
|
||||
if data[0] != '"' || data[len(data)-1] != '"' {
|
||||
return errors.New("OID JSON string not wrapped in quotes." + string(data))
|
||||
}
|
||||
data = data[1 : len(data)-1]
|
||||
parsedOid, err := parseObjectIdentifier(string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*oid = OID(parsedOid)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalJSON marshals an oid into a JSON string.
|
||||
func (oid OID) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf(`"%v"`, asn1.ObjectIdentifier(oid))), nil
|
||||
}
|
||||
|
||||
func parseObjectIdentifier(oidString string) (oid asn1.ObjectIdentifier, err error) {
|
||||
validOID, err := regexp.MatchString("\\d(\\.\\d+)*", oidString)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !validOID {
|
||||
err = errors.New("Invalid OID")
|
||||
return
|
||||
}
|
||||
|
||||
segments := strings.Split(oidString, ".")
|
||||
oid = make(asn1.ObjectIdentifier, len(segments))
|
||||
for i, intString := range segments {
|
||||
oid[i], err = strconv.Atoi(intString)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const timeFormat = "2006-01-02T15:04:05"
|
||||
|
||||
// populate is used to fill in the fields that are not in JSON
|
||||
//
|
||||
// First, the ExpiryString parameter is needed to parse
|
||||
// expiration timestamps from JSON. The JSON decoder is not able to
|
||||
// decode a string time duration to a time.Duration, so this is called
|
||||
// when loading the configuration to properly parse and fill out the
|
||||
// Expiry parameter.
|
||||
// This function is also used to create references to the auth key
|
||||
// and default remote for the profile.
|
||||
// It returns true if ExpiryString is a valid representation of a
|
||||
// time.Duration, and the AuthKeyString and RemoteName point to
|
||||
// valid objects. It returns false otherwise.
|
||||
func (p *SigningProfile) populate(cfg *Config) error {
|
||||
if p == nil {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("can't parse nil profile"))
|
||||
}
|
||||
|
||||
var err error
|
||||
if p.RemoteName == "" && p.AuthRemote.RemoteName == "" {
|
||||
log.Debugf("parse expiry in profile")
|
||||
if p.ExpiryString == "" {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("empty expiry string"))
|
||||
}
|
||||
|
||||
dur, err := time.ParseDuration(p.ExpiryString)
|
||||
if err != nil {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
|
||||
}
|
||||
|
||||
log.Debugf("expiry is valid")
|
||||
p.Expiry = dur
|
||||
|
||||
if p.BackdateString != "" {
|
||||
dur, err = time.ParseDuration(p.BackdateString)
|
||||
if err != nil {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
|
||||
}
|
||||
|
||||
p.Backdate = dur
|
||||
}
|
||||
|
||||
if !p.NotBefore.IsZero() && !p.NotAfter.IsZero() && p.NotAfter.Before(p.NotBefore) {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, err)
|
||||
}
|
||||
|
||||
if len(p.Policies) > 0 {
|
||||
for _, policy := range p.Policies {
|
||||
for _, qualifier := range policy.Qualifiers {
|
||||
if qualifier.Type != "" && qualifier.Type != "id-qt-unotice" && qualifier.Type != "id-qt-cps" {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("invalid policy qualifier type"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if p.RemoteName != "" {
|
||||
log.Debug("match remote in profile to remotes section")
|
||||
if p.AuthRemote.RemoteName != "" {
|
||||
log.Error("profile has both a remote and an auth remote specified")
|
||||
return cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
|
||||
}
|
||||
if remote := cfg.Remotes[p.RemoteName]; remote != "" {
|
||||
if err := p.updateRemote(remote); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("failed to find remote in remotes section"))
|
||||
}
|
||||
} else {
|
||||
log.Debug("match auth remote in profile to remotes section")
|
||||
if remote := cfg.Remotes[p.AuthRemote.RemoteName]; remote != "" {
|
||||
if err := p.updateRemote(remote); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("failed to find remote in remotes section"))
|
||||
}
|
||||
}
|
||||
|
||||
if p.AuthKeyName != "" {
|
||||
log.Debug("match auth key in profile to auth_keys section")
|
||||
if key, ok := cfg.AuthKeys[p.AuthKeyName]; ok == true {
|
||||
if key.Type == "standard" {
|
||||
p.Provider, err = auth.New(key.Key, nil)
|
||||
if err != nil {
|
||||
log.Debugf("failed to create new standard auth provider: %v", err)
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("failed to create new standard auth provider"))
|
||||
}
|
||||
} else {
|
||||
log.Debugf("unknown authentication type %v", key.Type)
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("unknown authentication type"))
|
||||
}
|
||||
} else {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("failed to find auth_key in auth_keys section"))
|
||||
}
|
||||
}
|
||||
|
||||
if p.AuthRemote.AuthKeyName != "" {
|
||||
log.Debug("match auth remote key in profile to auth_keys section")
|
||||
if key, ok := cfg.AuthKeys[p.AuthRemote.AuthKeyName]; ok == true {
|
||||
if key.Type == "standard" {
|
||||
p.RemoteProvider, err = auth.New(key.Key, nil)
|
||||
if err != nil {
|
||||
log.Debugf("failed to create new standard auth provider: %v", err)
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("failed to create new standard auth provider"))
|
||||
}
|
||||
} else {
|
||||
log.Debugf("unknown authentication type %v", key.Type)
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("unknown authentication type"))
|
||||
}
|
||||
} else {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("failed to find auth_remote's auth_key in auth_keys section"))
|
||||
}
|
||||
}
|
||||
|
||||
if p.NameWhitelistString != "" {
|
||||
log.Debug("compiling whitelist regular expression")
|
||||
rule, err := regexp.Compile(p.NameWhitelistString)
|
||||
if err != nil {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("failed to compile name whitelist section"))
|
||||
}
|
||||
p.NameWhitelist = rule
|
||||
}
|
||||
|
||||
p.ExtensionWhitelist = map[string]bool{}
|
||||
for _, oid := range p.AllowedExtensions {
|
||||
p.ExtensionWhitelist[asn1.ObjectIdentifier(oid).String()] = true
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateRemote takes a signing profile and initializes the remote server object
|
||||
// to the hostname:port combination sent by remote.
|
||||
func (p *SigningProfile) updateRemote(remote string) error {
|
||||
if remote != "" {
|
||||
p.RemoteServer = remote
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// OverrideRemotes takes a signing configuration and updates the remote server object
|
||||
// to the hostname:port combination sent by remote
|
||||
func (p *Signing) OverrideRemotes(remote string) error {
|
||||
if remote != "" {
|
||||
var err error
|
||||
for _, profile := range p.Profiles {
|
||||
err = profile.updateRemote(remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err = p.Default.updateRemote(remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetClientCertKeyPairFromFile updates the properties to set client certificates for mutual
|
||||
// authenticated TLS remote requests
|
||||
func (p *Signing) SetClientCertKeyPairFromFile(certFile string, keyFile string) error {
|
||||
if certFile != "" && keyFile != "" {
|
||||
cert, err := helpers.LoadClientCertificate(certFile, keyFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, profile := range p.Profiles {
|
||||
profile.ClientCert = cert
|
||||
}
|
||||
p.Default.ClientCert = cert
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRemoteCAsFromFile reads root CAs from file and updates the properties to set remote CAs for TLS
|
||||
// remote requests
|
||||
func (p *Signing) SetRemoteCAsFromFile(caFile string) error {
|
||||
if caFile != "" {
|
||||
remoteCAs, err := helpers.LoadPEMCertPool(caFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.SetRemoteCAs(remoteCAs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRemoteCAs updates the properties to set remote CAs for TLS
|
||||
// remote requests
|
||||
func (p *Signing) SetRemoteCAs(remoteCAs *x509.CertPool) {
|
||||
for _, profile := range p.Profiles {
|
||||
profile.RemoteCAs = remoteCAs
|
||||
}
|
||||
p.Default.RemoteCAs = remoteCAs
|
||||
}
|
||||
|
||||
// NeedsRemoteSigner returns true if one of the profiles has a remote set
|
||||
func (p *Signing) NeedsRemoteSigner() bool {
|
||||
for _, profile := range p.Profiles {
|
||||
if profile.RemoteServer != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if p.Default.RemoteServer != "" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// NeedsLocalSigner returns true if one of the profiles doe not have a remote set
|
||||
func (p *Signing) NeedsLocalSigner() bool {
|
||||
for _, profile := range p.Profiles {
|
||||
if profile.RemoteServer == "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if p.Default.RemoteServer == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Usages parses the list of key uses in the profile, translating them
|
||||
// to a list of X.509 key usages and extended key usages. The unknown
|
||||
// uses are collected into a slice that is also returned.
|
||||
func (p *SigningProfile) Usages() (ku x509.KeyUsage, eku []x509.ExtKeyUsage, unk []string) {
|
||||
for _, keyUse := range p.Usage {
|
||||
if kuse, ok := KeyUsage[keyUse]; ok {
|
||||
ku |= kuse
|
||||
} else if ekuse, ok := ExtKeyUsage[keyUse]; ok {
|
||||
eku = append(eku, ekuse)
|
||||
} else {
|
||||
unk = append(unk, keyUse)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// A valid profile must be a valid local profile or a valid remote profile.
|
||||
// A valid local profile has defined at least key usages to be used, and a
|
||||
// valid local default profile has defined at least a default expiration.
|
||||
// A valid remote profile (default or not) has remote signer initialized.
|
||||
// In addition, a remote profile must has a valid auth provider if auth
|
||||
// key defined.
|
||||
func (p *SigningProfile) validProfile(isDefault bool) bool {
|
||||
if p == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if p.AuthRemote.RemoteName == "" && p.AuthRemote.AuthKeyName != "" {
|
||||
log.Debugf("invalid auth remote profile: no remote signer specified")
|
||||
return false
|
||||
}
|
||||
|
||||
if p.RemoteName != "" {
|
||||
log.Debugf("validate remote profile")
|
||||
|
||||
if p.RemoteServer == "" {
|
||||
log.Debugf("invalid remote profile: no remote signer specified")
|
||||
return false
|
||||
}
|
||||
|
||||
if p.AuthKeyName != "" && p.Provider == nil {
|
||||
log.Debugf("invalid remote profile: auth key name is defined but no auth provider is set")
|
||||
return false
|
||||
}
|
||||
|
||||
if p.AuthRemote.RemoteName != "" {
|
||||
log.Debugf("invalid remote profile: auth remote is also specified")
|
||||
return false
|
||||
}
|
||||
} else if p.AuthRemote.RemoteName != "" {
|
||||
log.Debugf("validate auth remote profile")
|
||||
if p.RemoteServer == "" {
|
||||
log.Debugf("invalid auth remote profile: no remote signer specified")
|
||||
return false
|
||||
}
|
||||
|
||||
if p.AuthRemote.AuthKeyName == "" || p.RemoteProvider == nil {
|
||||
log.Debugf("invalid auth remote profile: no auth key is defined")
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
log.Debugf("validate local profile")
|
||||
if !isDefault {
|
||||
if len(p.Usage) == 0 {
|
||||
log.Debugf("invalid local profile: no usages specified")
|
||||
return false
|
||||
} else if _, _, unk := p.Usages(); len(unk) == len(p.Usage) {
|
||||
log.Debugf("invalid local profile: no valid usages")
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if p.Expiry == 0 {
|
||||
log.Debugf("invalid local profile: no expiry set")
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Debugf("profile is valid")
|
||||
return true
|
||||
}
|
||||
|
||||
// This checks if the SigningProfile object contains configurations that are only effective with a local signer
|
||||
// which has access to CA private key.
|
||||
func (p *SigningProfile) hasLocalConfig() bool {
|
||||
if p.Usage != nil ||
|
||||
p.IssuerURL != nil ||
|
||||
p.OCSP != "" ||
|
||||
p.ExpiryString != "" ||
|
||||
p.BackdateString != "" ||
|
||||
p.CAConstraint.IsCA != false ||
|
||||
!p.NotBefore.IsZero() ||
|
||||
!p.NotAfter.IsZero() ||
|
||||
p.NameWhitelistString != "" ||
|
||||
len(p.CTLogServers) != 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// warnSkippedSettings prints a log warning message about skipped settings
|
||||
// in a SigningProfile, usually due to remote signer.
|
||||
func (p *Signing) warnSkippedSettings() {
|
||||
const warningMessage = `The configuration value by "usages", "issuer_urls", "ocsp_url", "crl_url", "ca_constraint", "expiry", "backdate", "not_before", "not_after", "cert_store" and "ct_log_servers" are skipped`
|
||||
if p == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if (p.Default.RemoteName != "" || p.Default.AuthRemote.RemoteName != "") && p.Default.hasLocalConfig() {
|
||||
log.Warning("default profile points to a remote signer: ", warningMessage)
|
||||
}
|
||||
|
||||
for name, profile := range p.Profiles {
|
||||
if (profile.RemoteName != "" || profile.AuthRemote.RemoteName != "") && profile.hasLocalConfig() {
|
||||
log.Warningf("Profiles[%s] points to a remote signer: %s", name, warningMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Signing codifies the signature configuration policy for a CA.
|
||||
type Signing struct {
|
||||
Profiles map[string]*SigningProfile `json:"profiles"`
|
||||
Default *SigningProfile `json:"default"`
|
||||
}
|
||||
|
||||
// Config stores configuration information for the CA.
|
||||
type Config struct {
|
||||
Signing *Signing `json:"signing"`
|
||||
OCSP *ocspConfig.Config `json:"ocsp"`
|
||||
AuthKeys map[string]AuthKey `json:"auth_keys,omitempty"`
|
||||
Remotes map[string]string `json:"remotes,omitempty"`
|
||||
}
|
||||
|
||||
// Valid ensures that Config is a valid configuration. It should be
|
||||
// called immediately after parsing a configuration file.
|
||||
func (c *Config) Valid() bool {
|
||||
return c.Signing.Valid()
|
||||
}
|
||||
|
||||
// Valid checks the signature policies, ensuring they are valid
|
||||
// policies. A policy is valid if it has defined at least key usages
|
||||
// to be used, and a valid default profile has defined at least a
|
||||
// default expiration.
|
||||
func (p *Signing) Valid() bool {
|
||||
if p == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
log.Debugf("validating configuration")
|
||||
if !p.Default.validProfile(true) {
|
||||
log.Debugf("default profile is invalid")
|
||||
return false
|
||||
}
|
||||
|
||||
for _, sp := range p.Profiles {
|
||||
if !sp.validProfile(false) {
|
||||
log.Debugf("invalid profile")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
p.warnSkippedSettings()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// KeyUsage contains a mapping of string names to key usages.
|
||||
var KeyUsage = map[string]x509.KeyUsage{
|
||||
"signing": x509.KeyUsageDigitalSignature,
|
||||
"digital signature": x509.KeyUsageDigitalSignature,
|
||||
"content commitment": x509.KeyUsageContentCommitment,
|
||||
"key encipherment": x509.KeyUsageKeyEncipherment,
|
||||
"key agreement": x509.KeyUsageKeyAgreement,
|
||||
"data encipherment": x509.KeyUsageDataEncipherment,
|
||||
"cert sign": x509.KeyUsageCertSign,
|
||||
"crl sign": x509.KeyUsageCRLSign,
|
||||
"encipher only": x509.KeyUsageEncipherOnly,
|
||||
"decipher only": x509.KeyUsageDecipherOnly,
|
||||
}
|
||||
|
||||
// ExtKeyUsage contains a mapping of string names to extended key
|
||||
// usages.
|
||||
var ExtKeyUsage = map[string]x509.ExtKeyUsage{
|
||||
"any": x509.ExtKeyUsageAny,
|
||||
"server auth": x509.ExtKeyUsageServerAuth,
|
||||
"client auth": x509.ExtKeyUsageClientAuth,
|
||||
"code signing": x509.ExtKeyUsageCodeSigning,
|
||||
"email protection": x509.ExtKeyUsageEmailProtection,
|
||||
"s/mime": x509.ExtKeyUsageEmailProtection,
|
||||
"ipsec end system": x509.ExtKeyUsageIPSECEndSystem,
|
||||
"ipsec tunnel": x509.ExtKeyUsageIPSECTunnel,
|
||||
"ipsec user": x509.ExtKeyUsageIPSECUser,
|
||||
"timestamping": x509.ExtKeyUsageTimeStamping,
|
||||
"ocsp signing": x509.ExtKeyUsageOCSPSigning,
|
||||
"microsoft sgc": x509.ExtKeyUsageMicrosoftServerGatedCrypto,
|
||||
"netscape sgc": x509.ExtKeyUsageNetscapeServerGatedCrypto,
|
||||
}
|
||||
|
||||
// An AuthKey contains an entry for a key used for authentication.
|
||||
type AuthKey struct {
|
||||
// Type contains information needed to select the appropriate
|
||||
// constructor. For example, "standard" for HMAC-SHA-256,
|
||||
// "standard-ip" for HMAC-SHA-256 incorporating the client's
|
||||
// IP.
|
||||
Type string `json:"type"`
|
||||
// Key contains the key information, such as a hex-encoded
|
||||
// HMAC key.
|
||||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// DefaultConfig returns a default configuration specifying basic key
|
||||
// usage and a 1 year expiration time. The key usages chosen are
|
||||
// signing, key encipherment, client auth and server auth.
|
||||
func DefaultConfig() *SigningProfile {
|
||||
d := helpers.OneYear
|
||||
return &SigningProfile{
|
||||
Usage: []string{"signing", "key encipherment", "server auth", "client auth"},
|
||||
Expiry: d,
|
||||
ExpiryString: "8760h",
|
||||
}
|
||||
}
|
||||
|
||||
// LoadFile attempts to load the configuration file stored at the path
|
||||
// and returns the configuration. On error, it returns nil.
|
||||
func LoadFile(path string) (*Config, error) {
|
||||
log.Debugf("loading configuration file from %s", path)
|
||||
if path == "" {
|
||||
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid path"))
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("could not read configuration file"))
|
||||
}
|
||||
|
||||
return LoadConfig(body)
|
||||
}
|
||||
|
||||
// LoadConfig attempts to load the configuration from a byte slice.
|
||||
// On error, it returns nil.
|
||||
func LoadConfig(config []byte) (*Config, error) {
|
||||
var cfg = &Config{}
|
||||
err := json.Unmarshal(config, &cfg)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
|
||||
errors.New("failed to unmarshal configuration: "+err.Error()))
|
||||
}
|
||||
|
||||
if cfg.Signing == nil {
|
||||
return nil, errors.New("No \"signing\" field present")
|
||||
}
|
||||
|
||||
if cfg.Signing.Default == nil {
|
||||
log.Debugf("no default given: using default config")
|
||||
cfg.Signing.Default = DefaultConfig()
|
||||
} else {
|
||||
if err := cfg.Signing.Default.populate(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for k := range cfg.Signing.Profiles {
|
||||
if err := cfg.Signing.Profiles[k].populate(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if !cfg.Valid() {
|
||||
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid configuration"))
|
||||
}
|
||||
|
||||
log.Debugf("configuration ok")
|
||||
return cfg, nil
|
||||
}
|
537
vendor/github.com/cloudflare/cfssl/config/config_test.go
generated
vendored
Normal file
537
vendor/github.com/cloudflare/cfssl/config/config_test.go
generated
vendored
Normal file
@ -0,0 +1,537 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var expiry = 1 * time.Minute
|
||||
|
||||
var invalidProfileConfig = &Config{
|
||||
Signing: &Signing{
|
||||
Profiles: map[string]*SigningProfile{
|
||||
"invalid": {
|
||||
Usage: []string{"wiretapping"},
|
||||
Expiry: expiry,
|
||||
},
|
||||
"empty": {},
|
||||
},
|
||||
Default: &SigningProfile{
|
||||
Usage: []string{"digital signature"},
|
||||
Expiry: expiry,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var invalidDefaultConfig = &Config{
|
||||
Signing: &Signing{
|
||||
Profiles: map[string]*SigningProfile{
|
||||
"key usage": {
|
||||
Usage: []string{"digital signature"},
|
||||
},
|
||||
},
|
||||
Default: &SigningProfile{
|
||||
Usage: []string{"s/mime"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var validConfig = &Config{
|
||||
Signing: &Signing{
|
||||
Profiles: map[string]*SigningProfile{
|
||||
"valid": {
|
||||
Usage: []string{"digital signature"},
|
||||
Expiry: expiry,
|
||||
},
|
||||
},
|
||||
Default: &SigningProfile{
|
||||
Usage: []string{"digital signature"},
|
||||
Expiry: expiry,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var validMixedConfig = `
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"auth_key": "sample",
|
||||
"remote": "localhost"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"sample": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}`
|
||||
|
||||
var validMinimalRemoteConfig = `
|
||||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"auth_key": "sample",
|
||||
"remote": "localhost"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"sample": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}`
|
||||
|
||||
var validMinimalRemoteConfig2 = `
|
||||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"auth_remote":{
|
||||
"auth_key": "sample",
|
||||
"remote": "localhost"
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"sample": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}`
|
||||
|
||||
var invalidConflictRemoteConfig = `
|
||||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"auth_remote":{
|
||||
"auth_key": "sample",
|
||||
"remote": "localhost"
|
||||
},
|
||||
"remote": "localhost"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"sample": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}`
|
||||
|
||||
var invalidRemoteConfig = `
|
||||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"auth_remotes_typos":{
|
||||
"auth_key": "sample",
|
||||
"remote": "localhost"
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"sample": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}`
|
||||
|
||||
var invalidAuthRemoteConfigMissingRemote = `
|
||||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"auth_remote":{
|
||||
"auth_key": "sample"
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"sample": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}`
|
||||
|
||||
var invalidAuthRemoteConfigMissingKey = `
|
||||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"auth_remote":{
|
||||
"remote": "localhost"
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"sample": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}`
|
||||
|
||||
var validMinimalLocalConfig = `
|
||||
{
|
||||
"signing": {
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
var validLocalConfigsWithCAConstraint = []string{
|
||||
`{
|
||||
"signing": {
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"ca_constraint": { "is_ca": true },
|
||||
"expiry": "8000h"
|
||||
}
|
||||
}
|
||||
}`,
|
||||
`{
|
||||
"signing": {
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"ca_constraint": { "is_ca": true, "max_path_len": 1 },
|
||||
"expiry": "8000h"
|
||||
}
|
||||
}
|
||||
}`,
|
||||
`{
|
||||
"signing": {
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"ca_constraint": { "is_ca": true, "max_path_len_zero": true },
|
||||
"expiry": "8000h"
|
||||
}
|
||||
}
|
||||
}`,
|
||||
}
|
||||
|
||||
func TestInvalidProfile(t *testing.T) {
|
||||
if invalidProfileConfig.Signing.Profiles["invalid"].validProfile(false) {
|
||||
t.Fatal("invalid profile accepted as valid")
|
||||
}
|
||||
|
||||
if invalidProfileConfig.Signing.Profiles["empty"].validProfile(false) {
|
||||
t.Fatal("invalid profile accepted as valid")
|
||||
}
|
||||
|
||||
if invalidProfileConfig.Valid() {
|
||||
t.Fatal("invalid config accepted as valid")
|
||||
}
|
||||
|
||||
if !invalidProfileConfig.Signing.Profiles["invalid"].validProfile(true) {
|
||||
t.Fatal("invalid profile should be a valid default profile")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoteProfiles(t *testing.T) {
|
||||
var validRemoteProfile = &SigningProfile{
|
||||
RemoteName: "localhost",
|
||||
RemoteServer: "localhost:8080",
|
||||
}
|
||||
|
||||
var invalidRemoteProfile = &SigningProfile{
|
||||
RemoteName: "localhost",
|
||||
}
|
||||
|
||||
var invalidRemoteAuthProfile = &SigningProfile{
|
||||
RemoteName: "localhost",
|
||||
RemoteServer: "localhost:8080",
|
||||
AuthKeyName: "blahblah",
|
||||
}
|
||||
|
||||
if !validRemoteProfile.validProfile(true) ||
|
||||
!validRemoteProfile.validProfile(false) {
|
||||
t.Fatal("valid remote profile is rejected.")
|
||||
}
|
||||
|
||||
if invalidRemoteProfile.validProfile(true) ||
|
||||
invalidRemoteProfile.validProfile(false) {
|
||||
t.Fatal("invalid remote profile is accepted.")
|
||||
}
|
||||
|
||||
if invalidRemoteAuthProfile.validProfile(true) ||
|
||||
invalidRemoteAuthProfile.validProfile(false) {
|
||||
t.Fatal("invalid remote profile is accepted.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidDefault(t *testing.T) {
|
||||
if invalidDefaultConfig.Signing.Default.validProfile(true) {
|
||||
t.Fatal("invalid default accepted as valid")
|
||||
}
|
||||
|
||||
if invalidDefaultConfig.Valid() {
|
||||
t.Fatal("invalid config accepted as valid")
|
||||
}
|
||||
|
||||
if !invalidDefaultConfig.Signing.Default.validProfile(false) {
|
||||
t.Fatal("invalid default profile should be a valid profile")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidConfig(t *testing.T) {
|
||||
if !validConfig.Valid() {
|
||||
t.Fatal("Valid config is not valid")
|
||||
}
|
||||
bytes, _ := json.Marshal(validConfig)
|
||||
fmt.Printf("%v", string(bytes))
|
||||
}
|
||||
|
||||
func TestDefaultConfig(t *testing.T) {
|
||||
if !DefaultConfig().validProfile(false) {
|
||||
t.Fatal("global default signing profile should be a valid profile.")
|
||||
}
|
||||
|
||||
if !DefaultConfig().validProfile(true) {
|
||||
t.Fatal("global default signing profile should be a valid default profile")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
var validProfiles = []*SigningProfile{
|
||||
{
|
||||
ExpiryString: "8760h",
|
||||
},
|
||||
{
|
||||
ExpiryString: "168h",
|
||||
},
|
||||
{
|
||||
ExpiryString: "300s",
|
||||
},
|
||||
}
|
||||
|
||||
var invalidProfiles = []*SigningProfile{
|
||||
nil,
|
||||
{},
|
||||
{
|
||||
ExpiryString: "",
|
||||
},
|
||||
{
|
||||
ExpiryString: "365d",
|
||||
},
|
||||
{
|
||||
ExpiryString: "1y",
|
||||
},
|
||||
{
|
||||
ExpiryString: "one year",
|
||||
},
|
||||
}
|
||||
|
||||
for _, p := range validProfiles {
|
||||
if p.populate(nil) != nil {
|
||||
t.Fatalf("Failed to parse ExpiryString=%s", p.ExpiryString)
|
||||
}
|
||||
}
|
||||
|
||||
for _, p := range invalidProfiles {
|
||||
if p.populate(nil) == nil {
|
||||
if p != nil {
|
||||
t.Fatalf("ExpiryString=%s should not be parseable", p.ExpiryString)
|
||||
}
|
||||
t.Fatalf("Nil profile should not be parseable")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestLoadFile(t *testing.T) {
|
||||
validConfigFiles := []string{
|
||||
"testdata/valid_config.json",
|
||||
"testdata/valid_config_auth.json",
|
||||
"testdata/valid_config_no_default.json",
|
||||
"testdata/valid_config_auth_no_default.json",
|
||||
}
|
||||
|
||||
for _, configFile := range validConfigFiles {
|
||||
_, err := LoadFile(configFile)
|
||||
if err != nil {
|
||||
t.Fatal("Load valid config file failed.", configFile, "error is ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadInvalidConfigFile(t *testing.T) {
|
||||
invalidConfigFiles := []string{"", "testdata/no_such_file",
|
||||
"testdata/invalid_default.json",
|
||||
"testdata/invalid_profiles.json",
|
||||
"testdata/invalid_usage.json",
|
||||
"testdata/invalid_config.json",
|
||||
"testdata/invalid_auth.json",
|
||||
"testdata/invalid_auth_bad_key.json",
|
||||
"testdata/invalid_no_auth_keys.json",
|
||||
"testdata/invalid_remote.json",
|
||||
"testdata/invalid_no_remotes.json",
|
||||
}
|
||||
for _, configFile := range invalidConfigFiles {
|
||||
_, err := LoadFile(configFile)
|
||||
if err == nil {
|
||||
t.Fatal("Invalid config is loaded.", configFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNeedLocalSigner(t *testing.T) {
|
||||
|
||||
c, err := LoadConfig([]byte(validMixedConfig))
|
||||
if err != nil {
|
||||
t.Fatal("load valid config failed:", err)
|
||||
}
|
||||
|
||||
// This signing config needs both local signer and remote signer.
|
||||
if c.Signing.NeedsLocalSigner() != true {
|
||||
t.Fatal("incorrect NeedsLocalSigner().")
|
||||
}
|
||||
|
||||
if c.Signing.NeedsRemoteSigner() != true {
|
||||
t.Fatal("incorrect NeedsRemoteSigner()")
|
||||
}
|
||||
|
||||
remoteConfig, err := LoadConfig([]byte(validMinimalRemoteConfig))
|
||||
if err != nil {
|
||||
t.Fatal("Load valid config failed:", err)
|
||||
}
|
||||
|
||||
if remoteConfig.Signing.NeedsLocalSigner() != false {
|
||||
t.Fatal("incorrect NeedsLocalSigner().")
|
||||
}
|
||||
|
||||
if remoteConfig.Signing.NeedsRemoteSigner() != true {
|
||||
t.Fatal("incorrect NeedsRemoteSigner().")
|
||||
}
|
||||
|
||||
localConfig, err := LoadConfig([]byte(validMinimalLocalConfig))
|
||||
if localConfig.Signing.NeedsLocalSigner() != true {
|
||||
t.Fatal("incorrect NeedsLocalSigner().")
|
||||
}
|
||||
|
||||
if localConfig.Signing.NeedsRemoteSigner() != false {
|
||||
t.Fatal("incorrect NeedsRemoteSigner().")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOverrideRemotes(t *testing.T) {
|
||||
c, err := LoadConfig([]byte(validMixedConfig))
|
||||
if err != nil {
|
||||
t.Fatal("load valid config failed:", err)
|
||||
}
|
||||
|
||||
host := "localhost:8888"
|
||||
c.Signing.OverrideRemotes(host)
|
||||
|
||||
if c.Signing.Default.RemoteServer != host {
|
||||
t.Fatal("should override default profile's RemoteServer")
|
||||
}
|
||||
|
||||
for _, p := range c.Signing.Profiles {
|
||||
if p.RemoteServer != host {
|
||||
t.Fatal("failed to override profile's RemoteServer")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAuthRemoteConfig(t *testing.T) {
|
||||
c, err := LoadConfig([]byte(validMinimalRemoteConfig2))
|
||||
if err != nil {
|
||||
t.Fatal("load valid config failed:", err)
|
||||
}
|
||||
|
||||
if c.Signing.Default.RemoteServer != "127.0.0.1:8888" {
|
||||
t.Fatal("load valid config failed: incorrect remote server")
|
||||
}
|
||||
|
||||
host := "localhost:8888"
|
||||
c.Signing.OverrideRemotes(host)
|
||||
|
||||
if c.Signing.Default.RemoteServer != host {
|
||||
t.Fatal("should override default profile's RemoteServer")
|
||||
}
|
||||
|
||||
for _, p := range c.Signing.Profiles {
|
||||
if p.RemoteServer != host {
|
||||
t.Fatal("failed to override profile's RemoteServer")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDuplicateRemoteConfig(t *testing.T) {
|
||||
_, err := LoadConfig([]byte(invalidConflictRemoteConfig))
|
||||
if err == nil {
|
||||
t.Fatal("fail to reject invalid config")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadAuthRemoteConfig(t *testing.T) {
|
||||
_, err := LoadConfig([]byte(invalidRemoteConfig))
|
||||
if err == nil {
|
||||
t.Fatal("load invalid config should failed")
|
||||
}
|
||||
|
||||
_, err = LoadConfig([]byte(invalidAuthRemoteConfigMissingRemote))
|
||||
if err == nil {
|
||||
t.Fatal("load invalid config should failed")
|
||||
}
|
||||
|
||||
_, err = LoadConfig([]byte(invalidAuthRemoteConfigMissingKey))
|
||||
if err == nil {
|
||||
t.Fatal("load invalid config should failed")
|
||||
}
|
||||
|
||||
var p *Signing
|
||||
if p.Valid() {
|
||||
t.Fatal("nil Signing config should be invalid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidCAConstraint(t *testing.T) {
|
||||
for _, config := range validLocalConfigsWithCAConstraint {
|
||||
_, err := LoadConfig([]byte(config))
|
||||
if err != nil {
|
||||
t.Fatal("can't parse valid ca constraint")
|
||||
}
|
||||
}
|
||||
}
|
27
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_auth.json
generated
vendored
Normal file
27
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_auth.json
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"remote": "localhost",
|
||||
"auth_key": "garbage"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"garbage": {
|
||||
"type":"stadardo",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}
|
27
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_auth_bad_key.json
generated
vendored
Normal file
27
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_auth_bad_key.json
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"remote": "localhost",
|
||||
"auth_key": "garbage"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"garbage": {
|
||||
"type":"standard",
|
||||
"key":"BAD_KEY"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}
|
17
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_config.json
generated
vendored
Normal file
17
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_config.json
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"usages": ["cert sign"],
|
||||
"expiry": "720h"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
}
|
||||
}
|
||||
}
|
18
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_default.json
generated
vendored
Normal file
18
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_default.json
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"usages": ["cert sign"],
|
||||
"expiry": "720h"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "invalid_expiry"
|
||||
}
|
||||
}
|
||||
}
|
23
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_no_auth_keys.json
generated
vendored
Normal file
23
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_no_auth_keys.json
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"remote": "localhost",
|
||||
"auth_key": "garbage"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}
|
24
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_no_remotes.json
generated
vendored
Normal file
24
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_no_remotes.json
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"auth_key": "garbage",
|
||||
"remote": "localhoster"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"garbage": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
}
|
||||
}
|
18
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_profile.json
generated
vendored
Normal file
18
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_profile.json
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"usages": ["cert sign"],
|
||||
"expiry": "720h"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "invalid_expiry"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
}
|
||||
}
|
27
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_remotes.json
generated
vendored
Normal file
27
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_remotes.json
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"auth_key": "garbage",
|
||||
"remote": "localhoster"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"garbage": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}
|
18
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_usage.json
generated
vendored
Normal file
18
vendor/github.com/cloudflare/cfssl/config/testdata/invalid_usage.json
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"usages": ["cert sign"],
|
||||
"expiry": "720h"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["BAD_USAGE"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
}
|
||||
}
|
24
vendor/github.com/cloudflare/cfssl/config/testdata/valid_config.json
generated
vendored
Normal file
24
vendor/github.com/cloudflare/cfssl/config/testdata/valid_config.json
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"usages": ["cert sign"],
|
||||
"expiry": "720h"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
},
|
||||
"auth_key": {
|
||||
"garbage": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
}
|
||||
}
|
29
vendor/github.com/cloudflare/cfssl/config/testdata/valid_config_auth.json
generated
vendored
Normal file
29
vendor/github.com/cloudflare/cfssl/config/testdata/valid_config_auth.json
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"usages": ["cert sign"],
|
||||
"expiry": "720h",
|
||||
"auth_key": "garbage",
|
||||
"remote": "localhost"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"usages": ["digital signature", "email protection"],
|
||||
"expiry": "8000h"
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"garbage": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}
|
19
vendor/github.com/cloudflare/cfssl/config/testdata/valid_config_auth_no_default.json
generated
vendored
Normal file
19
vendor/github.com/cloudflare/cfssl/config/testdata/valid_config_auth_no_default.json
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"auth_key": "garbage",
|
||||
"remote": "localhost"
|
||||
}
|
||||
}
|
||||
},
|
||||
"auth_keys": {
|
||||
"garbage": {
|
||||
"type":"standard",
|
||||
"key":"0123456789ABCDEF0123456789ABCDEF"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"localhost": "127.0.0.1:8888"
|
||||
}
|
||||
}
|
14
vendor/github.com/cloudflare/cfssl/config/testdata/valid_config_no_default.json
generated
vendored
Normal file
14
vendor/github.com/cloudflare/cfssl/config/testdata/valid_config_no_default.json
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"signing": {
|
||||
"profiles": {
|
||||
"CA": {
|
||||
"usages": ["cert sign"],
|
||||
"expiry": "720h"
|
||||
},
|
||||
"email": {
|
||||
"usages": ["s/mime"],
|
||||
"expiry": "720h"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
188
vendor/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go
generated
vendored
Normal file
188
vendor/github.com/cloudflare/cfssl/crypto/pkcs7/pkcs7.go
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
||||
// Package pkcs7 implements the subset of the CMS PKCS #7 datatype that is typically
|
||||
// used to package certificates and CRLs. Using openssl, every certificate converted
|
||||
// to PKCS #7 format from another encoding such as PEM conforms to this implementation.
|
||||
// reference: https://www.openssl.org/docs/man1.1.0/apps/crl2pkcs7.html
|
||||
//
|
||||
// PKCS #7 Data type, reference: https://tools.ietf.org/html/rfc2315
|
||||
//
|
||||
// The full pkcs#7 cryptographic message syntax allows for cryptographic enhancements,
|
||||
// for example data can be encrypted and signed and then packaged through pkcs#7 to be
|
||||
// sent over a network and then verified and decrypted. It is asn1, and the type of
|
||||
// PKCS #7 ContentInfo, which comprises the PKCS #7 structure, is:
|
||||
//
|
||||
// ContentInfo ::= SEQUENCE {
|
||||
// contentType ContentType,
|
||||
// content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
|
||||
// }
|
||||
//
|
||||
// There are 6 possible ContentTypes, data, signedData, envelopedData,
|
||||
// signedAndEnvelopedData, digestedData, and encryptedData. Here signedData, Data, and encrypted
|
||||
// Data are implemented, as the degenerate case of signedData without a signature is the typical
|
||||
// format for transferring certificates and CRLS, and Data and encryptedData are used in PKCS #12
|
||||
// formats.
|
||||
// The ContentType signedData has the form:
|
||||
//
|
||||
//
|
||||
// signedData ::= SEQUENCE {
|
||||
// version Version,
|
||||
// digestAlgorithms DigestAlgorithmIdentifiers,
|
||||
// contentInfo ContentInfo,
|
||||
// certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL
|
||||
// crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
|
||||
// signerInfos SignerInfos
|
||||
// }
|
||||
//
|
||||
// As of yet signerInfos and digestAlgorithms are not parsed, as they are not relevant to
|
||||
// this system's use of PKCS #7 data. Version is an integer type, note that PKCS #7 is
|
||||
// recursive, this second layer of ContentInfo is similar ignored for our degenerate
|
||||
// usage. The ExtendedCertificatesAndCertificates type consists of a sequence of choices
|
||||
// between PKCS #6 extended certificates and x509 certificates. Any sequence consisting
|
||||
// of any number of extended certificates is not yet supported in this implementation.
|
||||
//
|
||||
// The ContentType Data is simply a raw octet string and is parsed directly into a Go []byte slice.
|
||||
//
|
||||
// The ContentType encryptedData is the most complicated and its form can be gathered by
|
||||
// the go type below. It essentially contains a raw octet string of encrypted data and an
|
||||
// algorithm identifier for use in decrypting this data.
|
||||
package pkcs7
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
)
|
||||
|
||||
// Types used for asn1 Unmarshaling.
|
||||
|
||||
type signedData struct {
|
||||
Version int
|
||||
DigestAlgorithms asn1.RawValue
|
||||
ContentInfo asn1.RawValue
|
||||
Certificates asn1.RawValue `asn1:"optional" asn1:"tag:0"`
|
||||
Crls asn1.RawValue `asn1:"optional"`
|
||||
SignerInfos asn1.RawValue
|
||||
}
|
||||
|
||||
type initPKCS7 struct {
|
||||
Raw asn1.RawContent
|
||||
ContentType asn1.ObjectIdentifier
|
||||
Content asn1.RawValue `asn1:"tag:0,explicit,optional"`
|
||||
}
|
||||
|
||||
// Object identifier strings of the three implemented PKCS7 types.
|
||||
const (
|
||||
ObjIDData = "1.2.840.113549.1.7.1"
|
||||
ObjIDSignedData = "1.2.840.113549.1.7.2"
|
||||
ObjIDEncryptedData = "1.2.840.113549.1.7.6"
|
||||
)
|
||||
|
||||
// PKCS7 represents the ASN1 PKCS #7 Content type. It contains one of three
|
||||
// possible types of Content objects, as denoted by the object identifier in
|
||||
// the ContentInfo field, the other two being nil. SignedData
|
||||
// is the degenerate SignedData Content info without signature used
|
||||
// to hold certificates and crls. Data is raw bytes, and EncryptedData
|
||||
// is as defined in PKCS #7 standard.
|
||||
type PKCS7 struct {
|
||||
Raw asn1.RawContent
|
||||
ContentInfo string
|
||||
Content Content
|
||||
}
|
||||
|
||||
// Content implements three of the six possible PKCS7 data types. Only one is non-nil.
|
||||
type Content struct {
|
||||
Data []byte
|
||||
SignedData SignedData
|
||||
EncryptedData EncryptedData
|
||||
}
|
||||
|
||||
// SignedData defines the typical carrier of certificates and crls.
|
||||
type SignedData struct {
|
||||
Raw asn1.RawContent
|
||||
Version int
|
||||
Certificates []*x509.Certificate
|
||||
Crl *pkix.CertificateList
|
||||
}
|
||||
|
||||
// Data contains raw bytes. Used as a subtype in PKCS12.
|
||||
type Data struct {
|
||||
Bytes []byte
|
||||
}
|
||||
|
||||
// EncryptedData contains encrypted data. Used as a subtype in PKCS12.
|
||||
type EncryptedData struct {
|
||||
Raw asn1.RawContent
|
||||
Version int
|
||||
EncryptedContentInfo EncryptedContentInfo
|
||||
}
|
||||
|
||||
// EncryptedContentInfo is a subtype of PKCS7EncryptedData.
|
||||
type EncryptedContentInfo struct {
|
||||
Raw asn1.RawContent
|
||||
ContentType asn1.ObjectIdentifier
|
||||
ContentEncryptionAlgorithm pkix.AlgorithmIdentifier
|
||||
EncryptedContent []byte `asn1:"tag:0,optional"`
|
||||
}
|
||||
|
||||
// ParsePKCS7 attempts to parse the DER encoded bytes of a
|
||||
// PKCS7 structure.
|
||||
func ParsePKCS7(raw []byte) (msg *PKCS7, err error) {
|
||||
|
||||
var pkcs7 initPKCS7
|
||||
_, err = asn1.Unmarshal(raw, &pkcs7)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
|
||||
}
|
||||
|
||||
msg = new(PKCS7)
|
||||
msg.Raw = pkcs7.Raw
|
||||
msg.ContentInfo = pkcs7.ContentType.String()
|
||||
switch {
|
||||
case msg.ContentInfo == ObjIDData:
|
||||
msg.ContentInfo = "Data"
|
||||
_, err = asn1.Unmarshal(pkcs7.Content.Bytes, &msg.Content.Data)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
|
||||
}
|
||||
case msg.ContentInfo == ObjIDSignedData:
|
||||
msg.ContentInfo = "SignedData"
|
||||
var signedData signedData
|
||||
_, err = asn1.Unmarshal(pkcs7.Content.Bytes, &signedData)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
|
||||
}
|
||||
if len(signedData.Certificates.Bytes) != 0 {
|
||||
msg.Content.SignedData.Certificates, err = x509.ParseCertificates(signedData.Certificates.Bytes)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
|
||||
}
|
||||
}
|
||||
if len(signedData.Crls.Bytes) != 0 {
|
||||
msg.Content.SignedData.Crl, err = x509.ParseDERCRL(signedData.Crls.Bytes)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
|
||||
}
|
||||
}
|
||||
msg.Content.SignedData.Version = signedData.Version
|
||||
msg.Content.SignedData.Raw = pkcs7.Content.Bytes
|
||||
case msg.ContentInfo == ObjIDEncryptedData:
|
||||
msg.ContentInfo = "EncryptedData"
|
||||
var encryptedData EncryptedData
|
||||
_, err = asn1.Unmarshal(pkcs7.Content.Bytes, &encryptedData)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
|
||||
}
|
||||
if encryptedData.Version != 0 {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for PKCS #7 encryptedData version 0"))
|
||||
}
|
||||
msg.Content.EncryptedData = encryptedData
|
||||
|
||||
default:
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Attempt to parse PKCS# 7 Content not of type data, signed data or encrypted data"))
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
|
||||
}
|
432
vendor/github.com/cloudflare/cfssl/csr/csr.go
generated
vendored
Normal file
432
vendor/github.com/cloudflare/cfssl/csr/csr.go
generated
vendored
Normal file
@ -0,0 +1,432 @@
|
||||
// Package csr implements certificate requests for CFSSL.
|
||||
package csr
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"net"
|
||||
"net/mail"
|
||||
"strings"
|
||||
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
)
|
||||
|
||||
const (
|
||||
curveP256 = 256
|
||||
curveP384 = 384
|
||||
curveP521 = 521
|
||||
)
|
||||
|
||||
// A Name contains the SubjectInfo fields.
|
||||
type Name struct {
|
||||
C string // Country
|
||||
ST string // State
|
||||
L string // Locality
|
||||
O string // OrganisationName
|
||||
OU string // OrganisationalUnitName
|
||||
SerialNumber string
|
||||
}
|
||||
|
||||
// A KeyRequest is a generic request for a new key.
|
||||
type KeyRequest interface {
|
||||
Algo() string
|
||||
Size() int
|
||||
Generate() (crypto.PrivateKey, error)
|
||||
SigAlgo() x509.SignatureAlgorithm
|
||||
}
|
||||
|
||||
// A BasicKeyRequest contains the algorithm and key size for a new private key.
|
||||
type BasicKeyRequest struct {
|
||||
A string `json:"algo" yaml:"algo"`
|
||||
S int `json:"size" yaml:"size"`
|
||||
}
|
||||
|
||||
// NewBasicKeyRequest returns a default BasicKeyRequest.
|
||||
func NewBasicKeyRequest() *BasicKeyRequest {
|
||||
return &BasicKeyRequest{"ecdsa", curveP256}
|
||||
}
|
||||
|
||||
// Algo returns the requested key algorithm represented as a string.
|
||||
func (kr *BasicKeyRequest) Algo() string {
|
||||
return kr.A
|
||||
}
|
||||
|
||||
// Size returns the requested key size.
|
||||
func (kr *BasicKeyRequest) Size() int {
|
||||
return kr.S
|
||||
}
|
||||
|
||||
// Generate generates a key as specified in the request. Currently,
|
||||
// only ECDSA and RSA are supported.
|
||||
func (kr *BasicKeyRequest) Generate() (crypto.PrivateKey, error) {
|
||||
log.Debugf("generate key from request: algo=%s, size=%d", kr.Algo(), kr.Size())
|
||||
switch kr.Algo() {
|
||||
case "rsa":
|
||||
if kr.Size() < 2048 {
|
||||
return nil, errors.New("RSA key is too weak")
|
||||
}
|
||||
if kr.Size() > 8192 {
|
||||
return nil, errors.New("RSA key size too large")
|
||||
}
|
||||
return rsa.GenerateKey(rand.Reader, kr.Size())
|
||||
case "ecdsa":
|
||||
var curve elliptic.Curve
|
||||
switch kr.Size() {
|
||||
case curveP256:
|
||||
curve = elliptic.P256()
|
||||
case curveP384:
|
||||
curve = elliptic.P384()
|
||||
case curveP521:
|
||||
curve = elliptic.P521()
|
||||
default:
|
||||
return nil, errors.New("invalid curve")
|
||||
}
|
||||
return ecdsa.GenerateKey(curve, rand.Reader)
|
||||
default:
|
||||
return nil, errors.New("invalid algorithm")
|
||||
}
|
||||
}
|
||||
|
||||
// SigAlgo returns an appropriate X.509 signature algorithm given the
|
||||
// key request's type and size.
|
||||
func (kr *BasicKeyRequest) SigAlgo() x509.SignatureAlgorithm {
|
||||
switch kr.Algo() {
|
||||
case "rsa":
|
||||
switch {
|
||||
case kr.Size() >= 4096:
|
||||
return x509.SHA512WithRSA
|
||||
case kr.Size() >= 3072:
|
||||
return x509.SHA384WithRSA
|
||||
case kr.Size() >= 2048:
|
||||
return x509.SHA256WithRSA
|
||||
default:
|
||||
return x509.SHA1WithRSA
|
||||
}
|
||||
case "ecdsa":
|
||||
switch kr.Size() {
|
||||
case curveP521:
|
||||
return x509.ECDSAWithSHA512
|
||||
case curveP384:
|
||||
return x509.ECDSAWithSHA384
|
||||
case curveP256:
|
||||
return x509.ECDSAWithSHA256
|
||||
default:
|
||||
return x509.ECDSAWithSHA1
|
||||
}
|
||||
default:
|
||||
return x509.UnknownSignatureAlgorithm
|
||||
}
|
||||
}
|
||||
|
||||
// CAConfig is a section used in the requests initialising a new CA.
|
||||
type CAConfig struct {
|
||||
PathLength int `json:"pathlen" yaml:"pathlen"`
|
||||
PathLenZero bool `json:"pathlenzero" yaml:"pathlenzero"`
|
||||
Expiry string `json:"expiry" yaml:"expiry"`
|
||||
Backdate string `json:"backdate" yaml:"backdate"`
|
||||
}
|
||||
|
||||
// A CertificateRequest encapsulates the API interface to the
|
||||
// certificate request functionality.
|
||||
type CertificateRequest struct {
|
||||
CN string
|
||||
Names []Name `json:"names" yaml:"names"`
|
||||
Hosts []string `json:"hosts" yaml:"hosts"`
|
||||
KeyRequest KeyRequest `json:"key,omitempty" yaml:"key,omitempty"`
|
||||
CA *CAConfig `json:"ca,omitempty" yaml:"ca,omitempty"`
|
||||
SerialNumber string `json:"serialnumber,omitempty" yaml:"serialnumber,omitempty"`
|
||||
}
|
||||
|
||||
// New returns a new, empty CertificateRequest with a
|
||||
// BasicKeyRequest.
|
||||
func New() *CertificateRequest {
|
||||
return &CertificateRequest{
|
||||
KeyRequest: NewBasicKeyRequest(),
|
||||
}
|
||||
}
|
||||
|
||||
// appendIf appends to a if s is not an empty string.
|
||||
func appendIf(s string, a *[]string) {
|
||||
if s != "" {
|
||||
*a = append(*a, s)
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the PKIX name for the request.
|
||||
func (cr *CertificateRequest) Name() pkix.Name {
|
||||
var name pkix.Name
|
||||
name.CommonName = cr.CN
|
||||
|
||||
for _, n := range cr.Names {
|
||||
appendIf(n.C, &name.Country)
|
||||
appendIf(n.ST, &name.Province)
|
||||
appendIf(n.L, &name.Locality)
|
||||
appendIf(n.O, &name.Organization)
|
||||
appendIf(n.OU, &name.OrganizationalUnit)
|
||||
}
|
||||
name.SerialNumber = cr.SerialNumber
|
||||
return name
|
||||
}
|
||||
|
||||
// BasicConstraints CSR information RFC 5280, 4.2.1.9
|
||||
type BasicConstraints struct {
|
||||
IsCA bool `asn1:"optional"`
|
||||
MaxPathLen int `asn1:"optional,default:-1"`
|
||||
}
|
||||
|
||||
// ParseRequest takes a certificate request and generates a key and
|
||||
// CSR from it. It does no validation -- caveat emptor. It will,
|
||||
// however, fail if the key request is not valid (i.e., an unsupported
|
||||
// curve or RSA key size). The lack of validation was specifically
|
||||
// chosen to allow the end user to define a policy and validate the
|
||||
// request appropriately before calling this function.
|
||||
func ParseRequest(req *CertificateRequest) (csr, key []byte, err error) {
|
||||
log.Info("received CSR")
|
||||
if req.KeyRequest == nil {
|
||||
req.KeyRequest = NewBasicKeyRequest()
|
||||
}
|
||||
|
||||
log.Infof("generating key: %s-%d", req.KeyRequest.Algo(), req.KeyRequest.Size())
|
||||
priv, err := req.KeyRequest.Generate()
|
||||
if err != nil {
|
||||
err = cferr.Wrap(cferr.PrivateKeyError, cferr.GenerationFailed, err)
|
||||
return
|
||||
}
|
||||
|
||||
switch priv := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
key = x509.MarshalPKCS1PrivateKey(priv)
|
||||
block := pem.Block{
|
||||
Type: "RSA PRIVATE KEY",
|
||||
Bytes: key,
|
||||
}
|
||||
key = pem.EncodeToMemory(&block)
|
||||
case *ecdsa.PrivateKey:
|
||||
key, err = x509.MarshalECPrivateKey(priv)
|
||||
if err != nil {
|
||||
err = cferr.Wrap(cferr.PrivateKeyError, cferr.Unknown, err)
|
||||
return
|
||||
}
|
||||
block := pem.Block{
|
||||
Type: "EC PRIVATE KEY",
|
||||
Bytes: key,
|
||||
}
|
||||
key = pem.EncodeToMemory(&block)
|
||||
default:
|
||||
panic("Generate should have failed to produce a valid key.")
|
||||
}
|
||||
|
||||
csr, err = Generate(priv.(crypto.Signer), req)
|
||||
if err != nil {
|
||||
log.Errorf("failed to generate a CSR: %v", err)
|
||||
err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ExtractCertificateRequest extracts a CertificateRequest from
|
||||
// x509.Certificate. It is aimed to used for generating a new certificate
|
||||
// from an existing certificate. For a root certificate, the CA expiry
|
||||
// length is calculated as the duration between cert.NotAfter and cert.NotBefore.
|
||||
func ExtractCertificateRequest(cert *x509.Certificate) *CertificateRequest {
|
||||
req := New()
|
||||
req.CN = cert.Subject.CommonName
|
||||
req.Names = getNames(cert.Subject)
|
||||
req.Hosts = getHosts(cert)
|
||||
req.SerialNumber = cert.Subject.SerialNumber
|
||||
|
||||
if cert.IsCA {
|
||||
req.CA = new(CAConfig)
|
||||
// CA expiry length is calculated based on the input cert
|
||||
// issue date and expiry date.
|
||||
req.CA.Expiry = cert.NotAfter.Sub(cert.NotBefore).String()
|
||||
req.CA.PathLength = cert.MaxPathLen
|
||||
req.CA.PathLenZero = cert.MaxPathLenZero
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
func getHosts(cert *x509.Certificate) []string {
|
||||
var hosts []string
|
||||
for _, ip := range cert.IPAddresses {
|
||||
hosts = append(hosts, ip.String())
|
||||
}
|
||||
for _, dns := range cert.DNSNames {
|
||||
hosts = append(hosts, dns)
|
||||
}
|
||||
for _, email := range cert.EmailAddresses {
|
||||
hosts = append(hosts, email)
|
||||
}
|
||||
|
||||
return hosts
|
||||
}
|
||||
|
||||
// getNames returns an array of Names from the certificate
|
||||
// It onnly cares about Country, Organization, OrganizationalUnit, Locality, Province
|
||||
func getNames(sub pkix.Name) []Name {
|
||||
// anonymous func for finding the max of a list of interger
|
||||
max := func(v1 int, vn ...int) (max int) {
|
||||
max = v1
|
||||
for i := 0; i < len(vn); i++ {
|
||||
if vn[i] > max {
|
||||
max = vn[i]
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
nc := len(sub.Country)
|
||||
norg := len(sub.Organization)
|
||||
nou := len(sub.OrganizationalUnit)
|
||||
nl := len(sub.Locality)
|
||||
np := len(sub.Province)
|
||||
|
||||
n := max(nc, norg, nou, nl, np)
|
||||
|
||||
names := make([]Name, n)
|
||||
for i := range names {
|
||||
if i < nc {
|
||||
names[i].C = sub.Country[i]
|
||||
}
|
||||
if i < norg {
|
||||
names[i].O = sub.Organization[i]
|
||||
}
|
||||
if i < nou {
|
||||
names[i].OU = sub.OrganizationalUnit[i]
|
||||
}
|
||||
if i < nl {
|
||||
names[i].L = sub.Locality[i]
|
||||
}
|
||||
if i < np {
|
||||
names[i].ST = sub.Province[i]
|
||||
}
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// A Generator is responsible for validating certificate requests.
|
||||
type Generator struct {
|
||||
Validator func(*CertificateRequest) error
|
||||
}
|
||||
|
||||
// ProcessRequest validates and processes the incoming request. It is
|
||||
// a wrapper around a validator and the ParseRequest function.
|
||||
func (g *Generator) ProcessRequest(req *CertificateRequest) (csr, key []byte, err error) {
|
||||
|
||||
log.Info("generate received request")
|
||||
err = g.Validator(req)
|
||||
if err != nil {
|
||||
log.Warningf("invalid request: %v", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
csr, key, err = ParseRequest(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IsNameEmpty returns true if the name has no identifying information in it.
|
||||
func IsNameEmpty(n Name) bool {
|
||||
empty := func(s string) bool { return strings.TrimSpace(s) == "" }
|
||||
|
||||
if empty(n.C) && empty(n.ST) && empty(n.L) && empty(n.O) && empty(n.OU) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Regenerate uses the provided CSR as a template for signing a new
|
||||
// CSR using priv.
|
||||
func Regenerate(priv crypto.Signer, csr []byte) ([]byte, error) {
|
||||
req, extra, err := helpers.ParseCSR(csr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(extra) > 0 {
|
||||
return nil, errors.New("csr: trailing data in certificate request")
|
||||
}
|
||||
|
||||
return x509.CreateCertificateRequest(rand.Reader, req, priv)
|
||||
}
|
||||
|
||||
// Generate creates a new CSR from a CertificateRequest structure and
|
||||
// an existing key. The KeyRequest field is ignored.
|
||||
func Generate(priv crypto.Signer, req *CertificateRequest) (csr []byte, err error) {
|
||||
sigAlgo := helpers.SignerAlgo(priv)
|
||||
if sigAlgo == x509.UnknownSignatureAlgorithm {
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.Unavailable)
|
||||
}
|
||||
|
||||
var tpl = x509.CertificateRequest{
|
||||
Subject: req.Name(),
|
||||
SignatureAlgorithm: sigAlgo,
|
||||
}
|
||||
|
||||
for i := range req.Hosts {
|
||||
if ip := net.ParseIP(req.Hosts[i]); ip != nil {
|
||||
tpl.IPAddresses = append(tpl.IPAddresses, ip)
|
||||
} else if email, err := mail.ParseAddress(req.Hosts[i]); err == nil && email != nil {
|
||||
tpl.EmailAddresses = append(tpl.EmailAddresses, email.Address)
|
||||
} else {
|
||||
tpl.DNSNames = append(tpl.DNSNames, req.Hosts[i])
|
||||
}
|
||||
}
|
||||
|
||||
if req.CA != nil {
|
||||
err = appendCAInfoToCSR(req.CA, &tpl)
|
||||
if err != nil {
|
||||
err = cferr.Wrap(cferr.CSRError, cferr.GenerationFailed, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
csr, err = x509.CreateCertificateRequest(rand.Reader, &tpl, priv)
|
||||
if err != nil {
|
||||
log.Errorf("failed to generate a CSR: %v", err)
|
||||
err = cferr.Wrap(cferr.CSRError, cferr.BadRequest, err)
|
||||
return
|
||||
}
|
||||
block := pem.Block{
|
||||
Type: "CERTIFICATE REQUEST",
|
||||
Bytes: csr,
|
||||
}
|
||||
|
||||
log.Info("encoded CSR")
|
||||
csr = pem.EncodeToMemory(&block)
|
||||
return
|
||||
}
|
||||
|
||||
// appendCAInfoToCSR appends CAConfig BasicConstraint extension to a CSR
|
||||
func appendCAInfoToCSR(reqConf *CAConfig, csr *x509.CertificateRequest) error {
|
||||
pathlen := reqConf.PathLength
|
||||
if pathlen == 0 && !reqConf.PathLenZero {
|
||||
pathlen = -1
|
||||
}
|
||||
val, err := asn1.Marshal(BasicConstraints{true, pathlen})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
csr.ExtraExtensions = []pkix.Extension{
|
||||
{
|
||||
Id: asn1.ObjectIdentifier{2, 5, 29, 19},
|
||||
Value: val,
|
||||
Critical: true,
|
||||
},
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
744
vendor/github.com/cloudflare/cfssl/csr/csr_test.go
generated
vendored
Normal file
744
vendor/github.com/cloudflare/cfssl/csr/csr_test.go
generated
vendored
Normal file
@ -0,0 +1,744 @@
|
||||
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!")
|
||||
}
|
||||
}
|
15
vendor/github.com/cloudflare/cfssl/csr/testdata/test-ecdsa-ca.pem
generated
vendored
Normal file
15
vendor/github.com/cloudflare/cfssl/csr/testdata/test-ecdsa-ca.pem
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICUDCCAfagAwIBAgIIec5PjdpJcNYwCgYIKoZIzj0EAwIwejELMAkGA1UEBhMC
|
||||
VVMxGTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIzAhBgNVBAsTGlRlc3QgQ2Vy
|
||||
dGlmaWNhdGUgQXV0aG9yaXR5MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYD
|
||||
VQQIEwpDYWxpZm9ybmlhMB4XDTE1MTAwODIzMDEwMFoXDTE1MTAwODIzMDYwMFow
|
||||
ejELMAkGA1UEBhMCVVMxGTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIzAhBgNV
|
||||
BAsTGlRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMFkwEwYHKoZIzj0CAQYIKoZIzj0D
|
||||
AQcDQgAEoCV+bVOLTJMy38j50sc3vE5k41GMRgriFJt0g0OVX8yaOZ93CZTI7Lzf
|
||||
GbMU+KqWTgOwGhrPvpusep3fjw+dAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1Ud
|
||||
EwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFDpLhSKBN3njfb6cXQCdRLzCZt0ZMB8G
|
||||
A1UdIwQYMBaAFDpLhSKBN3njfb6cXQCdRLzCZt0ZMAoGCCqGSM49BAMCA0gAMEUC
|
||||
IFU3BmzntGGeXZu2qWZx249nYn37S0AkCnQ3rUtI31bdAiEAsPICnZ+GB8yCN26N
|
||||
OL+N8dHvXiOvZ9/Vl488pyWOccY=
|
||||
-----END CERTIFICATE-----
|
46
vendor/github.com/cloudflare/cfssl/errors/doc.go
generated
vendored
Normal file
46
vendor/github.com/cloudflare/cfssl/errors/doc.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
Package errors provides error types returned in CF SSL.
|
||||
|
||||
1. Type Error is intended for errors produced by CF SSL packages.
|
||||
It formats to a json object that consists of an error message and a 4-digit code for error reasoning.
|
||||
|
||||
Example: {"code":1002, "message": "Failed to decode certificate"}
|
||||
|
||||
The index of codes are listed below:
|
||||
1XXX: CertificateError
|
||||
1000: Unknown
|
||||
1001: ReadFailed
|
||||
1002: DecodeFailed
|
||||
1003: ParseFailed
|
||||
1100: SelfSigned
|
||||
12XX: VerifyFailed
|
||||
121X: CertificateInvalid
|
||||
1210: NotAuthorizedToSign
|
||||
1211: Expired
|
||||
1212: CANotAuthorizedForThisName
|
||||
1213: TooManyIntermediates
|
||||
1214: IncompatibleUsage
|
||||
1220: UnknownAuthority
|
||||
2XXX: PrivatekeyError
|
||||
2000: Unknown
|
||||
2001: ReadFailed
|
||||
2002: DecodeFailed
|
||||
2003: ParseFailed
|
||||
2100: Encrypted
|
||||
2200: NotRSA
|
||||
2300: KeyMismatch
|
||||
2400: GenerationFailed
|
||||
2500: Unavailable
|
||||
3XXX: IntermediatesError
|
||||
4XXX: RootError
|
||||
5XXX: PolicyError
|
||||
5100: NoKeyUsages
|
||||
5200: InvalidPolicy
|
||||
5300: InvalidRequest
|
||||
5400: UnknownProfile
|
||||
6XXX: DialError
|
||||
|
||||
2. Type HttpError is intended for CF SSL API to consume. It contains a HTTP status code that will be read and returned
|
||||
by the API server.
|
||||
*/
|
||||
package errors
|
438
vendor/github.com/cloudflare/cfssl/errors/error.go
generated
vendored
Normal file
438
vendor/github.com/cloudflare/cfssl/errors/error.go
generated
vendored
Normal file
@ -0,0 +1,438 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Error is the error type usually returned by functions in CF SSL package.
|
||||
// It contains a 4-digit error code where the most significant digit
|
||||
// describes the category where the error occurred and the rest 3 digits
|
||||
// describe the specific error reason.
|
||||
type Error struct {
|
||||
ErrorCode int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Category is the most significant digit of the error code.
|
||||
type Category int
|
||||
|
||||
// Reason is the last 3 digits of the error code.
|
||||
type Reason int
|
||||
|
||||
const (
|
||||
// Success indicates no error occurred.
|
||||
Success Category = 1000 * iota // 0XXX
|
||||
|
||||
// CertificateError indicates a fault in a certificate.
|
||||
CertificateError // 1XXX
|
||||
|
||||
// PrivateKeyError indicates a fault in a private key.
|
||||
PrivateKeyError // 2XXX
|
||||
|
||||
// IntermediatesError indicates a fault in an intermediate.
|
||||
IntermediatesError // 3XXX
|
||||
|
||||
// RootError indicates a fault in a root.
|
||||
RootError // 4XXX
|
||||
|
||||
// PolicyError indicates an error arising from a malformed or
|
||||
// non-existent policy, or a breach of policy.
|
||||
PolicyError // 5XXX
|
||||
|
||||
// DialError indicates a network fault.
|
||||
DialError // 6XXX
|
||||
|
||||
// APIClientError indicates a problem with the API client.
|
||||
APIClientError // 7XXX
|
||||
|
||||
// OCSPError indicates a problem with OCSP signing
|
||||
OCSPError // 8XXX
|
||||
|
||||
// CSRError indicates a problem with CSR parsing
|
||||
CSRError // 9XXX
|
||||
|
||||
// CTError indicates a problem with the certificate transparency process
|
||||
CTError // 10XXX
|
||||
|
||||
// CertStoreError indicates a problem with the certificate store
|
||||
CertStoreError // 11XXX
|
||||
)
|
||||
|
||||
// None is a non-specified error.
|
||||
const (
|
||||
None Reason = iota
|
||||
)
|
||||
|
||||
// Warning code for a success
|
||||
const (
|
||||
BundleExpiringBit int = 1 << iota // 0x01
|
||||
BundleNotUbiquitousBit // 0x02
|
||||
)
|
||||
|
||||
// Parsing errors
|
||||
const (
|
||||
Unknown Reason = iota // X000
|
||||
ReadFailed // X001
|
||||
DecodeFailed // X002
|
||||
ParseFailed // X003
|
||||
)
|
||||
|
||||
// The following represent certificate non-parsing errors, and must be
|
||||
// specified along with CertificateError.
|
||||
const (
|
||||
// SelfSigned indicates that a certificate is self-signed and
|
||||
// cannot be used in the manner being attempted.
|
||||
SelfSigned Reason = 100 * (iota + 1) // Code 11XX
|
||||
|
||||
// VerifyFailed is an X.509 verification failure. The least two
|
||||
// significant digits of 12XX is determined as the actual x509
|
||||
// error is examined.
|
||||
VerifyFailed // Code 12XX
|
||||
|
||||
// BadRequest indicates that the certificate request is invalid.
|
||||
BadRequest // Code 13XX
|
||||
|
||||
// MissingSerial indicates that the profile specified
|
||||
// 'ClientProvidesSerialNumbers', but the SignRequest did not include a serial
|
||||
// number.
|
||||
MissingSerial // Code 14XX
|
||||
)
|
||||
|
||||
const (
|
||||
certificateInvalid = 10 * (iota + 1) //121X
|
||||
unknownAuthority //122x
|
||||
)
|
||||
|
||||
// The following represent private-key non-parsing errors, and must be
|
||||
// specified with PrivateKeyError.
|
||||
const (
|
||||
// Encrypted indicates that the private key is a PKCS #8 encrypted
|
||||
// private key. At this time, CFSSL does not support decrypting
|
||||
// these keys.
|
||||
Encrypted Reason = 100 * (iota + 1) //21XX
|
||||
|
||||
// NotRSAOrECC indicates that they key is not an RSA or ECC
|
||||
// private key; these are the only two private key types supported
|
||||
// at this time by CFSSL.
|
||||
NotRSAOrECC //22XX
|
||||
|
||||
// KeyMismatch indicates that the private key does not match
|
||||
// the public key or certificate being presented with the key.
|
||||
KeyMismatch //23XX
|
||||
|
||||
// GenerationFailed indicates that a private key could not
|
||||
// be generated.
|
||||
GenerationFailed //24XX
|
||||
|
||||
// Unavailable indicates that a private key mechanism (such as
|
||||
// PKCS #11) was requested but support for that mechanism is
|
||||
// not available.
|
||||
Unavailable
|
||||
)
|
||||
|
||||
// The following are policy-related non-parsing errors, and must be
|
||||
// specified along with PolicyError.
|
||||
const (
|
||||
// NoKeyUsages indicates that the profile does not permit any
|
||||
// key usages for the certificate.
|
||||
NoKeyUsages Reason = 100 * (iota + 1) // 51XX
|
||||
|
||||
// InvalidPolicy indicates that policy being requested is not
|
||||
// a valid policy or does not exist.
|
||||
InvalidPolicy // 52XX
|
||||
|
||||
// InvalidRequest indicates a certificate request violated the
|
||||
// constraints of the policy being applied to the request.
|
||||
InvalidRequest // 53XX
|
||||
|
||||
// UnknownProfile indicates that the profile does not exist.
|
||||
UnknownProfile // 54XX
|
||||
|
||||
UnmatchedWhitelist // 55xx
|
||||
)
|
||||
|
||||
// The following are API client related errors, and should be
|
||||
// specified with APIClientError.
|
||||
const (
|
||||
// AuthenticationFailure occurs when the client is unable
|
||||
// to obtain an authentication token for the request.
|
||||
AuthenticationFailure Reason = 100 * (iota + 1)
|
||||
|
||||
// JSONError wraps an encoding/json error.
|
||||
JSONError
|
||||
|
||||
// IOError wraps an io/ioutil error.
|
||||
IOError
|
||||
|
||||
// ClientHTTPError wraps a net/http error.
|
||||
ClientHTTPError
|
||||
|
||||
// ServerRequestFailed covers any other failures from the API
|
||||
// client.
|
||||
ServerRequestFailed
|
||||
)
|
||||
|
||||
// The following are OCSP related errors, and should be
|
||||
// specified with OCSPError
|
||||
const (
|
||||
// IssuerMismatch ocurs when the certificate in the OCSP signing
|
||||
// request was not issued by the CA that this responder responds for.
|
||||
IssuerMismatch Reason = 100 * (iota + 1) // 81XX
|
||||
|
||||
// InvalidStatus occurs when the OCSP signing requests includes an
|
||||
// invalid value for the certificate status.
|
||||
InvalidStatus
|
||||
)
|
||||
|
||||
// Certificate transparency related errors specified with CTError
|
||||
const (
|
||||
// PrecertSubmissionFailed occurs when submitting a precertificate to
|
||||
// a log server fails
|
||||
PrecertSubmissionFailed = 100 * (iota + 1)
|
||||
// CTClientConstructionFailed occurs when the construction of a new
|
||||
// github.com/google/certificate-transparency client fails.
|
||||
CTClientConstructionFailed
|
||||
// PrecertMissingPoison occurs when a precert is passed to SignFromPrecert
|
||||
// and is missing the CT poison extension.
|
||||
PrecertMissingPoison
|
||||
// PrecertInvalidPoison occurs when a precert is passed to SignFromPrecert
|
||||
// and has a invalid CT poison extension value or the extension is not
|
||||
// critical.
|
||||
PrecertInvalidPoison
|
||||
)
|
||||
|
||||
// Certificate persistence related errors specified with CertStoreError
|
||||
const (
|
||||
// InsertionFailed occurs when a SQL insert query failes to complete.
|
||||
InsertionFailed = 100 * (iota + 1)
|
||||
// RecordNotFound occurs when a SQL query targeting on one unique
|
||||
// record failes to update the specified row in the table.
|
||||
RecordNotFound
|
||||
)
|
||||
|
||||
// The error interface implementation, which formats to a JSON object string.
|
||||
func (e *Error) Error() string {
|
||||
marshaled, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(marshaled)
|
||||
|
||||
}
|
||||
|
||||
// New returns an error that contains an error code and message derived from
|
||||
// the given category, reason. Currently, to avoid confusion, it is not
|
||||
// allowed to create an error of category Success
|
||||
func New(category Category, reason Reason) *Error {
|
||||
errorCode := int(category) + int(reason)
|
||||
var msg string
|
||||
switch category {
|
||||
case OCSPError:
|
||||
switch reason {
|
||||
case ReadFailed:
|
||||
msg = "No certificate provided"
|
||||
case IssuerMismatch:
|
||||
msg = "Certificate not issued by this issuer"
|
||||
case InvalidStatus:
|
||||
msg = "Invalid revocation status"
|
||||
}
|
||||
case CertificateError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "Unknown certificate error"
|
||||
case ReadFailed:
|
||||
msg = "Failed to read certificate"
|
||||
case DecodeFailed:
|
||||
msg = "Failed to decode certificate"
|
||||
case ParseFailed:
|
||||
msg = "Failed to parse certificate"
|
||||
case SelfSigned:
|
||||
msg = "Certificate is self signed"
|
||||
case VerifyFailed:
|
||||
msg = "Unable to verify certificate"
|
||||
case BadRequest:
|
||||
msg = "Invalid certificate request"
|
||||
case MissingSerial:
|
||||
msg = "Missing serial number in request"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category CertificateError.",
|
||||
reason))
|
||||
|
||||
}
|
||||
case PrivateKeyError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "Unknown private key error"
|
||||
case ReadFailed:
|
||||
msg = "Failed to read private key"
|
||||
case DecodeFailed:
|
||||
msg = "Failed to decode private key"
|
||||
case ParseFailed:
|
||||
msg = "Failed to parse private key"
|
||||
case Encrypted:
|
||||
msg = "Private key is encrypted."
|
||||
case NotRSAOrECC:
|
||||
msg = "Private key algorithm is not RSA or ECC"
|
||||
case KeyMismatch:
|
||||
msg = "Private key does not match public key"
|
||||
case GenerationFailed:
|
||||
msg = "Failed to new private key"
|
||||
case Unavailable:
|
||||
msg = "Private key is unavailable"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PrivateKeyError.",
|
||||
reason))
|
||||
}
|
||||
case IntermediatesError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "Unknown intermediate certificate error"
|
||||
case ReadFailed:
|
||||
msg = "Failed to read intermediate certificate"
|
||||
case DecodeFailed:
|
||||
msg = "Failed to decode intermediate certificate"
|
||||
case ParseFailed:
|
||||
msg = "Failed to parse intermediate certificate"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category IntermediatesError.",
|
||||
reason))
|
||||
}
|
||||
case RootError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "Unknown root certificate error"
|
||||
case ReadFailed:
|
||||
msg = "Failed to read root certificate"
|
||||
case DecodeFailed:
|
||||
msg = "Failed to decode root certificate"
|
||||
case ParseFailed:
|
||||
msg = "Failed to parse root certificate"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category RootError.",
|
||||
reason))
|
||||
}
|
||||
case PolicyError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "Unknown policy error"
|
||||
case NoKeyUsages:
|
||||
msg = "Invalid policy: no key usage available"
|
||||
case InvalidPolicy:
|
||||
msg = "Invalid or unknown policy"
|
||||
case InvalidRequest:
|
||||
msg = "Policy violation request"
|
||||
case UnknownProfile:
|
||||
msg = "Unknown policy profile"
|
||||
case UnmatchedWhitelist:
|
||||
msg = "Request does not match policy whitelist"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category PolicyError.",
|
||||
reason))
|
||||
}
|
||||
case DialError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "Failed to dial remote server"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category DialError.",
|
||||
reason))
|
||||
}
|
||||
case APIClientError:
|
||||
switch reason {
|
||||
case AuthenticationFailure:
|
||||
msg = "API client authentication failure"
|
||||
case JSONError:
|
||||
msg = "API client JSON config error"
|
||||
case ClientHTTPError:
|
||||
msg = "API client HTTP error"
|
||||
case IOError:
|
||||
msg = "API client IO error"
|
||||
case ServerRequestFailed:
|
||||
msg = "API client error: Server request failed"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error reason %d under category APIClientError.",
|
||||
reason))
|
||||
}
|
||||
case CSRError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "CSR parsing failed due to unknown error"
|
||||
case ReadFailed:
|
||||
msg = "CSR file read failed"
|
||||
case ParseFailed:
|
||||
msg = "CSR Parsing failed"
|
||||
case DecodeFailed:
|
||||
msg = "CSR Decode failed"
|
||||
case BadRequest:
|
||||
msg = "CSR Bad request"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category APIClientError.", reason))
|
||||
}
|
||||
case CTError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "Certificate transparency parsing failed due to unknown error"
|
||||
case PrecertSubmissionFailed:
|
||||
msg = "Certificate transparency precertificate submission failed"
|
||||
case PrecertMissingPoison:
|
||||
msg = "Precertificate is missing CT poison extension"
|
||||
case PrecertInvalidPoison:
|
||||
msg = "Precertificate contains an invalid CT poison extension"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CTError.", reason))
|
||||
}
|
||||
case CertStoreError:
|
||||
switch reason {
|
||||
case Unknown:
|
||||
msg = "Certificate store action failed due to unknown error"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CF-SSL error reason %d under category CertStoreError.", reason))
|
||||
}
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
|
||||
category))
|
||||
}
|
||||
return &Error{ErrorCode: errorCode, Message: msg}
|
||||
}
|
||||
|
||||
// Wrap returns an error that contains the given error and an error code derived from
|
||||
// the given category, reason and the error. Currently, to avoid confusion, it is not
|
||||
// allowed to create an error of category Success
|
||||
func Wrap(category Category, reason Reason, err error) *Error {
|
||||
errorCode := int(category) + int(reason)
|
||||
if err == nil {
|
||||
panic("Wrap needs a supplied error to initialize.")
|
||||
}
|
||||
|
||||
// do not double wrap a error
|
||||
switch err.(type) {
|
||||
case *Error:
|
||||
panic("Unable to wrap a wrapped error.")
|
||||
}
|
||||
|
||||
switch category {
|
||||
case CertificateError:
|
||||
// given VerifyFailed , report the status with more detailed status code
|
||||
// for some certificate errors we care.
|
||||
if reason == VerifyFailed {
|
||||
switch errorType := err.(type) {
|
||||
case x509.CertificateInvalidError:
|
||||
errorCode += certificateInvalid + int(errorType.Reason)
|
||||
case x509.UnknownAuthorityError:
|
||||
errorCode += unknownAuthority
|
||||
}
|
||||
}
|
||||
case PrivateKeyError, IntermediatesError, RootError, PolicyError, DialError,
|
||||
APIClientError, CSRError, CTError, CertStoreError, OCSPError:
|
||||
// no-op, just use the error
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported CFSSL error type: %d.",
|
||||
category))
|
||||
}
|
||||
|
||||
return &Error{ErrorCode: errorCode, Message: err.Error()}
|
||||
|
||||
}
|
338
vendor/github.com/cloudflare/cfssl/errors/error_test.go
generated
vendored
Normal file
338
vendor/github.com/cloudflare/cfssl/errors/error_test.go
generated
vendored
Normal file
@ -0,0 +1,338 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
err := New(CertificateError, Unknown)
|
||||
if err == nil {
|
||||
t.Fatal("Error creation failed.")
|
||||
}
|
||||
if err.ErrorCode != int(CertificateError)+int(Unknown) {
|
||||
t.Fatal("Error code construction failed.")
|
||||
}
|
||||
if err.Message != "Unknown certificate error" {
|
||||
t.Fatal("Error message construction failed.")
|
||||
}
|
||||
|
||||
code := New(OCSPError, ReadFailed).ErrorCode
|
||||
if code != 8001 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(OCSPError, IssuerMismatch).ErrorCode
|
||||
if code != 8100 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(OCSPError, InvalidStatus).ErrorCode
|
||||
if code != 8200 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(CertificateError, Unknown).ErrorCode
|
||||
if code != 1000 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CertificateError, ReadFailed).ErrorCode
|
||||
if code != 1001 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CertificateError, DecodeFailed).ErrorCode
|
||||
if code != 1002 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CertificateError, ParseFailed).ErrorCode
|
||||
if code != 1003 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CertificateError, SelfSigned).ErrorCode
|
||||
if code != 1100 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CertificateError, VerifyFailed).ErrorCode
|
||||
if code != 1200 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CertificateError, BadRequest).ErrorCode
|
||||
if code != 1300 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CertificateError, MissingSerial).ErrorCode
|
||||
if code != 1400 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(PrivateKeyError, Unknown).ErrorCode
|
||||
if code != 2000 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PrivateKeyError, ReadFailed).ErrorCode
|
||||
if code != 2001 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PrivateKeyError, DecodeFailed).ErrorCode
|
||||
if code != 2002 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PrivateKeyError, ParseFailed).ErrorCode
|
||||
if code != 2003 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PrivateKeyError, Encrypted).ErrorCode
|
||||
if code != 2100 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PrivateKeyError, NotRSAOrECC).ErrorCode
|
||||
if code != 2200 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PrivateKeyError, KeyMismatch).ErrorCode
|
||||
if code != 2300 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PrivateKeyError, GenerationFailed).ErrorCode
|
||||
if code != 2400 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PrivateKeyError, Unavailable).ErrorCode
|
||||
if code != 2500 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(IntermediatesError, Unknown).ErrorCode
|
||||
if code != 3000 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(IntermediatesError, ReadFailed).ErrorCode
|
||||
if code != 3001 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(IntermediatesError, DecodeFailed).ErrorCode
|
||||
if code != 3002 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(IntermediatesError, ParseFailed).ErrorCode
|
||||
if code != 3003 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(RootError, Unknown).ErrorCode
|
||||
if code != 4000 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(RootError, ReadFailed).ErrorCode
|
||||
if code != 4001 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(RootError, DecodeFailed).ErrorCode
|
||||
if code != 4002 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(RootError, ParseFailed).ErrorCode
|
||||
if code != 4003 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(PolicyError, Unknown).ErrorCode
|
||||
if code != 5000 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PolicyError, NoKeyUsages).ErrorCode
|
||||
if code != 5100 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PolicyError, InvalidPolicy).ErrorCode
|
||||
if code != 5200 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PolicyError, InvalidRequest).ErrorCode
|
||||
if code != 5300 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(PolicyError, UnknownProfile).ErrorCode
|
||||
if code != 5400 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(DialError, Unknown).ErrorCode
|
||||
if code != 6000 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(APIClientError, AuthenticationFailure).ErrorCode
|
||||
if code != 7100 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(APIClientError, JSONError).ErrorCode
|
||||
if code != 7200 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(APIClientError, ClientHTTPError).ErrorCode
|
||||
if code != 7400 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(APIClientError, IOError).ErrorCode
|
||||
if code != 7300 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(APIClientError, ServerRequestFailed).ErrorCode
|
||||
if code != 7500 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(CSRError, Unknown).ErrorCode
|
||||
if code != 9000 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CSRError, ReadFailed).ErrorCode
|
||||
if code != 9001 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CSRError, DecodeFailed).ErrorCode
|
||||
if code != 9002 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CSRError, ParseFailed).ErrorCode
|
||||
if code != 9003 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CSRError, KeyMismatch).ErrorCode
|
||||
if code != 9300 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CSRError, BadRequest).ErrorCode
|
||||
if code != 9300 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
|
||||
code = New(CTError, Unknown).ErrorCode
|
||||
if code != 10000 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
code = New(CTError, PrecertSubmissionFailed).ErrorCode
|
||||
if code != 10100 {
|
||||
t.Fatal("Improper error code")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrap(t *testing.T) {
|
||||
msg := "Arbitrary error message"
|
||||
err := Wrap(CertificateError, Unknown, errors.New(msg))
|
||||
if err == nil {
|
||||
t.Fatal("Error creation failed.")
|
||||
}
|
||||
if err.ErrorCode != int(CertificateError)+int(Unknown) {
|
||||
t.Fatal("Error code construction failed.")
|
||||
}
|
||||
if err.Message != msg {
|
||||
t.Fatal("Error message construction failed.")
|
||||
}
|
||||
|
||||
err = Wrap(CertificateError, VerifyFailed, x509.CertificateInvalidError{Reason: x509.Expired})
|
||||
if err == nil {
|
||||
t.Fatal("Error creation failed.")
|
||||
}
|
||||
if err.ErrorCode != int(CertificateError)+int(VerifyFailed)+certificateInvalid+int(x509.Expired) {
|
||||
t.Fatal("Error code construction failed.")
|
||||
}
|
||||
if err.Message != "x509: certificate has expired or is not yet valid" {
|
||||
t.Fatal("Error message construction failed.")
|
||||
}
|
||||
|
||||
err = Wrap(CertificateError, VerifyFailed, x509.UnknownAuthorityError{})
|
||||
if err == nil {
|
||||
t.Fatal("Error creation failed.")
|
||||
}
|
||||
|
||||
err = Wrap(RootError, Unknown, errors.New(msg))
|
||||
if err == nil {
|
||||
t.Fatal("Error creation failed.")
|
||||
}
|
||||
if err.ErrorCode != int(RootError)+int(Unknown) {
|
||||
t.Fatal("Error code construction failed.")
|
||||
}
|
||||
if err.Message != msg {
|
||||
t.Fatal("Error message construction failed.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshal(t *testing.T) {
|
||||
msg := "Arbitrary error message"
|
||||
err := Wrap(CertificateError, Unknown, errors.New(msg))
|
||||
bytes, _ := json.Marshal(err)
|
||||
var received Error
|
||||
json.Unmarshal(bytes, &received)
|
||||
if received.ErrorCode != int(CertificateError)+int(Unknown) {
|
||||
t.Fatal("Error code construction failed.")
|
||||
}
|
||||
if received.Message != msg {
|
||||
t.Fatal("Error message construction failed.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorString(t *testing.T) {
|
||||
msg := "Arbitrary error message"
|
||||
err := Wrap(CertificateError, Unknown, errors.New(msg))
|
||||
str := err.Error()
|
||||
if str != `{"code":1000,"message":"`+msg+`"}` {
|
||||
t.Fatal("Incorrect Error():", str)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTP(t *testing.T) {
|
||||
err := NewMethodNotAllowed("GET")
|
||||
if err == nil {
|
||||
t.Fatal("New Mathod Check failed")
|
||||
}
|
||||
|
||||
err = NewBadRequest(errors.New("Bad Request"))
|
||||
if err == nil {
|
||||
t.Fatal("New Bad Request Check failed")
|
||||
}
|
||||
|
||||
if err.StatusCode != 400 {
|
||||
t.Fatal("New Bad Request error code construction failed")
|
||||
}
|
||||
|
||||
err = NewBadRequestString("Bad Request String")
|
||||
if err == nil {
|
||||
t.Fatal("New Bad Request String Check failed")
|
||||
}
|
||||
|
||||
if err.StatusCode != 400 {
|
||||
t.Fatal("New Bad Request String error code construction failed")
|
||||
}
|
||||
|
||||
err = NewBadRequestMissingParameter("Request Missing Parameter")
|
||||
if err == nil {
|
||||
t.Fatal("New Bad Request Missing Parameter Check failed")
|
||||
}
|
||||
|
||||
if err.StatusCode != 400 {
|
||||
t.Fatal("New Bad Request Missing Parameter error code construction failed")
|
||||
}
|
||||
|
||||
err = NewBadRequestUnwantedParameter("Unwanted Parameter Present In Request")
|
||||
if err == nil {
|
||||
t.Fatal("New Bad Request Unwanted Parameter Check failed")
|
||||
}
|
||||
|
||||
if err.StatusCode != 400 {
|
||||
t.Fatal("New Bad Request Unwanted Parameter error code construction failed")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestHTTPErrorString(t *testing.T) {
|
||||
method := "GET"
|
||||
err := NewMethodNotAllowed(method)
|
||||
str := err.Error()
|
||||
if str != `Method is not allowed:"`+method+`"` {
|
||||
t.Fatal("Incorrect Error():", str)
|
||||
}
|
||||
}
|
47
vendor/github.com/cloudflare/cfssl/errors/http.go
generated
vendored
Normal file
47
vendor/github.com/cloudflare/cfssl/errors/http.go
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// HTTPError is an augmented error with a HTTP status code.
|
||||
type HTTPError struct {
|
||||
StatusCode int
|
||||
error
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (e *HTTPError) Error() string {
|
||||
return e.error.Error()
|
||||
}
|
||||
|
||||
// NewMethodNotAllowed returns an appropriate error in the case that
|
||||
// an HTTP client uses an invalid method (i.e. a GET in place of a POST)
|
||||
// on an API endpoint.
|
||||
func NewMethodNotAllowed(method string) *HTTPError {
|
||||
return &HTTPError{http.StatusMethodNotAllowed, errors.New(`Method is not allowed:"` + method + `"`)}
|
||||
}
|
||||
|
||||
// NewBadRequest creates a HttpError with the given error and error code 400.
|
||||
func NewBadRequest(err error) *HTTPError {
|
||||
return &HTTPError{http.StatusBadRequest, err}
|
||||
}
|
||||
|
||||
// NewBadRequestString returns a HttpError with the supplied message
|
||||
// and error code 400.
|
||||
func NewBadRequestString(s string) *HTTPError {
|
||||
return NewBadRequest(errors.New(s))
|
||||
}
|
||||
|
||||
// NewBadRequestMissingParameter returns a 400 HttpError as a required
|
||||
// parameter is missing in the HTTP request.
|
||||
func NewBadRequestMissingParameter(s string) *HTTPError {
|
||||
return NewBadRequestString(`Missing parameter "` + s + `"`)
|
||||
}
|
||||
|
||||
// NewBadRequestUnwantedParameter returns a 400 HttpError as a unnecessary
|
||||
// parameter is present in the HTTP request.
|
||||
func NewBadRequestUnwantedParameter(s string) *HTTPError {
|
||||
return NewBadRequestString(`Unwanted parameter "` + s + `"`)
|
||||
}
|
42
vendor/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go
generated
vendored
Normal file
42
vendor/github.com/cloudflare/cfssl/helpers/derhelpers/derhelpers.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
// Package derhelpers implements common functionality
|
||||
// on DER encoded data
|
||||
package derhelpers
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
)
|
||||
|
||||
// ParsePrivateKeyDER parses a PKCS #1, PKCS #8, or elliptic curve
|
||||
// DER-encoded private key. The key must not be in PEM format.
|
||||
func ParsePrivateKeyDER(keyDER []byte) (key crypto.Signer, err error) {
|
||||
generalKey, err := x509.ParsePKCS8PrivateKey(keyDER)
|
||||
if err != nil {
|
||||
generalKey, err = x509.ParsePKCS1PrivateKey(keyDER)
|
||||
if err != nil {
|
||||
generalKey, err = x509.ParseECPrivateKey(keyDER)
|
||||
if err != nil {
|
||||
// We don't include the actual error into
|
||||
// the final error. The reason might be
|
||||
// we don't want to leak any info about
|
||||
// the private key.
|
||||
return nil, cferr.New(cferr.PrivateKeyError,
|
||||
cferr.ParseFailed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch generalKey.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return generalKey.(*rsa.PrivateKey), nil
|
||||
case *ecdsa.PrivateKey:
|
||||
return generalKey.(*ecdsa.PrivateKey), nil
|
||||
}
|
||||
|
||||
// should never reach here
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.ParseFailed)
|
||||
}
|
577
vendor/github.com/cloudflare/cfssl/helpers/helpers.go
generated
vendored
Normal file
577
vendor/github.com/cloudflare/cfssl/helpers/helpers.go
generated
vendored
Normal file
@ -0,0 +1,577 @@
|
||||
// Package helpers implements utility functionality common to many
|
||||
// CFSSL packages.
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/google/certificate-transparency-go"
|
||||
cttls "github.com/google/certificate-transparency-go/tls"
|
||||
ctx509 "github.com/google/certificate-transparency-go/x509"
|
||||
"golang.org/x/crypto/ocsp"
|
||||
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cfssl/crypto/pkcs7"
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
"github.com/cloudflare/cfssl/helpers/derhelpers"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
"golang.org/x/crypto/pkcs12"
|
||||
)
|
||||
|
||||
// OneYear is a time.Duration representing a year's worth of seconds.
|
||||
const OneYear = 8760 * time.Hour
|
||||
|
||||
// OneDay is a time.Duration representing a day's worth of seconds.
|
||||
const OneDay = 24 * time.Hour
|
||||
|
||||
// InclusiveDate returns the time.Time representation of a date - 1
|
||||
// nanosecond. This allows time.After to be used inclusively.
|
||||
func InclusiveDate(year int, month time.Month, day int) time.Time {
|
||||
return time.Date(year, month, day, 0, 0, 0, 0, time.UTC).Add(-1 * time.Nanosecond)
|
||||
}
|
||||
|
||||
// Jul2012 is the July 2012 CAB Forum deadline for when CAs must stop
|
||||
// issuing certificates valid for more than 5 years.
|
||||
var Jul2012 = InclusiveDate(2012, time.July, 01)
|
||||
|
||||
// Apr2015 is the April 2015 CAB Forum deadline for when CAs must stop
|
||||
// issuing certificates valid for more than 39 months.
|
||||
var Apr2015 = InclusiveDate(2015, time.April, 01)
|
||||
|
||||
// KeyLength returns the bit size of ECDSA or RSA PublicKey
|
||||
func KeyLength(key interface{}) int {
|
||||
if key == nil {
|
||||
return 0
|
||||
}
|
||||
if ecdsaKey, ok := key.(*ecdsa.PublicKey); ok {
|
||||
return ecdsaKey.Curve.Params().BitSize
|
||||
} else if rsaKey, ok := key.(*rsa.PublicKey); ok {
|
||||
return rsaKey.N.BitLen()
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// ExpiryTime returns the time when the certificate chain is expired.
|
||||
func ExpiryTime(chain []*x509.Certificate) (notAfter time.Time) {
|
||||
if len(chain) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
notAfter = chain[0].NotAfter
|
||||
for _, cert := range chain {
|
||||
if notAfter.After(cert.NotAfter) {
|
||||
notAfter = cert.NotAfter
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MonthsValid returns the number of months for which a certificate is valid.
|
||||
func MonthsValid(c *x509.Certificate) int {
|
||||
issued := c.NotBefore
|
||||
expiry := c.NotAfter
|
||||
years := (expiry.Year() - issued.Year())
|
||||
months := years*12 + int(expiry.Month()) - int(issued.Month())
|
||||
|
||||
// Round up if valid for less than a full month
|
||||
if expiry.Day() > issued.Day() {
|
||||
months++
|
||||
}
|
||||
return months
|
||||
}
|
||||
|
||||
// ValidExpiry determines if a certificate is valid for an acceptable
|
||||
// length of time per the CA/Browser Forum baseline requirements.
|
||||
// See https://cabforum.org/wp-content/uploads/CAB-Forum-BR-1.3.0.pdf
|
||||
func ValidExpiry(c *x509.Certificate) bool {
|
||||
issued := c.NotBefore
|
||||
|
||||
var maxMonths int
|
||||
switch {
|
||||
case issued.After(Apr2015):
|
||||
maxMonths = 39
|
||||
case issued.After(Jul2012):
|
||||
maxMonths = 60
|
||||
case issued.Before(Jul2012):
|
||||
maxMonths = 120
|
||||
}
|
||||
|
||||
if MonthsValid(c) > maxMonths {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// SignatureString returns the TLS signature string corresponding to
|
||||
// an X509 signature algorithm.
|
||||
func SignatureString(alg x509.SignatureAlgorithm) string {
|
||||
switch alg {
|
||||
case x509.MD2WithRSA:
|
||||
return "MD2WithRSA"
|
||||
case x509.MD5WithRSA:
|
||||
return "MD5WithRSA"
|
||||
case x509.SHA1WithRSA:
|
||||
return "SHA1WithRSA"
|
||||
case x509.SHA256WithRSA:
|
||||
return "SHA256WithRSA"
|
||||
case x509.SHA384WithRSA:
|
||||
return "SHA384WithRSA"
|
||||
case x509.SHA512WithRSA:
|
||||
return "SHA512WithRSA"
|
||||
case x509.DSAWithSHA1:
|
||||
return "DSAWithSHA1"
|
||||
case x509.DSAWithSHA256:
|
||||
return "DSAWithSHA256"
|
||||
case x509.ECDSAWithSHA1:
|
||||
return "ECDSAWithSHA1"
|
||||
case x509.ECDSAWithSHA256:
|
||||
return "ECDSAWithSHA256"
|
||||
case x509.ECDSAWithSHA384:
|
||||
return "ECDSAWithSHA384"
|
||||
case x509.ECDSAWithSHA512:
|
||||
return "ECDSAWithSHA512"
|
||||
default:
|
||||
return "Unknown Signature"
|
||||
}
|
||||
}
|
||||
|
||||
// HashAlgoString returns the hash algorithm name contains in the signature
|
||||
// method.
|
||||
func HashAlgoString(alg x509.SignatureAlgorithm) string {
|
||||
switch alg {
|
||||
case x509.MD2WithRSA:
|
||||
return "MD2"
|
||||
case x509.MD5WithRSA:
|
||||
return "MD5"
|
||||
case x509.SHA1WithRSA:
|
||||
return "SHA1"
|
||||
case x509.SHA256WithRSA:
|
||||
return "SHA256"
|
||||
case x509.SHA384WithRSA:
|
||||
return "SHA384"
|
||||
case x509.SHA512WithRSA:
|
||||
return "SHA512"
|
||||
case x509.DSAWithSHA1:
|
||||
return "SHA1"
|
||||
case x509.DSAWithSHA256:
|
||||
return "SHA256"
|
||||
case x509.ECDSAWithSHA1:
|
||||
return "SHA1"
|
||||
case x509.ECDSAWithSHA256:
|
||||
return "SHA256"
|
||||
case x509.ECDSAWithSHA384:
|
||||
return "SHA384"
|
||||
case x509.ECDSAWithSHA512:
|
||||
return "SHA512"
|
||||
default:
|
||||
return "Unknown Hash Algorithm"
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeCertificatesPEM encodes a number of x509 certificates to PEM
|
||||
func EncodeCertificatesPEM(certs []*x509.Certificate) []byte {
|
||||
var buffer bytes.Buffer
|
||||
for _, cert := range certs {
|
||||
pem.Encode(&buffer, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
})
|
||||
}
|
||||
|
||||
return buffer.Bytes()
|
||||
}
|
||||
|
||||
// EncodeCertificatePEM encodes a single x509 certificates to PEM
|
||||
func EncodeCertificatePEM(cert *x509.Certificate) []byte {
|
||||
return EncodeCertificatesPEM([]*x509.Certificate{cert})
|
||||
}
|
||||
|
||||
// ParseCertificatesPEM parses a sequence of PEM-encoded certificate and returns them,
|
||||
// can handle PEM encoded PKCS #7 structures.
|
||||
func ParseCertificatesPEM(certsPEM []byte) ([]*x509.Certificate, error) {
|
||||
var certs []*x509.Certificate
|
||||
var err error
|
||||
certsPEM = bytes.TrimSpace(certsPEM)
|
||||
for len(certsPEM) > 0 {
|
||||
var cert []*x509.Certificate
|
||||
cert, certsPEM, err = ParseOneCertificateFromPEM(certsPEM)
|
||||
if err != nil {
|
||||
|
||||
return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed)
|
||||
} else if cert == nil {
|
||||
break
|
||||
}
|
||||
|
||||
certs = append(certs, cert...)
|
||||
}
|
||||
if len(certsPEM) > 0 {
|
||||
return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
// ParseCertificatesDER parses a DER encoding of a certificate object and possibly private key,
|
||||
// either PKCS #7, PKCS #12, or raw x509.
|
||||
func ParseCertificatesDER(certsDER []byte, password string) (certs []*x509.Certificate, key crypto.Signer, err error) {
|
||||
certsDER = bytes.TrimSpace(certsDER)
|
||||
pkcs7data, err := pkcs7.ParsePKCS7(certsDER)
|
||||
if err != nil {
|
||||
var pkcs12data interface{}
|
||||
certs = make([]*x509.Certificate, 1)
|
||||
pkcs12data, certs[0], err = pkcs12.Decode(certsDER, password)
|
||||
if err != nil {
|
||||
certs, err = x509.ParseCertificates(certsDER)
|
||||
if err != nil {
|
||||
return nil, nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
|
||||
}
|
||||
} else {
|
||||
key = pkcs12data.(crypto.Signer)
|
||||
}
|
||||
} else {
|
||||
if pkcs7data.ContentInfo != "SignedData" {
|
||||
return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.DecodeFailed, errors.New("can only extract certificates from signed data content info"))
|
||||
}
|
||||
certs = pkcs7data.Content.SignedData.Certificates
|
||||
}
|
||||
if certs == nil {
|
||||
return nil, key, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
|
||||
}
|
||||
return certs, key, nil
|
||||
}
|
||||
|
||||
// ParseSelfSignedCertificatePEM parses a PEM-encoded certificate and check if it is self-signed.
|
||||
func ParseSelfSignedCertificatePEM(certPEM []byte) (*x509.Certificate, error) {
|
||||
cert, err := ParseCertificatePEM(certPEM)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.VerifyFailed, err)
|
||||
}
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
// ParseCertificatePEM parses and returns a PEM-encoded certificate,
|
||||
// can handle PEM encoded PKCS #7 structures.
|
||||
func ParseCertificatePEM(certPEM []byte) (*x509.Certificate, error) {
|
||||
certPEM = bytes.TrimSpace(certPEM)
|
||||
cert, rest, err := ParseOneCertificateFromPEM(certPEM)
|
||||
if err != nil {
|
||||
// Log the actual parsing error but throw a default parse error message.
|
||||
log.Debugf("Certificate parsing error: %v", err)
|
||||
return nil, cferr.New(cferr.CertificateError, cferr.ParseFailed)
|
||||
} else if cert == nil {
|
||||
return nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
|
||||
} else if len(rest) > 0 {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("the PEM file should contain only one object"))
|
||||
} else if len(cert) > 1 {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("the PKCS7 object in the PEM file should contain only one certificate"))
|
||||
}
|
||||
return cert[0], nil
|
||||
}
|
||||
|
||||
// ParseOneCertificateFromPEM attempts to parse one PEM encoded certificate object,
|
||||
// either a raw x509 certificate or a PKCS #7 structure possibly containing
|
||||
// multiple certificates, from the top of certsPEM, which itself may
|
||||
// contain multiple PEM encoded certificate objects.
|
||||
func ParseOneCertificateFromPEM(certsPEM []byte) ([]*x509.Certificate, []byte, error) {
|
||||
|
||||
block, rest := pem.Decode(certsPEM)
|
||||
if block == nil {
|
||||
return nil, rest, nil
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
pkcs7data, err := pkcs7.ParsePKCS7(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, rest, err
|
||||
}
|
||||
if pkcs7data.ContentInfo != "SignedData" {
|
||||
return nil, rest, errors.New("only PKCS #7 Signed Data Content Info supported for certificate parsing")
|
||||
}
|
||||
certs := pkcs7data.Content.SignedData.Certificates
|
||||
if certs == nil {
|
||||
return nil, rest, errors.New("PKCS #7 structure contains no certificates")
|
||||
}
|
||||
return certs, rest, nil
|
||||
}
|
||||
var certs = []*x509.Certificate{cert}
|
||||
return certs, rest, nil
|
||||
}
|
||||
|
||||
// LoadPEMCertPool loads a pool of PEM certificates from file.
|
||||
func LoadPEMCertPool(certsFile string) (*x509.CertPool, error) {
|
||||
if certsFile == "" {
|
||||
return nil, nil
|
||||
}
|
||||
pemCerts, err := ioutil.ReadFile(certsFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return PEMToCertPool(pemCerts)
|
||||
}
|
||||
|
||||
// PEMToCertPool concerts PEM certificates to a CertPool.
|
||||
func PEMToCertPool(pemCerts []byte) (*x509.CertPool, error) {
|
||||
if len(pemCerts) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
certPool := x509.NewCertPool()
|
||||
if !certPool.AppendCertsFromPEM(pemCerts) {
|
||||
return nil, errors.New("failed to load cert pool")
|
||||
}
|
||||
|
||||
return certPool, nil
|
||||
}
|
||||
|
||||
// ParsePrivateKeyPEM parses and returns a PEM-encoded private
|
||||
// key. The private key may be either an unencrypted PKCS#8, PKCS#1,
|
||||
// or elliptic private key.
|
||||
func ParsePrivateKeyPEM(keyPEM []byte) (key crypto.Signer, err error) {
|
||||
return ParsePrivateKeyPEMWithPassword(keyPEM, nil)
|
||||
}
|
||||
|
||||
// ParsePrivateKeyPEMWithPassword parses and returns a PEM-encoded private
|
||||
// key. The private key may be a potentially encrypted PKCS#8, PKCS#1,
|
||||
// or elliptic private key.
|
||||
func ParsePrivateKeyPEMWithPassword(keyPEM []byte, password []byte) (key crypto.Signer, err error) {
|
||||
keyDER, err := GetKeyDERFromPEM(keyPEM, password)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return derhelpers.ParsePrivateKeyDER(keyDER)
|
||||
}
|
||||
|
||||
// GetKeyDERFromPEM parses a PEM-encoded private key and returns DER-format key bytes.
|
||||
func GetKeyDERFromPEM(in []byte, password []byte) ([]byte, error) {
|
||||
keyDER, _ := pem.Decode(in)
|
||||
if keyDER != nil {
|
||||
if procType, ok := keyDER.Headers["Proc-Type"]; ok {
|
||||
if strings.Contains(procType, "ENCRYPTED") {
|
||||
if password != nil {
|
||||
return x509.DecryptPEMBlock(keyDER, password)
|
||||
}
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.Encrypted)
|
||||
}
|
||||
}
|
||||
return keyDER.Bytes, nil
|
||||
}
|
||||
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.DecodeFailed)
|
||||
}
|
||||
|
||||
// ParseCSR parses a PEM- or DER-encoded PKCS #10 certificate signing request.
|
||||
func ParseCSR(in []byte) (csr *x509.CertificateRequest, rest []byte, err error) {
|
||||
in = bytes.TrimSpace(in)
|
||||
p, rest := pem.Decode(in)
|
||||
if p != nil {
|
||||
if p.Type != "NEW CERTIFICATE REQUEST" && p.Type != "CERTIFICATE REQUEST" {
|
||||
return nil, rest, cferr.New(cferr.CSRError, cferr.BadRequest)
|
||||
}
|
||||
|
||||
csr, err = x509.ParseCertificateRequest(p.Bytes)
|
||||
} else {
|
||||
csr, err = x509.ParseCertificateRequest(in)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, rest, err
|
||||
}
|
||||
|
||||
err = csr.CheckSignature()
|
||||
if err != nil {
|
||||
return nil, rest, err
|
||||
}
|
||||
|
||||
return csr, rest, nil
|
||||
}
|
||||
|
||||
// ParseCSRPEM parses a PEM-encoded certificate signing request.
|
||||
// It does not check the signature. This is useful for dumping data from a CSR
|
||||
// locally.
|
||||
func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
|
||||
block, _ := pem.Decode([]byte(csrPEM))
|
||||
if block == nil {
|
||||
return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed)
|
||||
}
|
||||
csrObject, err := x509.ParseCertificateRequest(block.Bytes)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return csrObject, nil
|
||||
}
|
||||
|
||||
// SignerAlgo returns an X.509 signature algorithm from a crypto.Signer.
|
||||
func SignerAlgo(priv crypto.Signer) x509.SignatureAlgorithm {
|
||||
switch pub := priv.Public().(type) {
|
||||
case *rsa.PublicKey:
|
||||
bitLength := pub.N.BitLen()
|
||||
switch {
|
||||
case bitLength >= 4096:
|
||||
return x509.SHA512WithRSA
|
||||
case bitLength >= 3072:
|
||||
return x509.SHA384WithRSA
|
||||
case bitLength >= 2048:
|
||||
return x509.SHA256WithRSA
|
||||
default:
|
||||
return x509.SHA1WithRSA
|
||||
}
|
||||
case *ecdsa.PublicKey:
|
||||
switch pub.Curve {
|
||||
case elliptic.P521():
|
||||
return x509.ECDSAWithSHA512
|
||||
case elliptic.P384():
|
||||
return x509.ECDSAWithSHA384
|
||||
case elliptic.P256():
|
||||
return x509.ECDSAWithSHA256
|
||||
default:
|
||||
return x509.ECDSAWithSHA1
|
||||
}
|
||||
default:
|
||||
return x509.UnknownSignatureAlgorithm
|
||||
}
|
||||
}
|
||||
|
||||
// LoadClientCertificate load key/certificate from pem files
|
||||
func LoadClientCertificate(certFile string, keyFile string) (*tls.Certificate, error) {
|
||||
if certFile != "" && keyFile != "" {
|
||||
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
|
||||
if err != nil {
|
||||
log.Critical("Unable to read client certificate from file: %s or key from file: %s", certFile, keyFile)
|
||||
return nil, err
|
||||
}
|
||||
log.Debug("Client certificate loaded ")
|
||||
return &cert, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// CreateTLSConfig creates a tls.Config object from certs and roots
|
||||
func CreateTLSConfig(remoteCAs *x509.CertPool, cert *tls.Certificate) *tls.Config {
|
||||
var certs []tls.Certificate
|
||||
if cert != nil {
|
||||
certs = []tls.Certificate{*cert}
|
||||
}
|
||||
return &tls.Config{
|
||||
Certificates: certs,
|
||||
RootCAs: remoteCAs,
|
||||
}
|
||||
}
|
||||
|
||||
// SerializeSCTList serializes a list of SCTs.
|
||||
func SerializeSCTList(sctList []ct.SignedCertificateTimestamp) ([]byte, error) {
|
||||
list := ctx509.SignedCertificateTimestampList{}
|
||||
for _, sct := range sctList {
|
||||
sctBytes, err := cttls.Marshal(sct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
list.SCTList = append(list.SCTList, ctx509.SerializedSCT{Val: sctBytes})
|
||||
}
|
||||
return cttls.Marshal(list)
|
||||
}
|
||||
|
||||
// DeserializeSCTList deserializes a list of SCTs.
|
||||
func DeserializeSCTList(serializedSCTList []byte) ([]ct.SignedCertificateTimestamp, error) {
|
||||
var sctList ctx509.SignedCertificateTimestampList
|
||||
rest, err := cttls.Unmarshal(serializedSCTList, &sctList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rest) != 0 {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, errors.New("serialized SCT list contained trailing garbage"))
|
||||
}
|
||||
list := make([]ct.SignedCertificateTimestamp, len(sctList.SCTList))
|
||||
for i, serializedSCT := range sctList.SCTList {
|
||||
var sct ct.SignedCertificateTimestamp
|
||||
rest, err := cttls.Unmarshal(serializedSCT.Val, &sct)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rest) != 0 {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, errors.New("serialized SCT contained trailing garbage"))
|
||||
}
|
||||
list[i] = sct
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// SCTListFromOCSPResponse extracts the SCTList from an ocsp.Response,
|
||||
// returning an empty list if the SCT extension was not found or could not be
|
||||
// unmarshalled.
|
||||
func SCTListFromOCSPResponse(response *ocsp.Response) ([]ct.SignedCertificateTimestamp, error) {
|
||||
// This loop finds the SCTListExtension in the OCSP response.
|
||||
var SCTListExtension, ext pkix.Extension
|
||||
for _, ext = range response.Extensions {
|
||||
// sctExtOid is the ObjectIdentifier of a Signed Certificate Timestamp.
|
||||
sctExtOid := asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 5}
|
||||
if ext.Id.Equal(sctExtOid) {
|
||||
SCTListExtension = ext
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// This code block extracts the sctList from the SCT extension.
|
||||
var sctList []ct.SignedCertificateTimestamp
|
||||
var err error
|
||||
if numBytes := len(SCTListExtension.Value); numBytes != 0 {
|
||||
var serializedSCTList []byte
|
||||
rest := make([]byte, numBytes)
|
||||
copy(rest, SCTListExtension.Value)
|
||||
for len(rest) != 0 {
|
||||
rest, err = asn1.Unmarshal(rest, &serializedSCTList)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
}
|
||||
sctList, err = DeserializeSCTList(serializedSCTList)
|
||||
}
|
||||
return sctList, err
|
||||
}
|
||||
|
||||
// ReadBytes reads a []byte either from a file or an environment variable.
|
||||
// If valFile has a prefix of 'env:', the []byte is read from the environment
|
||||
// using the subsequent name. If the prefix is 'file:' the []byte is read from
|
||||
// the subsequent file. If no prefix is provided, valFile is assumed to be a
|
||||
// file path.
|
||||
func ReadBytes(valFile string) ([]byte, error) {
|
||||
switch splitVal := strings.SplitN(valFile, ":", 2); len(splitVal) {
|
||||
case 1:
|
||||
return ioutil.ReadFile(valFile)
|
||||
case 2:
|
||||
switch splitVal[0] {
|
||||
case "env":
|
||||
return []byte(os.Getenv(splitVal[1])), nil
|
||||
case "file":
|
||||
return ioutil.ReadFile(splitVal[1])
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown prefix: %s", splitVal[0])
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("multiple prefixes: %s",
|
||||
strings.Join(splitVal[:len(splitVal)-1], ", "))
|
||||
}
|
||||
}
|
629
vendor/github.com/cloudflare/cfssl/helpers/helpers_test.go
generated
vendored
Normal file
629
vendor/github.com/cloudflare/cfssl/helpers/helpers_test.go
generated
vendored
Normal file
@ -0,0 +1,629 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ocsp"
|
||||
|
||||
"github.com/google/certificate-transparency-go"
|
||||
)
|
||||
|
||||
const (
|
||||
testCertFile = "testdata/cert.pem"
|
||||
testCertDERFile = "testdata/cert.der"
|
||||
testBundleFile = "testdata/bundle.pem"
|
||||
testExtraWSCertFile = "testdata/cert_with_whitespace.pem"
|
||||
testExtraWSBundleFile = "testdata/bundle_with_whitespace.pem"
|
||||
testMessedUpBundleFile = "testdata/messed_up_bundle.pem"
|
||||
testMessedUpCertFile = "testdata/messedupcert.pem"
|
||||
testEmptyCertFile = "testdata/emptycert.pem"
|
||||
testPrivateRSAKey = "testdata/priv_rsa_key.pem"
|
||||
testPrivateECDSAKey = "testdata/private_ecdsa_key.pem"
|
||||
testUnsupportedECDSAKey = "testdata/secp256k1-key.pem"
|
||||
testMessedUpPrivateKey = "testdata/messed_up_priv_key.pem"
|
||||
testEncryptedPrivateKey = "testdata/enc_priv_key.pem"
|
||||
testEmptyPem = "testdata/empty.pem"
|
||||
testNoHeaderCert = "testdata/noheadercert.pem"
|
||||
testSinglePKCS7 = "testdata/cert_pkcs7.pem" // openssl crl2pkcs7 -nocrl -out cert_pkcs7.pem -in cert.pem
|
||||
testEmptyPKCS7DER = "testdata/empty_pkcs7.der" // openssl crl2pkcs7 -nocrl -out empty_pkcs7.der -outform der
|
||||
testEmptyPKCS7PEM = "testdata/empty_pkcs7.pem" // openssl crl2pkcs7 -nocrl -out empty_pkcs7.pem -outform pem
|
||||
testMultiplePKCS7 = "testdata/bundle_pkcs7.pem"
|
||||
testPKCS12EmptyPswd = "testdata/emptypasswordpkcs12.p12"
|
||||
testPKCS12Passwordispassword = "testdata/passwordpkcs12.p12"
|
||||
testPKCS12MultipleCerts = "testdata/multiplecerts.p12"
|
||||
testCSRPEM = "testdata/test.csr.pem"
|
||||
testCSRPEMBad = "testdata/test.bad.csr.pem"
|
||||
)
|
||||
|
||||
func TestParseCertificatesDER(t *testing.T) {
|
||||
var password = []string{"password", "", ""}
|
||||
for i, testFile := range []string{testPKCS12Passwordispassword, testPKCS12EmptyPswd, testCertDERFile} {
|
||||
testDER, err := ioutil.ReadFile(testFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, _, err := ParseCertificatesDER(testDER, password[i]); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Incorrect Password for PKCS12 formatted files
|
||||
if _, _, err := ParseCertificatesDER(testDER, "incorrectpassword"); err == nil && i != 2 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
testDER, err := ioutil.ReadFile(testEmptyPKCS7DER)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// PKCS7 with no certificates
|
||||
if _, _, err := ParseCertificatesDER(testDER, ""); err == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyLength(t *testing.T) {
|
||||
expNil := 0
|
||||
recNil := KeyLength(nil)
|
||||
if expNil != recNil {
|
||||
t.Fatal("KeyLength on nil did not return 0")
|
||||
}
|
||||
|
||||
expNonsense := 0
|
||||
inNonsense := "string?"
|
||||
outNonsense := KeyLength(inNonsense)
|
||||
if expNonsense != outNonsense {
|
||||
t.Fatal("KeyLength malfunctioning on nonsense input")
|
||||
}
|
||||
|
||||
//test the ecdsa branch
|
||||
ecdsaPriv, _ := ecdsa.GenerateKey(elliptic.P224(), rand.Reader)
|
||||
ecdsaIn, _ := ecdsaPriv.Public().(*ecdsa.PublicKey)
|
||||
expEcdsa := ecdsaIn.Curve.Params().BitSize
|
||||
outEcdsa := KeyLength(ecdsaIn)
|
||||
if expEcdsa != outEcdsa {
|
||||
t.Fatal("KeyLength malfunctioning on ecdsa input")
|
||||
}
|
||||
|
||||
//test the rsa branch
|
||||
rsaPriv, _ := rsa.GenerateKey(rand.Reader, 256)
|
||||
rsaIn, _ := rsaPriv.Public().(*rsa.PublicKey)
|
||||
expRsa := rsaIn.N.BitLen()
|
||||
outRsa := KeyLength(rsaIn)
|
||||
|
||||
if expRsa != outRsa {
|
||||
t.Fatal("KeyLength malfunctioning on rsa input")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpiryTime(t *testing.T) {
|
||||
// nil case
|
||||
var expNil time.Time
|
||||
inNil := []*x509.Certificate{}
|
||||
outNil := ExpiryTime(inNil)
|
||||
if expNil != outNil {
|
||||
t.Fatal("Expiry time is malfunctioning on empty input")
|
||||
}
|
||||
|
||||
//read a pem file and use that expiry date
|
||||
bytes, _ := ioutil.ReadFile(testBundleFile)
|
||||
certs, err := ParseCertificatesPEM(bytes)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
expected := time.Date(2014, time.April, 15, 0, 0, 0, 0, time.UTC)
|
||||
out := ExpiryTime(certs)
|
||||
if out != expected {
|
||||
t.Fatalf("Expected %v, got %v", expected, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonthsValid(t *testing.T) {
|
||||
var cert = &x509.Certificate{
|
||||
NotBefore: time.Date(2015, time.April, 01, 0, 0, 0, 0, time.UTC),
|
||||
NotAfter: time.Date(2015, time.April, 01, 0, 0, 0, 0, time.UTC),
|
||||
}
|
||||
|
||||
if MonthsValid(cert) != 0 {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
cert.NotAfter = time.Date(2016, time.April, 01, 0, 0, 0, 0, time.UTC)
|
||||
if MonthsValid(cert) != 12 {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// extra days should be rounded up to 1 month
|
||||
cert.NotAfter = time.Date(2016, time.April, 02, 0, 0, 0, 0, time.UTC)
|
||||
if MonthsValid(cert) != 13 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasValidExpiry(t *testing.T) {
|
||||
// Issue period > April 1, 2015
|
||||
var cert = &x509.Certificate{
|
||||
NotBefore: time.Date(2015, time.April, 01, 0, 0, 0, 0, time.UTC),
|
||||
NotAfter: time.Date(2016, time.April, 01, 0, 0, 0, 0, time.UTC),
|
||||
}
|
||||
|
||||
if !ValidExpiry(cert) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
cert.NotAfter = time.Date(2019, time.April, 01, 01, 0, 0, 0, time.UTC)
|
||||
if ValidExpiry(cert) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Issue period < July 1, 2012
|
||||
cert.NotBefore = time.Date(2009, time.March, 01, 0, 0, 0, 0, time.UTC)
|
||||
if ValidExpiry(cert) {
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
// Issue period July 1, 2012 - April 1, 2015
|
||||
cert.NotBefore = time.Date(2012, time.July, 01, 0, 0, 0, 0, time.UTC)
|
||||
cert.NotAfter = time.Date(2017, time.July, 01, 0, 0, 0, 0, time.UTC)
|
||||
if !ValidExpiry(cert) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashAlgoString(t *testing.T) {
|
||||
if HashAlgoString(x509.MD2WithRSA) != "MD2" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.MD5WithRSA) != "MD5" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.SHA1WithRSA) != "SHA1" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.SHA256WithRSA) != "SHA256" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.SHA384WithRSA) != "SHA384" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.SHA512WithRSA) != "SHA512" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.DSAWithSHA1) != "SHA1" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.DSAWithSHA256) != "SHA256" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.ECDSAWithSHA1) != "SHA1" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.ECDSAWithSHA256) != "SHA256" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.ECDSAWithSHA384) != "SHA384" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(x509.ECDSAWithSHA512) != "SHA512" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
if HashAlgoString(math.MaxInt32) != "Unknown Hash Algorithm" {
|
||||
t.Fatal("standin")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignatureString(t *testing.T) {
|
||||
if SignatureString(x509.MD2WithRSA) != "MD2WithRSA" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.MD5WithRSA) != "MD5WithRSA" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.SHA1WithRSA) != "SHA1WithRSA" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.SHA256WithRSA) != "SHA256WithRSA" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.SHA384WithRSA) != "SHA384WithRSA" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.SHA512WithRSA) != "SHA512WithRSA" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.DSAWithSHA1) != "DSAWithSHA1" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.DSAWithSHA256) != "DSAWithSHA256" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.ECDSAWithSHA1) != "ECDSAWithSHA1" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.ECDSAWithSHA256) != "ECDSAWithSHA256" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.ECDSAWithSHA384) != "ECDSAWithSHA384" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(x509.ECDSAWithSHA512) != "ECDSAWithSHA512" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
if SignatureString(math.MaxInt32) != "Unknown Signature" {
|
||||
t.Fatal("Signature String functioning improperly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCertificatePEM(t *testing.T) {
|
||||
for _, testFile := range []string{testCertFile, testExtraWSCertFile, testSinglePKCS7} {
|
||||
certPEM, err := ioutil.ReadFile(testFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ParseCertificatePEM(certPEM); err != nil {
|
||||
t.Log(testFile)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
for _, testFile := range []string{testBundleFile, testMessedUpCertFile, testEmptyPKCS7PEM, testEmptyCertFile, testMultiplePKCS7} {
|
||||
certPEM, err := ioutil.ReadFile(testFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ParseCertificatePEM(certPEM); err == nil {
|
||||
t.Fatal("Incorrect cert failed to raise error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCertificatesPEM(t *testing.T) {
|
||||
// expected cases
|
||||
for _, testFile := range []string{testBundleFile, testExtraWSBundleFile, testSinglePKCS7, testMultiplePKCS7} {
|
||||
bundlePEM, err := ioutil.ReadFile(testFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ParseCertificatesPEM(bundlePEM); err != nil {
|
||||
t.Log(testFile)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// test failure cases
|
||||
// few lines deleted, then headers removed
|
||||
for _, testFile := range []string{testMessedUpBundleFile, testEmptyPKCS7PEM, testNoHeaderCert} {
|
||||
bundlePEM, err := ioutil.ReadFile(testFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ParseCertificatesPEM(bundlePEM); err == nil {
|
||||
t.Fatal("Incorrectly-formatted file failed to produce an error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelfSignedCertificatePEM(t *testing.T) {
|
||||
testPEM, _ := ioutil.ReadFile(testCertFile)
|
||||
_, err := ParseSelfSignedCertificatePEM(testPEM)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
// a few lines deleted from the pem file
|
||||
wrongPEM, _ := ioutil.ReadFile(testMessedUpCertFile)
|
||||
_, err2 := ParseSelfSignedCertificatePEM(wrongPEM)
|
||||
if err2 == nil {
|
||||
t.Fatal("Improper pem file failed to raise an error")
|
||||
}
|
||||
|
||||
// alter the signature of a valid certificate
|
||||
blk, _ := pem.Decode(testPEM)
|
||||
blk.Bytes[len(blk.Bytes)-10]++ // some hacking to get to the sig
|
||||
alteredBytes := pem.EncodeToMemory(blk)
|
||||
_, err = ParseSelfSignedCertificatePEM(alteredBytes)
|
||||
if err == nil {
|
||||
t.Fatal("Incorrect cert failed to produce an error")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestParsePrivateKeyPEM(t *testing.T) {
|
||||
|
||||
// expected cases
|
||||
testRSAPEM, _ := ioutil.ReadFile(testPrivateRSAKey)
|
||||
_, err := ParsePrivateKeyPEM(testRSAPEM)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testECDSAPEM, _ := ioutil.ReadFile(testPrivateECDSAKey)
|
||||
_, err = ParsePrivateKeyPEM(testECDSAPEM)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// error cases
|
||||
errCases := []string{
|
||||
testMessedUpPrivateKey, // a few lines deleted
|
||||
testEmptyPem, // empty file
|
||||
testEncryptedPrivateKey, // encrypted key
|
||||
testUnsupportedECDSAKey, // ECDSA curve not currently supported by Go standard library
|
||||
}
|
||||
|
||||
for _, fname := range errCases {
|
||||
testPEM, _ := ioutil.ReadFile(fname)
|
||||
_, err = ParsePrivateKeyPEM(testPEM)
|
||||
if err == nil {
|
||||
t.Fatal("Incorrect private key failed to produce an error")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Imported from signers/local/testdata/
|
||||
const ecdsaTestCSR = "testdata/ecdsa256.csr"
|
||||
|
||||
func TestParseCSRPEM(t *testing.T) {
|
||||
in, err := ioutil.ReadFile(ecdsaTestCSR)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
_, _, err = ParseCSR(in)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
in[12]++
|
||||
_, _, err = ParseCSR(in)
|
||||
if err == nil {
|
||||
t.Fatalf("Expected an invalid CSR.")
|
||||
}
|
||||
in[12]--
|
||||
}
|
||||
|
||||
func TestParseCSRPEMMore(t *testing.T) {
|
||||
csrPEM, err := ioutil.ReadFile(testCSRPEM)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ParseCSRPEM(csrPEM); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
csrPEM, err = ioutil.ReadFile(testCSRPEMBad)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ParseCSRPEM(csrPEM); err == nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := ParseCSRPEM([]byte("not even pem")); err == nil {
|
||||
t.Fatal("Expected an invalid CSR.")
|
||||
}
|
||||
}
|
||||
|
||||
// Imported from signers/local/testdata/
|
||||
const rsaOldTestCSR = "testdata/rsa-old.csr"
|
||||
|
||||
func TestParseOldCSR(t *testing.T) {
|
||||
in, err := ioutil.ReadFile(rsaOldTestCSR)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
_, _, err = ParseCSR(in)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Imported from signers/local/testdata/
|
||||
const clientCertFile = "testdata/ca.pem"
|
||||
const clientKeyFile = "testdata/ca_key.pem"
|
||||
|
||||
func TestClientCertParams(t *testing.T) {
|
||||
_, err := LoadClientCertificate(testCertFile, testPrivateRSAKey)
|
||||
if err == nil {
|
||||
t.Fatal("Unmatched cert/key should generate error")
|
||||
}
|
||||
|
||||
cert, err := LoadClientCertificate("", "")
|
||||
if err != nil || cert != nil {
|
||||
t.Fatal("Certificate atempted to loaded with missing key and cert")
|
||||
}
|
||||
cert, err = LoadClientCertificate(clientCertFile, "")
|
||||
if err != nil || cert != nil {
|
||||
t.Fatal("Certificate atempted to loaded with missing key")
|
||||
}
|
||||
cert, err = LoadClientCertificate("", clientKeyFile)
|
||||
if err != nil || cert != nil {
|
||||
t.Fatal("Certificate atempted to loaded with missing cert")
|
||||
}
|
||||
|
||||
cert, err = LoadClientCertificate(clientCertFile, clientKeyFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cert == nil {
|
||||
t.Fatal("cert not created")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPEMCertPool(t *testing.T) {
|
||||
certPool, err := PEMToCertPool([]byte{})
|
||||
if certPool != nil || err != nil {
|
||||
t.Fatal("Empty file name should not generate error or a cert pool")
|
||||
}
|
||||
|
||||
in, err := ioutil.ReadFile(testEmptyPem)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
certPool, err = PEMToCertPool(in)
|
||||
if certPool != nil {
|
||||
t.Fatal("Empty file should not generate a cert pool")
|
||||
} else if err == nil {
|
||||
t.Fatal("Expected error for empty file")
|
||||
}
|
||||
|
||||
in, err = ioutil.ReadFile(testEmptyCertFile)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
certPool, err = PEMToCertPool(in)
|
||||
if certPool != nil {
|
||||
t.Fatal("Empty cert should not generate a cert pool")
|
||||
} else if err == nil {
|
||||
t.Fatal("Expected error for empty cert")
|
||||
}
|
||||
|
||||
in, err = ioutil.ReadFile(clientCertFile)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
certPool, err = PEMToCertPool(in)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
} else if certPool == nil {
|
||||
t.Fatal("cert pool not created")
|
||||
}
|
||||
}
|
||||
|
||||
// sctEquals returns true if all fields of both SCTs are equivalent.
|
||||
func sctEquals(sctA, sctB ct.SignedCertificateTimestamp) bool {
|
||||
if sctA.SCTVersion == sctB.SCTVersion &&
|
||||
sctA.LogID == sctB.LogID &&
|
||||
sctA.Timestamp == sctB.Timestamp &&
|
||||
bytes.Equal(sctA.Extensions, sctB.Extensions) &&
|
||||
sctA.Signature.Algorithm == sctB.Signature.Algorithm &&
|
||||
bytes.Equal(sctA.Signature.Signature, sctA.Signature.Signature) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// NOTE: TestDeserializeSCTList tests both DeserializeSCTList and
|
||||
// SerializeSCTList.
|
||||
func TestDeserializeSCTList(t *testing.T) {
|
||||
// Here we make sure that empty SCT lists return an error
|
||||
emptyLists := [][]byte{nil, {}}
|
||||
for _, emptyList := range emptyLists {
|
||||
_, err := DeserializeSCTList(emptyList)
|
||||
if err == nil {
|
||||
t.Fatalf("DeserializeSCTList(%v) should raise an error\n", emptyList)
|
||||
}
|
||||
}
|
||||
|
||||
// Here we make sure that an SCT list with a zero SCT is deserialized
|
||||
// correctly
|
||||
var zeroSCT ct.SignedCertificateTimestamp
|
||||
serializedSCT, err := SerializeSCTList([]ct.SignedCertificateTimestamp{zeroSCT})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
deserializedSCTList, err := DeserializeSCTList(serializedSCT)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !sctEquals(zeroSCT, (deserializedSCTList)[0]) {
|
||||
t.Fatal("SCTs don't match")
|
||||
}
|
||||
|
||||
// Here we verify that an error is raised when the SCT list length
|
||||
// field is greater than its actual length
|
||||
serializedSCT, err = SerializeSCTList([]ct.SignedCertificateTimestamp{zeroSCT})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
serializedSCT[0] = 15
|
||||
_, err = DeserializeSCTList(serializedSCT)
|
||||
if err == nil {
|
||||
t.Fatalf("DeserializeSCTList should raise an error when " +
|
||||
"the SCT list length field and the list length don't match\n")
|
||||
}
|
||||
|
||||
// Here we verify that an error is raised when the SCT list length
|
||||
// field is less than its actual length
|
||||
serializedSCT[0] = 0
|
||||
serializedSCT[1] = 0
|
||||
_, err = DeserializeSCTList(serializedSCT)
|
||||
if err == nil {
|
||||
t.Fatalf("DeserializeSCTList should raise an error when " +
|
||||
"the SCT list length field and the list length don't match\n")
|
||||
}
|
||||
|
||||
// Here we verify that an error is raised when the SCT length field is
|
||||
// greater than its actual length
|
||||
serializedSCT[0] = 0
|
||||
serializedSCT[1] = 49
|
||||
serializedSCT[2] = 1
|
||||
_, err = DeserializeSCTList(serializedSCT)
|
||||
if err == nil {
|
||||
t.Fatalf("DeserializeSCTList should raise an error when " +
|
||||
"the SCT length field and the SCT length don't match\n")
|
||||
}
|
||||
|
||||
// Here we verify that an error is raised when the SCT length field is
|
||||
// less than its actual length
|
||||
serializedSCT[2] = 0
|
||||
serializedSCT[3] = 0
|
||||
_, err = DeserializeSCTList(serializedSCT)
|
||||
if err == nil {
|
||||
t.Fatalf("DeserializeSCTList should raise an error when " +
|
||||
"the SCT length field and the SCT length don't match\n")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSCTListFromOCSPResponse(t *testing.T) {
|
||||
var response ocsp.Response
|
||||
lst, err := SCTListFromOCSPResponse(&response)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(lst) != 0 {
|
||||
t.Fatal("SCTListFromOCSPResponse should return an empty SCT list for an empty extension")
|
||||
}
|
||||
|
||||
var zeroSCT ct.SignedCertificateTimestamp
|
||||
serializedSCTList, err := SerializeSCTList([]ct.SignedCertificateTimestamp{zeroSCT})
|
||||
if err != nil {
|
||||
t.Fatal("failed to serialize SCT list")
|
||||
}
|
||||
serializedSCTList, err = asn1.Marshal(serializedSCTList)
|
||||
if err != nil {
|
||||
t.Fatal("failed to serialize SCT list")
|
||||
}
|
||||
// The value of Id below is the object identifier of the OCSP Stapling
|
||||
// SCT extension (see section 3.3. of RFC 6962).
|
||||
response.Extensions = []pkix.Extension{{
|
||||
Id: asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 5},
|
||||
Critical: false,
|
||||
Value: serializedSCTList,
|
||||
}}
|
||||
lst, err = SCTListFromOCSPResponse(&response)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !sctEquals(zeroSCT, lst[0]) {
|
||||
t.Fatal("SCTs don't match")
|
||||
}
|
||||
}
|
53
vendor/github.com/cloudflare/cfssl/helpers/testdata/bundle.pem
generated
vendored
Normal file
53
vendor/github.com/cloudflare/cfssl/helpers/testdata/bundle.pem
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEczCCAl2gAwIBAgIIDARj8BWNsscwCwYJKoZIhvcNAQELMIGMMQswCQYDVQQG
|
||||
EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
|
||||
bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
|
||||
cm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wHhcNMTQwMzAyMDAw
|
||||
MDAwWhcNMTkwNDAxMDAwMDAwWjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNs
|
||||
b3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcT
|
||||
DVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHTAbBgNVBAMTFGNs
|
||||
b3VkZmxhcmUtaW50ZXIuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEIVkjNJGw
|
||||
f3F0XWJH7yQSVtxuoBidi5JNsQ7FhxEQcZEl3b+/1iF60TBY2Yi6KwJuA6nIE73P
|
||||
IXGyfNhThw4D8CiZbackQ/ufgz2DyvxyWFDPzLr7TXeM/0wSp/imoxWeo4GIMIGF
|
||||
MA4GA1UdDwEB/wQEAwIApDASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBRB
|
||||
+YoiUjIm34/wBwHdJGE4Wufs/DAfBgNVHSMEGDAWgBTXXUgpaSwO9HOrQBxGqOOS
|
||||
FHsHEDAfBgNVHREEGDAWghRjbG91ZGZsYXJlLWludGVyLmNvbTALBgkqhkiG9w0B
|
||||
AQsDggIBACRqAC5EJEe+8ihv1WzCUMEMb7KtS0BqoNbdXE32ia66PgJSQmHcmeJd
|
||||
FI1UjL0DlljTM2tc+8KxR/1/qnKiI+W/D4wFTWOY/JWFOd15q7lXuKGl+8PMkAHF
|
||||
A145JCr6oZoO9G9wUwVUrbmXAbyPCOfzsEQ2+mD9F1ZpoEjzVhtGf0R+vnYrRw8j
|
||||
4WCv5AIcYRAf7HZxbhMILF1bccNlqyUtdH+/MTHXpjkjJjA5KbsHBrAEfjAXkD7c
|
||||
WWOay6m7mVWb3PPFmGorP6t29baEETK9ZTZSrfD9rnExjjUCftWJEn0M4Pp98DvT
|
||||
br6+bg8jwtq73qdyOfNsC/Sod18UuHH7MTQA22yqAF5jIlcYtAHGlNnl+sDPZACs
|
||||
369/Z9rOL9vPFL+Z3F/uJtqZzvN1QiCkj8jWzR0u9fh3eQwZADM2RwgwS4Gs2Ygh
|
||||
PsypDo33sFOwfX93KqKBsTHssn8SSDDaSnZ8bu1ATEdshbVieecuQx40UadPuJpw
|
||||
EPVqTR5AhviXQ9bKrTnU5T7EgkW9vNydkpLQQlMg3QE8hsndv4loGZbZGfNtqQHS
|
||||
/mg1t07S+7OEa4YaMW+wVOBOqTdW7OXlZFLfCcF5SYLM0SnlTMklRMxiqI4JqZXH
|
||||
0thnUGD0JjfLX4rTaZUzT3lrXXWzpS2jzutXQkjGv4nhGGprIDuT
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEkDCCA/ugAwIBAgIIWnP9jF/2nogwCwYJKoZIhvcNAQELMH0xCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv
|
||||
MRMwEQYDVQQKDApDbG91ZEZsYXJlMRQwEgYDVQQLDAtERVZfVEVTVElORzEWMBQG
|
||||
A1UEAwwNQ0ZTU0xfVEVTVF9DQTAeFw0xNDAzMDEwMDAwMDBaFw0xNDA0MTUwMDAw
|
||||
MDBaMIGMMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UE
|
||||
CxMTU3lzdGVtcyBFbmdpbmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzET
|
||||
MBEGA1UECBMKQ2FsaWZvcm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5j
|
||||
b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDlCnV+vj0sVPy8SqHL
|
||||
AlI+xwnPhWgzj2VevD6Nz1Zu1BeQ5m5y4CWCf+GmRGTP7+a/C510Fw6rpmInB0Ng
|
||||
xxwQ2rC08fJtCnijlGH/VjEPIHY5lRaAomcM8Rgx6JOuv9BpZJKpr9pyUMV53JeW
|
||||
RbWuLH5nEMdyk9NpetS2gWxt4/D20QlhK/tHkROrcLmEUddwIGdwE8JzI88c77Fu
|
||||
u6pgMtHKvl4GGH0yvb4T7PvCdH8V2tCH7bt8roXd9MSyFVy7uORkfouip7EsVREU
|
||||
mlcY5EvpR141KXbZqiOQiusJ+u76mEUQNk8wCR1/CW/ii9v1BKOVjXwCfEtIXjg0
|
||||
APJx1VNSSH6XoDpUETL+eQ4J0FL9XNbsDuYar7+zD0N1/5vSo3HLNRQR9f0lbsys
|
||||
sWBEN+CxK19xyPumr21Z0bU0f1B5H52VSF0q3I1Ju9wRo994a7YipdGcmZ2lChmT
|
||||
7r3mzlBTYl3poU26q34v8wG9U7Jv4fsZJ+RGebDI+TR3QG6Yod06l9oEYZxWXBY7
|
||||
STOs8wuTu3huSnan/IpWnV017Vsc61D5G+QrqcxZdXckt3anZKCF75JpUnJ7vuow
|
||||
TmmHlb8KIMa9mOvcuGX4P6mz8gTi2arl/aL27kj9Q0Jgv/y1ebe2Bx2P9TF6+VND
|
||||
DL3J/vSVlFeqLt2reAIBKnytLwIDAQABo4GIMIGFMA4GA1UdDwEB/wQEAwIApDAS
|
||||
BgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBTXXUgpaSwO9HOrQBxGqOOSFHsH
|
||||
EDAfBgNVHSMEGDAWgBS4Xu+uZ1C31vMH5Wq+VbNnOg2SPjAfBgNVHREEGDAWghRj
|
||||
bG91ZGZsYXJlLWludGVyLmNvbTALBgkqhkiG9w0BAQsDgYEAfPLKCAHnPzgMYLX/
|
||||
fWznVvOEFAAYZByPFx4QdMBbDZUtxHyvJIBs6PdxrdSuDwSiMqE7qQIi+jzzwGl9
|
||||
fC7vf45B2zCX0OW51QL2oWNBdKlGgB+b2pwyME82lX/Pr7V1GY10u+ep1xdZDnch
|
||||
DaMsXjQQTJu0iuG3qKEuCmUwOmc=
|
||||
-----END CERTIFICATE-----
|
52
vendor/github.com/cloudflare/cfssl/helpers/testdata/bundle_pkcs7.pem
generated
vendored
Normal file
52
vendor/github.com/cloudflare/cfssl/helpers/testdata/bundle_pkcs7.pem
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
-----BEGIN PKCS7-----
|
||||
MIIJOAYJKoZIhvcNAQcCoIIJKTCCCSUCAQExADALBgkqhkiG9w0BBwGgggkLMIIE
|
||||
czCCAl2gAwIBAgIIDARj8BWNsscwCwYJKoZIhvcNAQELMIGMMQswCQYDVQQGEwJV
|
||||
UzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdpbmVl
|
||||
cmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZvcm5p
|
||||
YTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wHhcNMTQwMzAyMDAwMDAw
|
||||
WhcNMTkwNDAxMDAwMDAwWjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNsb3Vk
|
||||
RmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcTDVNh
|
||||
biBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHTAbBgNVBAMTFGNsb3Vk
|
||||
ZmxhcmUtaW50ZXIuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEIVkjNJGwf3F0
|
||||
XWJH7yQSVtxuoBidi5JNsQ7FhxEQcZEl3b+/1iF60TBY2Yi6KwJuA6nIE73PIXGy
|
||||
fNhThw4D8CiZbackQ/ufgz2DyvxyWFDPzLr7TXeM/0wSp/imoxWeo4GIMIGFMA4G
|
||||
A1UdDwEB/wQEAwIApDASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBRB+Yoi
|
||||
UjIm34/wBwHdJGE4Wufs/DAfBgNVHSMEGDAWgBTXXUgpaSwO9HOrQBxGqOOSFHsH
|
||||
EDAfBgNVHREEGDAWghRjbG91ZGZsYXJlLWludGVyLmNvbTALBgkqhkiG9w0BAQsD
|
||||
ggIBACRqAC5EJEe+8ihv1WzCUMEMb7KtS0BqoNbdXE32ia66PgJSQmHcmeJdFI1U
|
||||
jL0DlljTM2tc+8KxR/1/qnKiI+W/D4wFTWOY/JWFOd15q7lXuKGl+8PMkAHFA145
|
||||
JCr6oZoO9G9wUwVUrbmXAbyPCOfzsEQ2+mD9F1ZpoEjzVhtGf0R+vnYrRw8j4WCv
|
||||
5AIcYRAf7HZxbhMILF1bccNlqyUtdH+/MTHXpjkjJjA5KbsHBrAEfjAXkD7cWWOa
|
||||
y6m7mVWb3PPFmGorP6t29baEETK9ZTZSrfD9rnExjjUCftWJEn0M4Pp98DvTbr6+
|
||||
bg8jwtq73qdyOfNsC/Sod18UuHH7MTQA22yqAF5jIlcYtAHGlNnl+sDPZACs369/
|
||||
Z9rOL9vPFL+Z3F/uJtqZzvN1QiCkj8jWzR0u9fh3eQwZADM2RwgwS4Gs2YghPsyp
|
||||
Do33sFOwfX93KqKBsTHssn8SSDDaSnZ8bu1ATEdshbVieecuQx40UadPuJpwEPVq
|
||||
TR5AhviXQ9bKrTnU5T7EgkW9vNydkpLQQlMg3QE8hsndv4loGZbZGfNtqQHS/mg1
|
||||
t07S+7OEa4YaMW+wVOBOqTdW7OXlZFLfCcF5SYLM0SnlTMklRMxiqI4JqZXH0thn
|
||||
UGD0JjfLX4rTaZUzT3lrXXWzpS2jzutXQkjGv4nhGGprIDuTMIIEkDCCA/ugAwIB
|
||||
AgIIWnP9jF/2nogwCwYJKoZIhvcNAQELMH0xCzAJBgNVBAYTAlVTMRMwEQYDVQQI
|
||||
DApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRMwEQYDVQQKDApD
|
||||
bG91ZEZsYXJlMRQwEgYDVQQLDAtERVZfVEVTVElORzEWMBQGA1UEAwwNQ0ZTU0xf
|
||||
VEVTVF9DQTAeFw0xNDAzMDEwMDAwMDBaFw0xNDA0MTUwMDAwMDBaMIGMMQswCQYD
|
||||
VQQGEwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBF
|
||||
bmdpbmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2Fs
|
||||
aWZvcm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wggIiMA0GCSqG
|
||||
SIb3DQEBAQUAA4ICDwAwggIKAoICAQDlCnV+vj0sVPy8SqHLAlI+xwnPhWgzj2Ve
|
||||
vD6Nz1Zu1BeQ5m5y4CWCf+GmRGTP7+a/C510Fw6rpmInB0NgxxwQ2rC08fJtCnij
|
||||
lGH/VjEPIHY5lRaAomcM8Rgx6JOuv9BpZJKpr9pyUMV53JeWRbWuLH5nEMdyk9Np
|
||||
etS2gWxt4/D20QlhK/tHkROrcLmEUddwIGdwE8JzI88c77Fuu6pgMtHKvl4GGH0y
|
||||
vb4T7PvCdH8V2tCH7bt8roXd9MSyFVy7uORkfouip7EsVREUmlcY5EvpR141KXbZ
|
||||
qiOQiusJ+u76mEUQNk8wCR1/CW/ii9v1BKOVjXwCfEtIXjg0APJx1VNSSH6XoDpU
|
||||
ETL+eQ4J0FL9XNbsDuYar7+zD0N1/5vSo3HLNRQR9f0lbsyssWBEN+CxK19xyPum
|
||||
r21Z0bU0f1B5H52VSF0q3I1Ju9wRo994a7YipdGcmZ2lChmT7r3mzlBTYl3poU26
|
||||
q34v8wG9U7Jv4fsZJ+RGebDI+TR3QG6Yod06l9oEYZxWXBY7STOs8wuTu3huSnan
|
||||
/IpWnV017Vsc61D5G+QrqcxZdXckt3anZKCF75JpUnJ7vuowTmmHlb8KIMa9mOvc
|
||||
uGX4P6mz8gTi2arl/aL27kj9Q0Jgv/y1ebe2Bx2P9TF6+VNDDL3J/vSVlFeqLt2r
|
||||
eAIBKnytLwIDAQABo4GIMIGFMA4GA1UdDwEB/wQEAwIApDASBgNVHRMBAf8ECDAG
|
||||
AQH/AgEBMB0GA1UdDgQWBBTXXUgpaSwO9HOrQBxGqOOSFHsHEDAfBgNVHSMEGDAW
|
||||
gBS4Xu+uZ1C31vMH5Wq+VbNnOg2SPjAfBgNVHREEGDAWghRjbG91ZGZsYXJlLWlu
|
||||
dGVyLmNvbTALBgkqhkiG9w0BAQsDgYEAfPLKCAHnPzgMYLX/fWznVvOEFAAYZByP
|
||||
Fx4QdMBbDZUtxHyvJIBs6PdxrdSuDwSiMqE7qQIi+jzzwGl9fC7vf45B2zCX0OW5
|
||||
1QL2oWNBdKlGgB+b2pwyME82lX/Pr7V1GY10u+ep1xdZDnchDaMsXjQQTJu0iuG3
|
||||
qKEuCmUwOmehADEA
|
||||
-----END PKCS7-----
|
56
vendor/github.com/cloudflare/cfssl/helpers/testdata/bundle_with_whitespace.pem
generated
vendored
Normal file
56
vendor/github.com/cloudflare/cfssl/helpers/testdata/bundle_with_whitespace.pem
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEczCCAl2gAwIBAgIIDARj8BWNsscwCwYJKoZIhvcNAQELMIGMMQswCQYDVQQG
|
||||
EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
|
||||
bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
|
||||
cm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wHhcNMTQwMzAyMDAw
|
||||
MDAwWhcNMTkwNDAxMDAwMDAwWjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNs
|
||||
b3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcT
|
||||
DVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3JuaWExHTAbBgNVBAMTFGNs
|
||||
b3VkZmxhcmUtaW50ZXIuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEIVkjNJGw
|
||||
f3F0XWJH7yQSVtxuoBidi5JNsQ7FhxEQcZEl3b+/1iF60TBY2Yi6KwJuA6nIE73P
|
||||
IXGyfNhThw4D8CiZbackQ/ufgz2DyvxyWFDPzLr7TXeM/0wSp/imoxWeo4GIMIGF
|
||||
MA4GA1UdDwEB/wQEAwIApDASBgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBRB
|
||||
+YoiUjIm34/wBwHdJGE4Wufs/DAfBgNVHSMEGDAWgBTXXUgpaSwO9HOrQBxGqOOS
|
||||
FHsHEDAfBgNVHREEGDAWghRjbG91ZGZsYXJlLWludGVyLmNvbTALBgkqhkiG9w0B
|
||||
AQsDggIBACRqAC5EJEe+8ihv1WzCUMEMb7KtS0BqoNbdXE32ia66PgJSQmHcmeJd
|
||||
FI1UjL0DlljTM2tc+8KxR/1/qnKiI+W/D4wFTWOY/JWFOd15q7lXuKGl+8PMkAHF
|
||||
A145JCr6oZoO9G9wUwVUrbmXAbyPCOfzsEQ2+mD9F1ZpoEjzVhtGf0R+vnYrRw8j
|
||||
4WCv5AIcYRAf7HZxbhMILF1bccNlqyUtdH+/MTHXpjkjJjA5KbsHBrAEfjAXkD7c
|
||||
WWOay6m7mVWb3PPFmGorP6t29baEETK9ZTZSrfD9rnExjjUCftWJEn0M4Pp98DvT
|
||||
br6+bg8jwtq73qdyOfNsC/Sod18UuHH7MTQA22yqAF5jIlcYtAHGlNnl+sDPZACs
|
||||
369/Z9rOL9vPFL+Z3F/uJtqZzvN1QiCkj8jWzR0u9fh3eQwZADM2RwgwS4Gs2Ygh
|
||||
PsypDo33sFOwfX93KqKBsTHssn8SSDDaSnZ8bu1ATEdshbVieecuQx40UadPuJpw
|
||||
EPVqTR5AhviXQ9bKrTnU5T7EgkW9vNydkpLQQlMg3QE8hsndv4loGZbZGfNtqQHS
|
||||
/mg1t07S+7OEa4YaMW+wVOBOqTdW7OXlZFLfCcF5SYLM0SnlTMklRMxiqI4JqZXH
|
||||
0thnUGD0JjfLX4rTaZUzT3lrXXWzpS2jzutXQkjGv4nhGGprIDuT
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEkDCCA/ugAwIBAgIIWnP9jF/2nogwCwYJKoZIhvcNAQELMH0xCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv
|
||||
MRMwEQYDVQQKDApDbG91ZEZsYXJlMRQwEgYDVQQLDAtERVZfVEVTVElORzEWMBQG
|
||||
A1UEAwwNQ0ZTU0xfVEVTVF9DQTAeFw0xNDAzMDEwMDAwMDBaFw0xNDA0MTUwMDAw
|
||||
MDBaMIGMMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UE
|
||||
CxMTU3lzdGVtcyBFbmdpbmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzET
|
||||
MBEGA1UECBMKQ2FsaWZvcm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5j
|
||||
b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDlCnV+vj0sVPy8SqHL
|
||||
AlI+xwnPhWgzj2VevD6Nz1Zu1BeQ5m5y4CWCf+GmRGTP7+a/C510Fw6rpmInB0Ng
|
||||
xxwQ2rC08fJtCnijlGH/VjEPIHY5lRaAomcM8Rgx6JOuv9BpZJKpr9pyUMV53JeW
|
||||
RbWuLH5nEMdyk9NpetS2gWxt4/D20QlhK/tHkROrcLmEUddwIGdwE8JzI88c77Fu
|
||||
u6pgMtHKvl4GGH0yvb4T7PvCdH8V2tCH7bt8roXd9MSyFVy7uORkfouip7EsVREU
|
||||
mlcY5EvpR141KXbZqiOQiusJ+u76mEUQNk8wCR1/CW/ii9v1BKOVjXwCfEtIXjg0
|
||||
APJx1VNSSH6XoDpUETL+eQ4J0FL9XNbsDuYar7+zD0N1/5vSo3HLNRQR9f0lbsys
|
||||
sWBEN+CxK19xyPumr21Z0bU0f1B5H52VSF0q3I1Ju9wRo994a7YipdGcmZ2lChmT
|
||||
7r3mzlBTYl3poU26q34v8wG9U7Jv4fsZJ+RGebDI+TR3QG6Yod06l9oEYZxWXBY7
|
||||
STOs8wuTu3huSnan/IpWnV017Vsc61D5G+QrqcxZdXckt3anZKCF75JpUnJ7vuow
|
||||
TmmHlb8KIMa9mOvcuGX4P6mz8gTi2arl/aL27kj9Q0Jgv/y1ebe2Bx2P9TF6+VND
|
||||
DL3J/vSVlFeqLt2reAIBKnytLwIDAQABo4GIMIGFMA4GA1UdDwEB/wQEAwIApDAS
|
||||
BgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBTXXUgpaSwO9HOrQBxGqOOSFHsH
|
||||
EDAfBgNVHSMEGDAWgBS4Xu+uZ1C31vMH5Wq+VbNnOg2SPjAfBgNVHREEGDAWghRj
|
||||
bG91ZGZsYXJlLWludGVyLmNvbTALBgkqhkiG9w0BAQsDgYEAfPLKCAHnPzgMYLX/
|
||||
fWznVvOEFAAYZByPFx4QdMBbDZUtxHyvJIBs6PdxrdSuDwSiMqE7qQIi+jzzwGl9
|
||||
fC7vf45B2zCX0OW51QL2oWNBdKlGgB+b2pwyME82lX/Pr7V1GY10u+ep1xdZDnch
|
||||
DaMsXjQQTJu0iuG3qKEuCmUwOmc=
|
||||
-----END CERTIFICATE-----
|
||||
|
27
vendor/github.com/cloudflare/cfssl/helpers/testdata/ca.pem
generated
vendored
Normal file
27
vendor/github.com/cloudflare/cfssl/helpers/testdata/ca.pem
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEmzCCA4OgAwIBAgIMAMSvNBgypwaaSQ5iMA0GCSqGSIb3DQEBBQUAMIGMMQsw
|
||||
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
|
||||
YW5jaXNjbzETMBEGA1UEChMKQ0ZTU0wgVEVTVDEbMBkGA1UEAxMSQ0ZTU0wgVEVT
|
||||
VCBSb290IENBMR4wHAYJKoZIhvcNAQkBFg90ZXN0QHRlc3QubG9jYWwwHhcNMTIx
|
||||
MjEyMDIxMDMxWhcNMjIxMDIxMDIxMDMxWjCBjDELMAkGA1UEBhMCVVMxEzARBgNV
|
||||
BAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEzARBgNVBAoT
|
||||
CkNGU1NMIFRFU1QxGzAZBgNVBAMTEkNGU1NMIFRFU1QgUm9vdCBDQTEeMBwGCSqG
|
||||
SIb3DQEJARYPdGVzdEB0ZXN0LmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEAsRp1xSfIDoD/40Bo4Hls3sFn4dav5NgxbZGpVyGF7dJI9u0eEnL4
|
||||
BUGssPaUFLWC83CZxujUEiEfE0oKX+uOhhGv3+j5xSTNM764m2eSiN53cdZtK05d
|
||||
hwq9uS8LtjKOQeN1mQ5qmiqxBMdjkKgMsVw5lMCgoYKo57kaKFyXzdpNVDzqw+pt
|
||||
HWmuNtDQjK3qT5Ma06mYPmIGYhIZYLY7oJGg9ZEaNR0GIw4zIT5JRsNiaSb5wTLw
|
||||
aa0n/4vLJyVjLJcYmJBvZWj8g+taK+C4INu/jGux+bmsC9hq14tbOaTNAn/NE0qN
|
||||
8oHwcRBEqfOdEYdZkxI5NWPiKNW/Q+AeXQIDAQABo4H6MIH3MB0GA1UdDgQWBBS3
|
||||
0veEuqg51fusEM4p/YuWpBPsvTCBxAYDVR0jBIG8MIG5gBS30veEuqg51fusEM4p
|
||||
/YuWpBPsvaGBkqSBjzCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3Ju
|
||||
aWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEzARBgNVBAoTCkNGU1NMIFRFU1Qx
|
||||
GzAZBgNVBAMTEkNGU1NMIFRFU1QgUm9vdCBDQTEeMBwGCSqGSIb3DQEJARYPdGVz
|
||||
dEB0ZXN0LmxvY2FsggwAxK80GDKnBppJDmIwDwYDVR0TBAgwBgEB/wIBADANBgkq
|
||||
hkiG9w0BAQUFAAOCAQEAJ7r1EZYDwed6rS0+YKHdkRGRQ5Rz6A9DIVBPXrSMAGj3
|
||||
F5EF2m/GJbhpVbnNJTVlgP9DDyabOZNxzdrCr4cHMkYYnocDdgAodnkw6GZ/GJTc
|
||||
depbVTR4TpihFNzeDEGJePrEwM1DouGswpu97jyuCYZ3z1a60+a+3C1GwWaJ7Aet
|
||||
Uqm+yLTUrMISsfnDPqJdM1NeqW3jiZ4IgcqJkieCCSpag9Xuzrp9q6rjmePvlQkv
|
||||
qz020JGg6VijJ+c6Tf5y0XqbAhkBTqYtVamu9gEth9utn12EhdNjTZMPKMjjgFUd
|
||||
H0N6yOEuQMl4ky7RxZBM0iPyeob6i4z2LEQilgv9MQ==
|
||||
-----END CERTIFICATE-----
|
28
vendor/github.com/cloudflare/cfssl/helpers/testdata/ca_key.pem
generated
vendored
Normal file
28
vendor/github.com/cloudflare/cfssl/helpers/testdata/ca_key.pem
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCxGnXFJ8gOgP/j
|
||||
QGjgeWzewWfh1q/k2DFtkalXIYXt0kj27R4ScvgFQayw9pQUtYLzcJnG6NQSIR8T
|
||||
Sgpf646GEa/f6PnFJM0zvribZ5KI3ndx1m0rTl2HCr25Lwu2Mo5B43WZDmqaKrEE
|
||||
x2OQqAyxXDmUwKChgqjnuRooXJfN2k1UPOrD6m0daa420NCMrepPkxrTqZg+YgZi
|
||||
EhlgtjugkaD1kRo1HQYjDjMhPklGw2JpJvnBMvBprSf/i8snJWMslxiYkG9laPyD
|
||||
61or4Lgg27+Ma7H5uawL2GrXi1s5pM0Cf80TSo3ygfBxEESp850Rh1mTEjk1Y+Io
|
||||
1b9D4B5dAgMBAAECggEAKHhjcSomDSptTwDo9mLI/h40HudwSlsc8GzYxZBjinUD
|
||||
N2n39T9QbeMUE1xFenX/9qFEgq+xxnLLJx1EQacSapCgIAqdCO/f9HMgvGJumdg8
|
||||
c0cMq1i9Bp7tu+OESZ5D48qWlOM2eQRIb08g8W11eRIaFmPuUPoKnuktkQuXpPJc
|
||||
YbS/+JuA8SDwe6sV0cMCQuS+iHFfeGwWCKrDUkhLwcL3waW3od2XFyOeFFWFhl0h
|
||||
HmM/mWKRuRdqR7hrmArTwFZVkB+o/1ywVYXIv+JQm0eNZ5PKLNJGL2f5oxbMR/JI
|
||||
AoK0bAlJmYaFp96h1KpbPwLEL/0hHSWA7sAyJIgQAQKBgQDaEAZor/w4ZUTekT1+
|
||||
cbId0yA+ikDXQOfXaNCSh9Pex+Psjd5zVVOqyVFJ29daRju3d7rmpN4Cm5V4h0l1
|
||||
/2ad207rjCAnpCHtaddJWNyJzF2IL2IaoCZQRp0k7zOjBGQpoWDTwBaEin5CCv3P
|
||||
kkdQkKz6FDP1xskHSLZr21/QCQKBgQDP6jXutEgGjf3yKpMFk/69EamJdon8clbt
|
||||
hl7cOyWtobnZhdOWVZPe00Oo3Jag2aWgFFsm3EtwnUCnR4d4+fXRKS2LkhfIUZcz
|
||||
cKy17Ileggdd8UGhL4RDrF/En9tJL86WcVkcoOrqLcGB2FLWrVhVpHFK74eLMCH/
|
||||
uc/+ioPItQKBgHYoDsD08s7AGMQcoNx90MyWVLduhFnegoFW+wUa8jOZzieka6/E
|
||||
wVQeR5yksZjpy3vLNYu6M83n7eLkM2rrm/fXGHlLcTTpm7SgEBZfPwivotKjEh5p
|
||||
PrlqucWEk082lutz1RqHz+u7e1Rfzk2F7nx6GDBdeBYpw03eGXJx6QW5AoGBAIJq
|
||||
4puyAEAET1fZNtHX7IGCk7sDXTi6LCbgE57HhzHr8V0t4fQ6CABMuvMwM1gATjEk
|
||||
s6yjoLqqGUUUzDipanViBAy5fiuManC868lN7zkWDTLzQ3ytBqVAee4na/DziP27
|
||||
ae9YTSLJwskE/alloLRP6zTbHUXE0n7LelmrX1DFAoGBAMFLl+Lu+WFgCHxBjn43
|
||||
rHpJbQZQmsFhAMhkN4hsj6dJfAGn2gRLRiVRAika+8QF65xMZiVQWUVSUZADWERi
|
||||
0SXGjzN1wYxO3Qzy3LYwws6fxFAq5lo79eb38yFT2lHdqK3x/QgiDSRVl+R6cExV
|
||||
xQB518/lp2eIeMpglWByDwJX
|
||||
-----END PRIVATE KEY-----
|
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/cert.der
generated
vendored
Normal file
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/cert.der
generated
vendored
Normal file
Binary file not shown.
13
vendor/github.com/cloudflare/cfssl/helpers/testdata/cert.pem
generated
vendored
Normal file
13
vendor/github.com/cloudflare/cfssl/helpers/testdata/cert.pem
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB7DCCAZKgAwIBAgIIE/Qz49ebG7kwCgYIKoZIzj0EAwIwTDELMAkGA1UEBhMC
|
||||
VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
|
||||
EDAOBgNVBAoTB2FjbWUuY28wHhcNMTcwNTIzMTk1MTQ0WhcNMTcwODIzMDE1NjQ0
|
||||
WjBMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN
|
||||
U2FuIEZyYW5jaXNjbzEQMA4GA1UEChMHYWNtZS5jbzBZMBMGByqGSM49AgEGCCqG
|
||||
SM49AwEHA0IABEW8F+k/avvdBm/KRsuDnTZ3p+VuVdsqDF+aD9nIYeOhx5sj574y
|
||||
hEIZOpgbEsi3BvqY63y2jYyPFodf25+CA9GjXjBcMA4GA1UdDwEB/wQEAwIFoDAd
|
||||
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNV
|
||||
HQ4EFgQUzDpu+HN89EC1M8aNl7f0Ln5JnnIwCgYIKoZIzj0EAwIDSAAwRQIgC4/r
|
||||
urbw/pzE3LDA6GpIts6TVyzgftLLEfU2BzQsjp0CIQDo+sn8t7XC6JN4KKRr2ABl
|
||||
ZI+JifgG+2KCy9ln2LxGJQ==
|
||||
-----END CERTIFICATE-----
|
14
vendor/github.com/cloudflare/cfssl/helpers/testdata/cert_pkcs7.pem
generated
vendored
Normal file
14
vendor/github.com/cloudflare/cfssl/helpers/testdata/cert_pkcs7.pem
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
-----BEGIN PKCS7-----
|
||||
MIICHQYJKoZIhvcNAQcCoIICDjCCAgoCAQExADALBgkqhkiG9w0BBwGgggHwMIIB
|
||||
7DCCAZKgAwIBAgIIE/Qz49ebG7kwCgYIKoZIzj0EAwIwTDELMAkGA1UEBhMCVVMx
|
||||
EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEDAO
|
||||
BgNVBAoTB2FjbWUuY28wHhcNMTcwNTIzMTk1MTQ0WhcNMTcwODIzMDE1NjQ0WjBM
|
||||
MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2Fu
|
||||
IEZyYW5jaXNjbzEQMA4GA1UEChMHYWNtZS5jbzBZMBMGByqGSM49AgEGCCqGSM49
|
||||
AwEHA0IABEW8F+k/avvdBm/KRsuDnTZ3p+VuVdsqDF+aD9nIYeOhx5sj574yhEIZ
|
||||
OpgbEsi3BvqY63y2jYyPFodf25+CA9GjXjBcMA4GA1UdDwEB/wQEAwIFoDAdBgNV
|
||||
HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4E
|
||||
FgQUzDpu+HN89EC1M8aNl7f0Ln5JnnIwCgYIKoZIzj0EAwIDSAAwRQIgC4/rurbw
|
||||
/pzE3LDA6GpIts6TVyzgftLLEfU2BzQsjp0CIQDo+sn8t7XC6JN4KKRr2ABlZI+J
|
||||
ifgG+2KCy9ln2LxGJaEAMQA=
|
||||
-----END PKCS7-----
|
15
vendor/github.com/cloudflare/cfssl/helpers/testdata/cert_with_whitespace.pem
generated
vendored
Normal file
15
vendor/github.com/cloudflare/cfssl/helpers/testdata/cert_with_whitespace.pem
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB7DCCAZKgAwIBAgIIE/Qz49ebG7kwCgYIKoZIzj0EAwIwTDELMAkGA1UEBhMC
|
||||
VVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x
|
||||
EDAOBgNVBAoTB2FjbWUuY28wHhcNMTcwNTIzMTk1MTQ0WhcNMTcwODIzMDE1NjQ0
|
||||
WjBMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN
|
||||
U2FuIEZyYW5jaXNjbzEQMA4GA1UEChMHYWNtZS5jbzBZMBMGByqGSM49AgEGCCqG
|
||||
SM49AwEHA0IABEW8F+k/avvdBm/KRsuDnTZ3p+VuVdsqDF+aD9nIYeOhx5sj574y
|
||||
hEIZOpgbEsi3BvqY63y2jYyPFodf25+CA9GjXjBcMA4GA1UdDwEB/wQEAwIFoDAd
|
||||
BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNV
|
||||
HQ4EFgQUzDpu+HN89EC1M8aNl7f0Ln5JnnIwCgYIKoZIzj0EAwIDSAAwRQIgC4/r
|
||||
urbw/pzE3LDA6GpIts6TVyzgftLLEfU2BzQsjp0CIQDo+sn8t7XC6JN4KKRr2ABl
|
||||
ZI+JifgG+2KCy9ln2LxGJQ==
|
||||
-----END CERTIFICATE-----
|
||||
|
11
vendor/github.com/cloudflare/cfssl/helpers/testdata/ecdsa256.csr
generated
vendored
Normal file
11
vendor/github.com/cloudflare/cfssl/helpers/testdata/ecdsa256.csr
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBgTCCASgCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
|
||||
LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBn9Ldie6BOcMHezn2dPuYqW
|
||||
z/NoLYMLGNBqhOxUyEidYClI0JW2pWyUgT3A2UazFp1WgE94y7Z+2YlfRz+vcrKg
|
||||
PzA9BgkqhkiG9w0BCQ4xMDAuMCwGA1UdEQQlMCOCDmNsb3VkZmxhcmUuY29tghF3
|
||||
d3djbG91ZGZsYXJlLmNvbTAKBggqhkjOPQQDAgNHADBEAiBM+QRxe8u6rkdr10Jy
|
||||
cxbR6NxrGrNeg5QqiOqF96JEmgIgDbtjd5e3y3I8W/+ih2us3WtMxgnTXfqPd48i
|
||||
VLcv28Q=
|
||||
-----END CERTIFICATE REQUEST-----
|
1
vendor/github.com/cloudflare/cfssl/helpers/testdata/empty.pem
generated
vendored
Normal file
1
vendor/github.com/cloudflare/cfssl/helpers/testdata/empty.pem
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
|
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/empty_pkcs7.der
generated
vendored
Normal file
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/empty_pkcs7.der
generated
vendored
Normal file
Binary file not shown.
3
vendor/github.com/cloudflare/cfssl/helpers/testdata/empty_pkcs7.pem
generated
vendored
Normal file
3
vendor/github.com/cloudflare/cfssl/helpers/testdata/empty_pkcs7.pem
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN PKCS7-----
|
||||
MCcGCSqGSIb3DQEHAqAaMBgCAQExADALBgkqhkiG9w0BBwGgAKEAMQA=
|
||||
-----END PKCS7-----
|
2
vendor/github.com/cloudflare/cfssl/helpers/testdata/emptycert.pem
generated
vendored
Normal file
2
vendor/github.com/cloudflare/cfssl/helpers/testdata/emptycert.pem
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
-----END CERTIFICATE-----LSKFSKLF
|
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/emptypasswordpkcs12.p12
generated
vendored
Normal file
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/emptypasswordpkcs12.p12
generated
vendored
Normal file
Binary file not shown.
30
vendor/github.com/cloudflare/cfssl/helpers/testdata/enc_priv_key.pem
generated
vendored
Normal file
30
vendor/github.com/cloudflare/cfssl/helpers/testdata/enc_priv_key.pem
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,90B8A5792FA2FE75B2053582F3DF394F
|
||||
|
||||
yVY2xuth5fdJBg9gg+6eP3qTsr0CJ2mGEDW6rvYmYuATSRF1hVERrsznxJYjYLaw
|
||||
JHec8FVr78y4aXxI/aFzlxLkS8f12WjTtIhzHwhzgSJDwVOXSRphnLAeHWnhEKLe
|
||||
7kO+vzoTPIc3ECwdvtr6//z2tP1/sac+yIhL6C+x2rS5hFHhmDUXtILPxxfHJCiM
|
||||
qtKiiOZz3W6008CeJMC9ZPlKHDvpq7aIL4rfVP/GkZ+/teQkgWNpMxac7+gWLKuK
|
||||
109v6pu+8KT49D6SMsaZPvAb5PXcIB79ZCPI1JX0V26CKcswba4RHG/h1xifwyAF
|
||||
OIvmK29mmFqbx5GPlUefRUuPwRJKCXFiK6LTdhCwLYodtXde4ibvOFYy4onGoVax
|
||||
I5WVaOhQMqp+mxA6z7odrIvuFcQGixIA+peaaSbpNZSZGuxRvVefcdxPbJ+26Ijs
|
||||
wq8uyalbwhKtjPTPNkMaaYzJdWS7wd2DS4RM9JT8Y1h6NTftCY3c+/txOlt5pQzW
|
||||
T8n+NTd4o+PFOHzMnmEnrtf9Y/SSzXDB2OPCD95YdIXItQDdKcjK0NmnY8GNfkWL
|
||||
G30NJNy3/DR7Sa5u4xuqNgcgTFhgZaOQ1IVB3p5VjknqAX3gWFu2DrqzbH45071A
|
||||
He7VbdbzBpMHI2EdiCVOuK9fD/5sv25u9vVC2NHtG/YcoEQv+RB52TNHn9kdiMj1
|
||||
gLaywPqGjFmaPxI0xX07BrL+D9RruUT1GAEyw4JAHuJZIyq3+V98wmV/pEqwc7hp
|
||||
8WuSi6YddetfF4NPA5cGWt8qZ1it+wD/1ydQEAQsxdANqi0XVudYpYox02EoRS02
|
||||
up0sd9zqz83pN9RyOOKtGcHdt85gb9DYRVeff1UszMaoVULxqxYetwtzpiHn6grL
|
||||
DmnSk+DYgvXKOVt8tmSJysDTumhK1VN3xb34TYYJxeBOQJLzWFjGSELEpphZAQSj
|
||||
rS4OM1FwoP48wvASGiWD4VUJ6v+6F+NDvJr01S+zWGLg1EeUZJmXGHW5GrGd4Kgx
|
||||
3rdeOsrED9oXKp2cpgx9avXJ9upixja9MbAPp7RkSyeHMPvsuaI44xvOP3f0crmG
|
||||
d/5CdBKVT7nFaeTGSx/78kHb3VJyopAMm9k0V3CheKwBXXSbXmV1+0muBxMHsEI3
|
||||
aEKaI0y5cDfTewzo/U0l0kGtxF6kUPN1pdjFpAvssRlkGttFOC2nWxHwaNHpn7Kq
|
||||
gFAlN6P4cyB6kb+LvckIYTZ/tV39dx7PfL0KG5TWjJ4a9GSoL1IrAhQq+Qv6oUEt
|
||||
1vlejZoKyZ/35fni0fmeYNho+pCPimm6l+sHTuXkrWgGLr0S9O00HFLz11D7R4o9
|
||||
7mF4JkMNztT+ENOdT4xQBi3OGjRGMwtE6PsQPfDeu13Vq6eDtdEGUdhW1kAsGnBi
|
||||
eJRuysnGpnoWofJ7yS0+DhnS4GAVi907TMrQWwmez9V4CXl4NBc8X9T69TFL2LsW
|
||||
2KU9NUXdiCRZqZHD41gd3+RuRA/oXh50V9oaow+uepwYKTFyzde5IH1/DgBd7tOd
|
||||
Fa2fM5/zSA0uFPRb3yCVhRg5d6J9t5yaPAz7Jp0D1mDDGsMBD1O/FYJvWoANEwUX
|
||||
-----END RSA PRIVATE KEY-----
|
48
vendor/github.com/cloudflare/cfssl/helpers/testdata/messed_up_bundle.pem
generated
vendored
Normal file
48
vendor/github.com/cloudflare/cfssl/helpers/testdata/messed_up_bundle.pem
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEczCCAl2gAwIBAgIIDARj8BWNsscwCwYJKoZIhvcNAQELMIGMMQswCQYDVQQG
|
||||
EwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UECxMTU3lzdGVtcyBFbmdp
|
||||
bmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZv
|
||||
cm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5jb20wHhcNMTQwMzAyMDAw
|
||||
MDAwWhcNMTkwNDAxMDAwMDAwWjCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkNs
|
||||
b3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5lZXJpbmcxFjAUBgNVBAcT
|
||||
FHsHEDAfBgNVHREEGDAWghRjbG91ZGZsYXJlLWludGVyLmNvbTALBgkqhkiG9w0B
|
||||
AQsDggIBACRqAC5EJEe+8ihv1WzCUMEMb7KtS0BqoNbdXE32ia66PgJSQmHcmeJd
|
||||
FI1UjL0DlljTM2tc+8KxR/1/qnKiI+W/D4wFTWOY/JWFOd15q7lXuKGl+8PMkAHF
|
||||
A145JCr6oZoO9G9wUwVUrbmXAbyPCOfzsEQ2+mD9F1ZpoEjzVhtGf0R+vnYrRw8j
|
||||
4WCv5AIcYRAf7HZxbhMILF1bccNlqyUtdH+/MTHXpjkjJjA5KbsHBrAEfjAXkD7c
|
||||
WWOay6m7mVWb3PPFmGorP6t29baEETK9ZTZSrfD9rnExjjUCftWJEn0M4Pp98DvT
|
||||
br6+bg8jwtq73qdyOfNsC/Sod18UuHH7MTQA22yqAF5jIlcYtAHGlNnl+sDPZACs
|
||||
369/Z9rOL9vPFL+Z3F/uJtqZzvN1QiCkj8jWzR0u9fh3eQwZADM2RwgwS4Gs2Ygh
|
||||
PsypDo33sFOwfX93KqKBsTHssn8SSDDaSnZ8bu1ATEdshbVieecuQx40UadPuJpw
|
||||
EPVqTR5AhviXQ9bKrTnU5T7EgkW9vNydkpLQQlMg3QE8hsndv4loGZbZGfNtqQHS
|
||||
/mg1t07S+7OEa4YaMW+wVOBOqTdW7OXlZFLfCcF5SYLM0SnlTMklRMxiqI4JqZXH
|
||||
0thnUGD0JjfLX4rTaZUzT3lrXXWzpS2jzutXQkjGv4nhGGprIDuT
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEkDCCA/ugAwIBAgIIWnP9jF/2nogwCwYJKoZIhvcNAQELMH0xCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2Nv
|
||||
MRMwEQYDVQQKDApDbG91ZEZsYXJlMRQwEgYDVQQLDAtERVZfVEVTVElORzEWMBQG
|
||||
A1UEAwwNQ0ZTU0xfVEVTVF9DQTAeFw0xNDAzMDEwMDAwMDBaFw0xNDA0MTUwMDAw
|
||||
MDBaMIGMMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQ2xvdWRGbGFyZTEcMBoGA1UE
|
||||
CxMTU3lzdGVtcyBFbmdpbmVlcmluZzEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzET
|
||||
MBEGA1UECBMKQ2FsaWZvcm5pYTEdMBsGA1UEAxMUY2xvdWRmbGFyZS1pbnRlci5j
|
||||
b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDlCnV+vj0sVPy8SqHL
|
||||
AlI+xwnPhWgzj2VevD6Nz1Zu1BeQ5m5y4CWCf+GmRGTP7+a/C510Fw6rpmInB0Ng
|
||||
xxwQ2rC08fJtCnijlGH/VjEPIHY5lRaAomcM8Rgx6JOuv9BpZJKpr9pyUMV53JeW
|
||||
RbWuLH5nEMdyk9NpetS2gWxt4/D20QlhK/tHkROrcLmEUddwIGdwE8JzI88c77Fu
|
||||
u6pgMtHKvl4GGH0yvb4T7PvCdH8V2tCH7bt8roXd9MSyFVy7uORkfouip7EsVREU
|
||||
mlcY5EvpR141KXbZqiOQiusJ+u76mEUQNk8wCR1/CW/ii9v1BKOVjXwCfEtIXjg0
|
||||
APJx1VNSSH6XoDpUETL+eQ4J0FL9XNbsDuYar7+zD0N1/5vSo3HLNRQR9f0lbsys
|
||||
sWBEN+CxK19xyPumr21Z0bU0f1B5H52VSF0q3I1Ju9wRo994a7YipdGcmZ2lChmT
|
||||
7r3mzlBTYl3poU26q34v8wG9U7Jv4fsZJ+RGebDI+TR3QG6Yod06l9oEYZxWXBY7
|
||||
STOs8wuTu3huSnan/IpWnV017Vsc61D5G+QrqcxZdXckt3anZKCF75JpUnJ7vuow
|
||||
TmmHlb8KIMa9mOvcuGX4P6mz8gTi2arl/aL27kj9Q0Jgv/y1ebe2Bx2P9TF6+VND
|
||||
DL3J/vSVlFeqLt2reAIBKnytLwIDAQABo4GIMIGFMA4GA1UdDwEB/wQEAwIApDAS
|
||||
BgNVHRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBTXXUgpaSwO9HOrQBxGqOOSFHsH
|
||||
EDAfBgNVHSMEGDAWgBS4Xu+uZ1C31vMH5Wq+VbNnOg2SPjAfBgNVHREEGDAWghRj
|
||||
bG91ZGZsYXJlLWludGVyLmNvbTALBgkqhkiG9w0BAQsDgYEAfPLKCAHnPzgMYLX/
|
||||
fWznVvOEFAAYZByPFx4QdMBbDZUtxHyvJIBs6PdxrdSuDwSiMqE7qQIi+jzzwGl9
|
||||
fC7vf45B2zCX0OW51QL2oWNBdKlGgB+b2pwyME82lX/Pr7V1GY10u+ep1xdZDnch
|
||||
DaMsXjQQTJu0iuG3qKEuCmUwOmc=
|
||||
-----END CERTIFICATE-----
|
||||
SDFSDKjkfdlsdfj
|
20
vendor/github.com/cloudflare/cfssl/helpers/testdata/messed_up_priv_key.pem
generated
vendored
Normal file
20
vendor/github.com/cloudflare/cfssl/helpers/testdata/messed_up_priv_key.pem
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAvGKyz9ZzIXI/BFrtqbVQMmKQkPZGndyfV3AzeSb2ulbS/s5k
|
||||
yNJMH/jKZiSCvZiJNnW+JNlJrgLxORMmPStPz/N/0L0vCTotQKZUiaBttFgHgobQ
|
||||
LFsbMnumt9It5W/uOwgWI9binuzvqyPXywLlYwOq3jkOmA22ymhflzRrl6a3jzcY
|
||||
hT9evxHl0gV4bN7KZ5p4wK/UUuG1uMEQLw87lUwRRHeW3ZG52VL38+redka+f5pa
|
||||
SGKyG5j0oe1NPLqAjckNgqvDdPMY2gicmCq0VSLzTNpHRsURTUSJvC/iv34vVfba
|
||||
gIYgTvm8BvGbJSlZqP4kEVlOfd3vmB0ttUeoDwIDAQABAoIBAHZdpXCFlA1d1U6N
|
||||
O2s4a01dNOyAcVpa9xtfelgTLU9jomtLj3PG/uHP1oxbQHKUVxKK5JAOnwbg/mQY
|
||||
LhydDCbjHlovpFAt56UJXXCkBoocDYvr3P0huXL80oIJY6EXtR4ONKsMJ5Qn12c2
|
||||
vC3ogey2rzO1sf/EDigbcIR3AWtk1Tx8ZDUooktOFypIsDQgjjxXiURGssAlMPSh
|
||||
6GVgO4JRRG6oRxEna7yDe7izmh/hC5sxSYLsEikCgYEAsBHhb/Qef5obRCSrfFuQ
|
||||
41P7MCtGrXVxKD3iCDGQCzVbEbYGpmZnGsXSaHljp2FtnamaGGEudYziozGKPHjs
|
||||
pbTbsLIDbmNwxz1WcaZ1iyIjtOxcAEqDod8hY4hL6SaxypwTHn4Ydbw2NGzp11Eg
|
||||
Di4SVL82utjycATdKFvBzdsCgYB/3M+GMrt0Sh87rKcQLdL709Kzjcfhvm4HjIbJ
|
||||
GSXGPCZaYMKaXRTdNAjtRKxMawc9qcf0xSBEHL0GkB158TzusDQtjP1anTcYOnl6
|
||||
GsO4bRivp314iNlP4r3S3bIXqBxCGH3HbrvpdPFAN//qjYmAki2lFQZywfvbQOE8
|
||||
oFQHwQKBgHqJkTck2DGlXQIwA7jirLggISXjSPlsG4w4LuhY9ivyNKLUi4x5k1cE
|
||||
bX7SrRtJErQ1WaDN4TFG25xnysi5h+aPinuySatd0XmA5+dE1YjTqqShMO+lUpzi
|
||||
PrOQl6Eva/uw5BDAcUH4AaXTNRvvtXQptUil9qXyOh6fszikA9Mm
|
||||
-----END RSA PRIVATE KEY-----
|
11
vendor/github.com/cloudflare/cfssl/helpers/testdata/messedupcert.pem
generated
vendored
Normal file
11
vendor/github.com/cloudflare/cfssl/helpers/testdata/messedupcert.pem
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB7jCCAVmgAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
|
||||
bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTEyMDkwNzIyMDAwNFoXDTEzMDkwNzIy
|
||||
MDUwNFowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGd
|
||||
MAsGCSqGSIb3DQEBAQOBjQAwgYkCgYEAm6f+jkP2t5q/vM0YAUZZkhq/EAYD+L1C
|
||||
cqhEvLFbu3MCAwEAAaMyMDAwDgYDVR0PAQH/BAQDAgCgMA0GA1UdDgQGBAQBAgME
|
||||
MA8GA1UdIwQIMAaABAECAwQwCwYJKoZIhvcNAQEFA4GBABndWRIcfi+QB9Sakr+m
|
||||
dYnXTgYCnFio53L2Z+6EHTGG+rEhWtUEGhL4p4pzXX4siAnjWvwcgXTo92cafcfi
|
||||
uB7wRfK+NL9CTJdpN6cdL+fiNHzH8hsl3bj1nL0CSmdn2hkUWVLbLhSgWlib/I8O
|
||||
aq+K7aVrgHkPnWeRiG6tl+ZA
|
||||
-----END CERTIFICATE-----
|
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/multiplecerts.p12
generated
vendored
Normal file
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/multiplecerts.p12
generated
vendored
Normal file
Binary file not shown.
9
vendor/github.com/cloudflare/cfssl/helpers/testdata/noheadercert.pem
generated
vendored
Normal file
9
vendor/github.com/cloudflare/cfssl/helpers/testdata/noheadercert.pem
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
MIIB7jCCAVmgAwIBAgIBADALBgkqhkiG9w0BAQUwJjEQMA4GA1UEChMHQWNtZSBD
|
||||
bzESMBAGA1UEAxMJMTI3LjAuMC4xMB4XDTEyMDkwNzIyMDAwNFoXDTEzMDkwNzIy
|
||||
MDUwNFowJjEQMA4GA1UEChMHQWNtZSBDbzESMBAGA1UEAxMJMTI3LjAuMC4xMIGd
|
||||
MAsGCSqGSIb3DQEBAQOBjQAwgYkCgYEAm6f+jkP2t5q/vM0YAUZZkhq/EAYD+L1C
|
||||
cqhEvLFbu3MCAwEAAaMyMDAwDgYDVR0PAQH/BAQDAgCgMA0GA1UdDgQGBAQBAgME
|
||||
MA8GA1UdIwQIMAaABAECAwQwCwYJKoZIhvcNAQEFA4GBABndWRIcfi+QB9Sakr+m
|
||||
dYnXTgYCnFio53L2Z+6EHTGG+rEhWtUEGhL4p4pzXX4siAnjWvwcgXTo92cafcfi
|
||||
uB7wRfK+NL9CTJdpN6cdL+fiNHzH8hsl3bj1nL0CSmdn2hkUWVLbLhSgWlib/I8O
|
||||
aq+K7aVrgHkPnWeRiG6tl+ZA
|
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/passwordpkcs12.p12
generated
vendored
Normal file
BIN
vendor/github.com/cloudflare/cfssl/helpers/testdata/passwordpkcs12.p12
generated
vendored
Normal file
Binary file not shown.
28
vendor/github.com/cloudflare/cfssl/helpers/testdata/priv_rsa_key.pem
generated
vendored
Normal file
28
vendor/github.com/cloudflare/cfssl/helpers/testdata/priv_rsa_key.pem
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAvGKyz9ZzIXI/BFrtqbVQMmKQkPZGndyfV3AzeSb2ulbS/s5k
|
||||
yNJMH/jKZiSCvZiJNnW+JNlJrgLxORMmPStPz/N/0L0vCTotQKZUiaBttFgHgobQ
|
||||
LFsbMnumt9It5W/uOwgWI9binuzvqyPXywLlYwOq3jkOmA22ymhflzRrl6a3jzcY
|
||||
hT9evxHl0gV4bN7KZ5p4wK/UUuG1uMEQLw87lUwRRHeW3ZG52VL38+redka+f5pa
|
||||
SGKyG5j0oe1NPLqAjckNgqvDdPMY2gicmCq0VSLzTNpHRsURTUSJvC/iv34vVfba
|
||||
gIYgTvm8BvGbJSlZqP4kEVlOfd3vmB0ttUeoDwIDAQABAoIBAHZdpXCFlA1d1U6N
|
||||
O2s4a01dNOyAcVpa9xtfelgTLU9jomtLj3PG/uHP1oxbQHKUVxKK5JAOnwbg/mQY
|
||||
LhydDCbjHlovpFAt56UJXXCkBoocDYvr3P0huXL80oIJY6EXtR4ONKsMJ5Qn12c2
|
||||
vC3ogey2rzO1sf/EDigbcIR3AWtk1Tx8ZDUooktOFypIsDQgjjxXiURGssAlMPSh
|
||||
1BFz4StRUK4bESaja0GiHwbuxHa+XYEBlK5OqMo/fpWqpgHhV/42+7wdcBMJsMr8
|
||||
rFBe6m+r6TTbLSGJNowyd05XrjoAI35qduckpJ3Voun90i4ynTudjdJ/vHpIqB74
|
||||
qQLFW2ECgYEA+GSRVqobaKKakNUFGmK0I5T5Tikz5f137YXXER6aLtDQNiSrlXNi
|
||||
0aphkC/EfRO3oNvamq5+55bmmgDVoNNPDfpajKz+LZyG8GC2EXlTKO0hZS64KRRl
|
||||
C+bd+ZsYiUDImNVRbIHN82f+BQgsgXlTaWpBOrEqmoePO/J44O4eX3cCgYEAwieq
|
||||
amY4UaY+MhWPJFRK1y9M3hM8+N9N/35CFewQUdFJosC6vVQ4t8jNkSOxVQdgbNwE
|
||||
i/bTBgIwg82JJYbBUPuCVeTT3i6zxymf/FLumrI73URD81IN6FiH1skg0hSFrvs0
|
||||
6GVgO4JRRG6oRxEna7yDe7izmh/hC5sxSYLsEikCgYEAsBHhb/Qef5obRCSrfFuQ
|
||||
41P7MCtGrXVxKD3iCDGQCzVbEbYGpmZnGsXSaHljp2FtnamaGGEudYziozGKPHjs
|
||||
pbTbsLIDbmNwxz1WcaZ1iyIjtOxcAEqDod8hY4hL6SaxypwTHn4Ydbw2NGzp11Eg
|
||||
Di4SVL82utjycATdKFvBzdsCgYB/3M+GMrt0Sh87rKcQLdL709Kzjcfhvm4HjIbJ
|
||||
GSXGPCZaYMKaXRTdNAjtRKxMawc9qcf0xSBEHL0GkB158TzusDQtjP1anTcYOnl6
|
||||
GsO4bRivp314iNlP4r3S3bIXqBxCGH3HbrvpdPFAN//qjYmAki2lFQZywfvbQOE8
|
||||
oFQHwQKBgHqJkTck2DGlXQIwA7jirLggISXjSPlsG4w4LuhY9ivyNKLUi4x5k1cE
|
||||
bX7SrRtJErQ1WaDN4TFG25xnysi5h+aPinuySatd0XmA5+dE1YjTqqShMO+lUpzi
|
||||
PrOQl6Eva/uw5BDAcUH4AaXTNRvvtXQptUil9qXyOh6fszikA9Mm
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
5
vendor/github.com/cloudflare/cfssl/helpers/testdata/private_ecdsa_key.pem
generated
vendored
Normal file
5
vendor/github.com/cloudflare/cfssl/helpers/testdata/private_ecdsa_key.pem
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MGgCAQEEHCGXsrNo2xfy8+zd4Pzj8rcQ5KqQO43au1t/7nugBwYFK4EEACGhPAM6
|
||||
AASJodCTtj5aYXnWxMiYhwjEgNQJJbNzJFEbsGJX9pCWZC673ammTWFHMjnMPkS/
|
||||
9eU5YeW40BHqfw==
|
||||
-----END EC PRIVATE KEY-----
|
19
vendor/github.com/cloudflare/cfssl/helpers/testdata/rsa-old.csr
generated
vendored
Normal file
19
vendor/github.com/cloudflare/cfssl/helpers/testdata/rsa-old.csr
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN NEW CERTIFICATE REQUEST-----
|
||||
MIIDCTCCAfMCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
|
||||
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTWdoYxX4KN51fP
|
||||
WxQAyGH++VsPbfpAoXIbCPXSmU04BvIxyjzpHQ0ChMKkT/2VNcUeFJwk2fCf+ZwU
|
||||
f0raTQTplofwkckE0gEYA3WcEfJp+hbvbTb/2recsf+JE6JACYJe2Uu5wsjtrE5j
|
||||
A+7aT2BEU9RWzBdSy/5281ZfW3PArqcWaf8+RUyA3WRxVWmjmhFsVB+mdNLhCpW0
|
||||
C0QNMYR1ppEZiKVnEdao8gcI5sOvSd+35t8g82aPXcNSPU6jKcx1YNUPX5wgPEmu
|
||||
+anfc9RliQbYqqJYVODgBmV8IR5grw93yTsODoWKtFQ4PKVlnt9CD8AS/iSMQYm3
|
||||
OUogqgMCAwEAAaA/MD0GCSqGSIb3DQEJDjEwMC4wLAYDVR0RBCUwI4IOY2xvdWRm
|
||||
bGFyZS5jb22CEXd3d2Nsb3VkZmxhcmUuY29tMAsGCSqGSIb3DQEBCwOCAQEAl809
|
||||
gk9uZkRK+MJVYDSLjgGR2xqk5qOwnhovnispA7N3Z1GshodJRQa6ngNCKuXIm2/6
|
||||
AxB9kDGK14n186Qq4odXqHSHs8FG9i0zUcBXeLv1rPAKtwKTas/SLmsOpPgWPZFa
|
||||
iYiHHeu4HjOQoF987d7uGRYwc3xfstKwJsEXc12eCw2NH8TM1tJgSc/o6CzIpA91
|
||||
QnZKhx6uGM4xI2gnOaJA1YikNhyFGBuOGMZgd0k2+/IcR2pg0z4pc5oQw1bXLANx
|
||||
anqlA/MDrCM9v9019bRJ73zK8LQ3k/FW61PA9nL7RZ8ku65R+uYcVEdLa8pUeqnH
|
||||
cJZNboDRsItpccZuRQ==
|
||||
-----END NEW CERTIFICATE REQUEST-----
|
5
vendor/github.com/cloudflare/cfssl/helpers/testdata/secp256k1-key.pem
generated
vendored
Normal file
5
vendor/github.com/cloudflare/cfssl/helpers/testdata/secp256k1-key.pem
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHQCAQEEIJLKycmoCAk4HqlJGdsuFyHsxfIheKsLH91tS/TNP5OOoAcGBSuBBAAK
|
||||
oUQDQgAEBkmL7cvC2cgchzfSuUZPGnzH0FqBtf3kGhSllQiIzGDn4envPXNqp+93
|
||||
V2NZ8VT+Aba4ln2Vbp9gYrKquut5Zg==
|
||||
-----END EC PRIVATE KEY-----
|
15
vendor/github.com/cloudflare/cfssl/helpers/testdata/test.bad.csr.pem
generated
vendored
Normal file
15
vendor/github.com/cloudflare/cfssl/helpers/testdata/test.bad.csr.pem
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICzDCCAbQCAQAwgYYxCzAJBgNVBAYTAkVOMQ0wCwYDVQQIDARub25lMQ0wCwYD
|
||||
VQQHDARub25lMRIwEAYDVQQKDAlXaWtpcGVkaWExDTALBgNVBAsMBG5vbmUxGDAW
|
||||
BgNVBAMMDyoud2lraXBlZGlhLm9yZzEcMBoGCSqGSIb3DQEJARYNbm9uZUBub25l
|
||||
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMP/U8RlcCD6E8AL
|
||||
PT8LLUR9ygyygPCaSmIEC8zXGJung3ykElXFRz/Jc/bu0hxCxi2YDz5IjxBBOpB/
|
||||
kieG83HsSmZZtR+drZIQ6vOsr/ucvpnB9z4XzKuabNGZ5ZiTSQ9L7Mx8FzvUTq5y
|
||||
57HhA7ECAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4IBAQBn8OCVOIx+n0AS6WbEmYDR
|
||||
SspR9xOCoOwYfamB+2Bpmt82R01zJ/kaqzUtZUjaGvQvAaz5lUwoMdaO0X7I5Xfl
|
||||
sllMFDaYoGD4Rru4s8gz2qG/QHWA8uPXzJVAj6X0olbIdLTEqTKsnBj4Zr1AJCNy
|
||||
/YcG4ouLJr140o26MhwBpoCRpPjAgdYMH60BYfnc4/DILxMVqR9xqK1s98d6Ob/+
|
||||
3wHFK+S7BRWrJQXcM8veAexXuk9lHQ+FgGfD0eSYGz0kyP26Qa2pLTwumjt+nBPl
|
||||
rfJxaLHwTQ/1988G0H35ED0f9Md5fzoKi5evU1wG5WRxdEUPyt3QUXxdQ69i0C+7
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
18
vendor/github.com/cloudflare/cfssl/helpers/testdata/test.csr.pem
generated
vendored
Normal file
18
vendor/github.com/cloudflare/cfssl/helpers/testdata/test.csr.pem
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICzDCCAbQCAQAwgYYxCzAJBgNVBAYTAkVOMQ0wCwYDVQQIDARub25lMQ0wCwYD
|
||||
VQQHDARub25lMRIwEAYDVQQKDAlXaWtpcGVkaWExDTALBgNVBAsMBG5vbmUxGDAW
|
||||
BgNVBAMMDyoud2lraXBlZGlhLm9yZzEcMBoGCSqGSIb3DQEJARYNbm9uZUBub25l
|
||||
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMP/U8RlcCD6E8AL
|
||||
PT8LLUR9ygyygPCaSmIEC8zXGJung3ykElXFRz/Jc/bu0hxCxi2YDz5IjxBBOpB/
|
||||
kieG83HsSmZZtR+drZIQ6vOsr/ucvpnB9z4XzKuabNGZ5ZiTSQ9L7Mx8FzvUTq5y
|
||||
/ArIuM+FBeuno/IV8zvwAe/VRa8i0QjFXT9vBBp35aeatdnJ2ds50yKCsHHcjvtr
|
||||
9/8zPVqqmhl2XFS3Qdqlsprzbgksom67OobJGjaV+fNHNQ0o/rzP//Pl3i7vvaEG
|
||||
7Ff8tQhEwR9nJUR1T6Z7ln7S6cOr23YozgWVkEJ/dSr6LAopb+cZ88FzW5NszU6i
|
||||
57HhA7ECAwEAAaAAMA0GCSqGSIb3DQEBBAUAA4IBAQBn8OCVOIx+n0AS6WbEmYDR
|
||||
SspR9xOCoOwYfamB+2Bpmt82R01zJ/kaqzUtZUjaGvQvAaz5lUwoMdaO0X7I5Xfl
|
||||
sllMFDaYoGD4Rru4s8gz2qG/QHWA8uPXzJVAj6X0olbIdLTEqTKsnBj4Zr1AJCNy
|
||||
/YcG4ouLJr140o26MhwBpoCRpPjAgdYMH60BYfnc4/DILxMVqR9xqK1s98d6Ob/+
|
||||
3wHFK+S7BRWrJQXcM8veAexXuk9lHQ+FgGfD0eSYGz0kyP26Qa2pLTwumjt+nBPl
|
||||
rfJxaLHwTQ/1988G0H35ED0f9Md5fzoKi5evU1wG5WRxdEUPyt3QUXxdQ69i0C+7
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
|
15
vendor/github.com/cloudflare/cfssl/info/info.go
generated
vendored
Normal file
15
vendor/github.com/cloudflare/cfssl/info/info.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// Package info contains the definitions for the info endpoint
|
||||
package info
|
||||
|
||||
// Req is the request struct for an info API request.
|
||||
type Req struct {
|
||||
Label string `json:"label"`
|
||||
Profile string `json:"profile"`
|
||||
}
|
||||
|
||||
// Resp is the response for an Info API request.
|
||||
type Resp struct {
|
||||
Certificate string `json:"certificate"`
|
||||
Usage []string `json:"usages"`
|
||||
ExpiryString string `json:"expiry"`
|
||||
}
|
249
vendor/github.com/cloudflare/cfssl/initca/initca.go
generated
vendored
Normal file
249
vendor/github.com/cloudflare/cfssl/initca/initca.go
generated
vendored
Normal file
@ -0,0 +1,249 @@
|
||||
// Package initca contains code to initialise a certificate authority,
|
||||
// generating a new root key and certificate.
|
||||
package initca
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cfssl/config"
|
||||
"github.com/cloudflare/cfssl/csr"
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/cloudflare/cfssl/signer/local"
|
||||
)
|
||||
|
||||
// validator contains the default validation logic for certificate
|
||||
// authority certificates. The only requirement here is that the
|
||||
// certificate have a non-empty subject field.
|
||||
func validator(req *csr.CertificateRequest) error {
|
||||
if req.CN != "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(req.Names) == 0 {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing subject information"))
|
||||
}
|
||||
|
||||
for i := range req.Names {
|
||||
if csr.IsNameEmpty(req.Names[i]) {
|
||||
return cferr.Wrap(cferr.PolicyError, cferr.InvalidRequest, errors.New("missing subject information"))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// New creates a new root certificate from the certificate request.
|
||||
func New(req *csr.CertificateRequest) (cert, csrPEM, key []byte, err error) {
|
||||
policy := CAPolicy()
|
||||
if req.CA != nil {
|
||||
if req.CA.Expiry != "" {
|
||||
policy.Default.ExpiryString = req.CA.Expiry
|
||||
policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if req.CA.Backdate != "" {
|
||||
policy.Default.Backdate, err = time.ParseDuration(req.CA.Backdate)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
|
||||
if req.CA.PathLength != 0 && req.CA.PathLenZero {
|
||||
log.Infof("ignore invalid 'pathlenzero' value")
|
||||
} else {
|
||||
policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
|
||||
}
|
||||
}
|
||||
|
||||
g := &csr.Generator{Validator: validator}
|
||||
csrPEM, key, err = g.ProcessRequest(req)
|
||||
if err != nil {
|
||||
log.Errorf("failed to process request: %v", err)
|
||||
key = nil
|
||||
return
|
||||
}
|
||||
|
||||
priv, err := helpers.ParsePrivateKeyPEM(key)
|
||||
if err != nil {
|
||||
log.Errorf("failed to parse private key: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy)
|
||||
if err != nil {
|
||||
log.Errorf("failed to create signer: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
signReq := signer.SignRequest{Hosts: req.Hosts, Request: string(csrPEM)}
|
||||
cert, err = s.Sign(signReq)
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// NewFromPEM creates a new root certificate from the key file passed in.
|
||||
func NewFromPEM(req *csr.CertificateRequest, keyFile string) (cert, csrPEM []byte, err error) {
|
||||
privData, err := helpers.ReadBytes(keyFile)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
priv, err := helpers.ParsePrivateKeyPEM(privData)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return NewFromSigner(req, priv)
|
||||
}
|
||||
|
||||
// RenewFromPEM re-creates a root certificate from the CA cert and key
|
||||
// files. The resulting root certificate will have the input CA certificate
|
||||
// as the template and have the same expiry length. E.g. the existing CA
|
||||
// is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate
|
||||
// will be valid from now and expire in one year as well.
|
||||
func RenewFromPEM(caFile, keyFile string) ([]byte, error) {
|
||||
caBytes, err := helpers.ReadBytes(caFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ca, err := helpers.ParseCertificatePEM(caBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
keyBytes, err := helpers.ReadBytes(keyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := helpers.ParsePrivateKeyPEM(keyBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return RenewFromSigner(ca, key)
|
||||
}
|
||||
|
||||
// NewFromSigner creates a new root certificate from a crypto.Signer.
|
||||
func NewFromSigner(req *csr.CertificateRequest, priv crypto.Signer) (cert, csrPEM []byte, err error) {
|
||||
policy := CAPolicy()
|
||||
if req.CA != nil {
|
||||
if req.CA.Expiry != "" {
|
||||
policy.Default.ExpiryString = req.CA.Expiry
|
||||
policy.Default.Expiry, err = time.ParseDuration(req.CA.Expiry)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
policy.Default.CAConstraint.MaxPathLen = req.CA.PathLength
|
||||
if req.CA.PathLength != 0 && req.CA.PathLenZero == true {
|
||||
log.Infof("ignore invalid 'pathlenzero' value")
|
||||
} else {
|
||||
policy.Default.CAConstraint.MaxPathLenZero = req.CA.PathLenZero
|
||||
}
|
||||
}
|
||||
|
||||
csrPEM, err = csr.Generate(priv, req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
s, err := local.NewSigner(priv, nil, signer.DefaultSigAlgo(priv), policy)
|
||||
if err != nil {
|
||||
log.Errorf("failed to create signer: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
signReq := signer.SignRequest{Request: string(csrPEM)}
|
||||
cert, err = s.Sign(signReq)
|
||||
return
|
||||
}
|
||||
|
||||
// RenewFromSigner re-creates a root certificate from the CA cert and crypto.Signer.
|
||||
// The resulting root certificate will have ca certificate
|
||||
// as the template and have the same expiry length. E.g. the existing CA
|
||||
// is valid for a year from Jan 01 2015 to Jan 01 2016, the renewed certificate
|
||||
// will be valid from now and expire in one year as well.
|
||||
func RenewFromSigner(ca *x509.Certificate, priv crypto.Signer) ([]byte, error) {
|
||||
if !ca.IsCA {
|
||||
return nil, errors.New("input certificate is not a CA cert")
|
||||
}
|
||||
|
||||
// matching certificate public key vs private key
|
||||
switch {
|
||||
case ca.PublicKeyAlgorithm == x509.RSA:
|
||||
var rsaPublicKey *rsa.PublicKey
|
||||
var ok bool
|
||||
if rsaPublicKey, ok = priv.Public().(*rsa.PublicKey); !ok {
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
|
||||
}
|
||||
if ca.PublicKey.(*rsa.PublicKey).N.Cmp(rsaPublicKey.N) != 0 {
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
|
||||
}
|
||||
case ca.PublicKeyAlgorithm == x509.ECDSA:
|
||||
var ecdsaPublicKey *ecdsa.PublicKey
|
||||
var ok bool
|
||||
if ecdsaPublicKey, ok = priv.Public().(*ecdsa.PublicKey); !ok {
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
|
||||
}
|
||||
if ca.PublicKey.(*ecdsa.PublicKey).X.Cmp(ecdsaPublicKey.X) != 0 {
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.KeyMismatch)
|
||||
}
|
||||
default:
|
||||
return nil, cferr.New(cferr.PrivateKeyError, cferr.NotRSAOrECC)
|
||||
}
|
||||
|
||||
req := csr.ExtractCertificateRequest(ca)
|
||||
cert, _, err := NewFromSigner(req, priv)
|
||||
return cert, err
|
||||
|
||||
}
|
||||
|
||||
// CAPolicy contains the CA issuing policy as default policy.
|
||||
var CAPolicy = func() *config.Signing {
|
||||
return &config.Signing{
|
||||
Default: &config.SigningProfile{
|
||||
Usage: []string{"cert sign", "crl sign"},
|
||||
ExpiryString: "43800h",
|
||||
Expiry: 5 * helpers.OneYear,
|
||||
CAConstraint: config.CAConstraint{IsCA: true},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Update copies the CA certificate, updates the NotBefore and
|
||||
// NotAfter fields, and then re-signs the certificate.
|
||||
func Update(ca *x509.Certificate, priv crypto.Signer) (cert []byte, err error) {
|
||||
copy, err := x509.ParseCertificate(ca.Raw)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
validity := ca.NotAfter.Sub(ca.NotBefore)
|
||||
copy.NotBefore = time.Now().Round(time.Minute).Add(-5 * time.Minute)
|
||||
copy.NotAfter = copy.NotBefore.Add(validity)
|
||||
cert, err = x509.CreateCertificate(rand.Reader, copy, copy, priv.Public(), priv)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
cert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert})
|
||||
return
|
||||
}
|
385
vendor/github.com/cloudflare/cfssl/initca/initca_test.go
generated
vendored
Normal file
385
vendor/github.com/cloudflare/cfssl/initca/initca_test.go
generated
vendored
Normal file
@ -0,0 +1,385 @@
|
||||
package initca
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cloudflare/cfssl/config"
|
||||
"github.com/cloudflare/cfssl/csr"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/cloudflare/cfssl/signer/local"
|
||||
)
|
||||
|
||||
var validKeyParams = []csr.BasicKeyRequest{
|
||||
{A: "rsa", S: 2048},
|
||||
{A: "rsa", S: 3072},
|
||||
{A: "rsa", S: 4096},
|
||||
{A: "ecdsa", S: 256},
|
||||
{A: "ecdsa", S: 384},
|
||||
{A: "ecdsa", S: 521},
|
||||
}
|
||||
|
||||
var validCAConfigs = []csr.CAConfig{
|
||||
{PathLength: 0, PathLenZero: true},
|
||||
{PathLength: 0, PathLenZero: false},
|
||||
{PathLength: 2},
|
||||
{PathLength: 2, Expiry: "1h"},
|
||||
// invalid PathLenZero value will be ignored
|
||||
{PathLength: 2, PathLenZero: true},
|
||||
}
|
||||
|
||||
var invalidCAConfig = csr.CAConfig{
|
||||
PathLength: 2,
|
||||
// Expiry must be a duration string
|
||||
Expiry: "2116/12/31",
|
||||
}
|
||||
var csrFiles = []string{
|
||||
"testdata/rsa2048.csr",
|
||||
"testdata/rsa3072.csr",
|
||||
"testdata/rsa4096.csr",
|
||||
"testdata/ecdsa256.csr",
|
||||
"testdata/ecdsa384.csr",
|
||||
"testdata/ecdsa521.csr",
|
||||
}
|
||||
|
||||
var testRSACAFile = "testdata/5min-rsa.pem"
|
||||
var testRSACAKeyFile = "testdata/5min-rsa-key.pem"
|
||||
var testECDSACAFile = "testdata/5min-ecdsa.pem"
|
||||
var testECDSACAKeyFile = "testdata/5min-ecdsa-key.pem"
|
||||
|
||||
var invalidCryptoParams = []csr.BasicKeyRequest{
|
||||
// Weak Key
|
||||
{A: "rsa", S: 1024},
|
||||
// Bad param
|
||||
{A: "rsaCrypto", S: 2048},
|
||||
{A: "ecdsa", S: 2000},
|
||||
}
|
||||
|
||||
func TestInitCA(t *testing.T) {
|
||||
var req *csr.CertificateRequest
|
||||
hostname := "cloudflare.com"
|
||||
for _, param := range validKeyParams {
|
||||
for _, caconfig := range validCAConfigs {
|
||||
req = &csr.CertificateRequest{
|
||||
Names: []csr.Name{
|
||||
{
|
||||
C: "US",
|
||||
ST: "California",
|
||||
L: "San Francisco",
|
||||
O: "CloudFlare",
|
||||
OU: "Systems Engineering",
|
||||
},
|
||||
},
|
||||
CN: hostname,
|
||||
Hosts: []string{hostname, "www." + hostname},
|
||||
KeyRequest: ¶m,
|
||||
CA: &caconfig,
|
||||
}
|
||||
certBytes, _, keyBytes, err := New(req)
|
||||
if err != nil {
|
||||
t.Fatal("InitCA failed:", err)
|
||||
}
|
||||
key, err := helpers.ParsePrivateKeyPEM(keyBytes)
|
||||
if err != nil {
|
||||
t.Fatal("InitCA private key parsing failed:", err)
|
||||
}
|
||||
cert, err := helpers.ParseCertificatePEM(certBytes)
|
||||
if err != nil {
|
||||
t.Fatal("InitCA cert parsing failed:", err)
|
||||
}
|
||||
|
||||
// Verify key parameters.
|
||||
switch req.KeyRequest.Algo() {
|
||||
case "rsa":
|
||||
if cert.PublicKey.(*rsa.PublicKey).N.BitLen() != param.Size() {
|
||||
t.Fatal("Cert key length mismatch.")
|
||||
}
|
||||
if key.(*rsa.PrivateKey).N.BitLen() != param.Size() {
|
||||
t.Fatal("Private key length mismatch.")
|
||||
}
|
||||
case "ecdsa":
|
||||
if cert.PublicKey.(*ecdsa.PublicKey).Curve.Params().BitSize != param.Size() {
|
||||
t.Fatal("Cert key length mismatch.")
|
||||
}
|
||||
if key.(*ecdsa.PrivateKey).Curve.Params().BitSize != param.Size() {
|
||||
t.Fatal("Private key length mismatch.")
|
||||
}
|
||||
}
|
||||
|
||||
// Verify CA MaxPathLen
|
||||
if caconfig.PathLength == 0 && cert.MaxPathLenZero != caconfig.PathLenZero {
|
||||
t.Fatalf("fail to init a CA cert with specified CA pathlen zero: expect %v, got %v", caconfig.PathLenZero, cert.MaxPathLenZero)
|
||||
}
|
||||
|
||||
if caconfig.PathLength != 0 {
|
||||
if cert.MaxPathLen != caconfig.PathLength {
|
||||
t.Fatalf("fail to init a CA cert with specified CA pathlen: expect %d, got %d", caconfig.PathLength, cert.MaxPathLen)
|
||||
}
|
||||
if cert.MaxPathLenZero != false {
|
||||
t.Fatalf("fail to init a CA cert with specified CA pathlen zero: expect false, got %t", cert.MaxPathLenZero)
|
||||
}
|
||||
}
|
||||
|
||||
// Replace the default CAPolicy with a test (short expiry) version.
|
||||
CAPolicy = func() *config.Signing {
|
||||
return &config.Signing{
|
||||
Default: &config.SigningProfile{
|
||||
Usage: []string{"cert sign", "crl sign"},
|
||||
ExpiryString: "300s",
|
||||
Expiry: 300 * time.Second,
|
||||
CAConstraint: config.CAConstraint{IsCA: true},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Start a signer
|
||||
s, err := local.NewSigner(key, cert, signer.DefaultSigAlgo(key), nil)
|
||||
if err != nil {
|
||||
t.Fatal("Signer Creation error:", err)
|
||||
}
|
||||
s.SetPolicy(CAPolicy())
|
||||
|
||||
// Sign RSA and ECDSA customer CSRs.
|
||||
for _, csrFile := range csrFiles {
|
||||
csrBytes, err := ioutil.ReadFile(csrFile)
|
||||
if err != nil {
|
||||
t.Fatal("CSR loading error:", err)
|
||||
}
|
||||
req := signer.SignRequest{
|
||||
Request: string(csrBytes),
|
||||
Hosts: signer.SplitHosts(hostname),
|
||||
Profile: "",
|
||||
Label: "",
|
||||
}
|
||||
|
||||
bytes, err := s.Sign(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
customerCert, _ := helpers.ParseCertificatePEM(bytes)
|
||||
if customerCert.SignatureAlgorithm != s.SigAlgo() {
|
||||
t.Fatal("Signature Algorithm mismatch")
|
||||
}
|
||||
err = customerCert.CheckSignatureFrom(cert)
|
||||
if err != nil {
|
||||
t.Fatal("Signing CSR failed.", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func TestInvalidCAConfig(t *testing.T) {
|
||||
hostname := "example.com"
|
||||
req := &csr.CertificateRequest{
|
||||
Names: []csr.Name{
|
||||
{
|
||||
C: "US",
|
||||
ST: "California",
|
||||
L: "San Francisco",
|
||||
O: "CloudFlare",
|
||||
OU: "Systems Engineering",
|
||||
},
|
||||
},
|
||||
CN: hostname,
|
||||
Hosts: []string{hostname, "www." + hostname},
|
||||
KeyRequest: &validKeyParams[0],
|
||||
CA: &invalidCAConfig,
|
||||
}
|
||||
|
||||
_, _, _, err := New(req)
|
||||
if err == nil {
|
||||
t.Fatal("InitCA with bad CAConfig should fail:", err)
|
||||
}
|
||||
}
|
||||
func TestInvalidCryptoParams(t *testing.T) {
|
||||
var req *csr.CertificateRequest
|
||||
hostname := "cloudflare.com"
|
||||
for _, invalidParam := range invalidCryptoParams {
|
||||
req = &csr.CertificateRequest{
|
||||
Names: []csr.Name{
|
||||
{
|
||||
C: "US",
|
||||
ST: "California",
|
||||
L: "San Francisco",
|
||||
O: "CloudFlare",
|
||||
OU: "Systems Engineering",
|
||||
},
|
||||
},
|
||||
CN: hostname,
|
||||
Hosts: []string{hostname, "www." + hostname},
|
||||
KeyRequest: &invalidParam,
|
||||
}
|
||||
_, _, _, err := New(req)
|
||||
if err == nil {
|
||||
t.Fatal("InitCA with bad params should fail:", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), `"code":2400`) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type validation struct {
|
||||
r *csr.CertificateRequest
|
||||
v bool
|
||||
}
|
||||
|
||||
var testValidations = []validation{
|
||||
{&csr.CertificateRequest{}, false},
|
||||
{&csr.CertificateRequest{
|
||||
CN: "test CA",
|
||||
}, true},
|
||||
{&csr.CertificateRequest{
|
||||
Names: []csr.Name{{}},
|
||||
}, false},
|
||||
{&csr.CertificateRequest{
|
||||
Names: []csr.Name{
|
||||
{O: "Example CA"},
|
||||
},
|
||||
}, true},
|
||||
}
|
||||
|
||||
func TestValidations(t *testing.T) {
|
||||
for i, tv := range testValidations {
|
||||
err := validator(tv.r)
|
||||
if tv.v && err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
|
||||
if !tv.v && err == nil {
|
||||
t.Fatalf("%d: expected error, but no error was reported", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenewRSA(t *testing.T) {
|
||||
certPEM, err := RenewFromPEM(testRSACAFile, testRSACAKeyFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// must parse ok
|
||||
cert, err := helpers.ParseCertificatePEM(certPEM)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !cert.IsCA {
|
||||
t.Fatal("renewed CA certificate is not CA")
|
||||
}
|
||||
|
||||
// cert expiry must be 5 minutes
|
||||
expiry := cert.NotAfter.Sub(cert.NotBefore).Seconds()
|
||||
if expiry >= 301 || expiry <= 299 {
|
||||
t.Fatal("expiry is not correct:", expiry)
|
||||
}
|
||||
|
||||
// check subject
|
||||
|
||||
if cert.Subject.CommonName != "" {
|
||||
t.Fatal("Bad CommonName")
|
||||
}
|
||||
|
||||
if len(cert.Subject.Country) != 1 || cert.Subject.Country[0] != "US" {
|
||||
t.Fatal("Bad Subject")
|
||||
}
|
||||
|
||||
if len(cert.Subject.Organization) != 1 || cert.Subject.Organization[0] != "CloudFlare, Inc." {
|
||||
t.Fatal("Bad Subject")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenewECDSA(t *testing.T) {
|
||||
certPEM, err := RenewFromPEM(testECDSACAFile, testECDSACAKeyFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// must parse ok
|
||||
cert, err := helpers.ParseCertificatePEM(certPEM)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !cert.IsCA {
|
||||
t.Fatal("renewed CA certificate is not CA")
|
||||
}
|
||||
|
||||
// cert expiry must be 5 minutes
|
||||
expiry := cert.NotAfter.Sub(cert.NotBefore).Seconds()
|
||||
if expiry >= 301 || expiry <= 299 {
|
||||
t.Fatal("expiry is not correct:", expiry)
|
||||
}
|
||||
|
||||
// check subject
|
||||
|
||||
if cert.Subject.CommonName != "" {
|
||||
t.Fatal("Bad CommonName")
|
||||
}
|
||||
|
||||
if len(cert.Subject.Country) != 1 || cert.Subject.Country[0] != "US" {
|
||||
t.Fatal("Bad Subject")
|
||||
}
|
||||
|
||||
if len(cert.Subject.Organization) != 1 || cert.Subject.Organization[0] != "CloudFlare, Inc." {
|
||||
t.Fatal("Bad Subject")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenewMismatch(t *testing.T) {
|
||||
_, err := RenewFromPEM(testECDSACAFile, testRSACAKeyFile)
|
||||
if err == nil {
|
||||
t.Fatal("Fail to detect cert/key mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenew(t *testing.T) {
|
||||
in, err := ioutil.ReadFile(testECDSACAFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cert, err := helpers.ParseCertificatePEM(in)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
in, err = ioutil.ReadFile(testECDSACAKeyFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
priv, err := helpers.ParsePrivateKeyPEM(in)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
renewed, err := Update(cert, priv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
newCert, err := helpers.ParseCertificatePEM(renewed)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(newCert.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) {
|
||||
t.Fatal("Update returned a certificate with different subject public key info")
|
||||
}
|
||||
|
||||
if !bytes.Equal(newCert.RawSubject, cert.RawSubject) {
|
||||
t.Fatal("Update returned a certificate with different subject info")
|
||||
}
|
||||
|
||||
if !bytes.Equal(newCert.RawIssuer, cert.RawIssuer) {
|
||||
t.Fatal("Update returned a certificate with different issuer info")
|
||||
}
|
||||
}
|
5
vendor/github.com/cloudflare/cfssl/initca/testdata/5min-ecdsa-key.pem
generated
vendored
Normal file
5
vendor/github.com/cloudflare/cfssl/initca/testdata/5min-ecdsa-key.pem
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIA8OzPeVZT0cXTAPdcXYefLRIqyUXa0f0SgYMJ2J1AVcoAoGCCqGSM49
|
||||
AwEHoUQDQgAEoCV+bVOLTJMy38j50sc3vE5k41GMRgriFJt0g0OVX8yaOZ93CZTI
|
||||
7LzfGbMU+KqWTgOwGhrPvpusep3fjw+dAQ==
|
||||
-----END EC PRIVATE KEY-----
|
15
vendor/github.com/cloudflare/cfssl/initca/testdata/5min-ecdsa.pem
generated
vendored
Normal file
15
vendor/github.com/cloudflare/cfssl/initca/testdata/5min-ecdsa.pem
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICUDCCAfagAwIBAgIIec5PjdpJcNYwCgYIKoZIzj0EAwIwejELMAkGA1UEBhMC
|
||||
VVMxGTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIzAhBgNVBAsTGlRlc3QgQ2Vy
|
||||
dGlmaWNhdGUgQXV0aG9yaXR5MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYD
|
||||
VQQIEwpDYWxpZm9ybmlhMB4XDTE1MTAwODIzMDEwMFoXDTE1MTAwODIzMDYwMFow
|
||||
ejELMAkGA1UEBhMCVVMxGTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIzAhBgNV
|
||||
BAsTGlRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMFkwEwYHKoZIzj0CAQYIKoZIzj0D
|
||||
AQcDQgAEoCV+bVOLTJMy38j50sc3vE5k41GMRgriFJt0g0OVX8yaOZ93CZTI7Lzf
|
||||
GbMU+KqWTgOwGhrPvpusep3fjw+dAaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1Ud
|
||||
EwEB/wQIMAYBAf8CAQIwHQYDVR0OBBYEFDpLhSKBN3njfb6cXQCdRLzCZt0ZMB8G
|
||||
A1UdIwQYMBaAFDpLhSKBN3njfb6cXQCdRLzCZt0ZMAoGCCqGSM49BAMCA0gAMEUC
|
||||
IFU3BmzntGGeXZu2qWZx249nYn37S0AkCnQ3rUtI31bdAiEAsPICnZ+GB8yCN26N
|
||||
OL+N8dHvXiOvZ9/Vl488pyWOccY=
|
||||
-----END CERTIFICATE-----
|
27
vendor/github.com/cloudflare/cfssl/initca/testdata/5min-rsa-key.pem
generated
vendored
Normal file
27
vendor/github.com/cloudflare/cfssl/initca/testdata/5min-rsa-key.pem
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAtrYWs9ao2CpLWWLMyJJr3Bw7eJu3vSImzoqsBuhAREMaeuHm
|
||||
vAwqbByVpdxu1o+t0u6cMp/1M4YwDSxD4Ny3zEUUGse6yZpyph0+whdHSn1LOCxY
|
||||
KVwMtcYaEswenm0a+s/b9BYpbLv6lPoJ8+6bQNDuyyracDzlvGgk/HabemqDly4+
|
||||
W64tlrMUDHBuHHIm5EMF1sqVcinLCS8KsVDVfg4qKfzsZbTw0dDo5GZh1lPslkk9
|
||||
y8NzRltZjfJ3y5acv7SvIlETpy41VxScplR+Ot/6sXNJY3aEBT10smPXPABDeWjx
|
||||
FbnU5xacL/pC7pnKy734sL4lkvzKPDWZPsNMEwIDAQABAoIBAHIFHBHKib+sVS1I
|
||||
7MbWKR1JOQvBEV6kK1eFTmlZEpIG1kWNJ/J+HRMum2zQLRMUwsL5SNyG2fv3Z5Ew
|
||||
6IMw+joteahkr/oTuixT39A7uq+PlRtPAQ1+digRoj/MxebT65xNjtO56MwEWxIR
|
||||
H5jsdFJ0kDCVY4/bUPrMexhZ5Bj1xM3j8wpCPlVv2b9Ic/FUD9p6tOZDFhfSluiE
|
||||
87VsFHUImNvu4p/BAKUuKiz58cPNDHPAABsPrJR2SVU59roC4QtEmaxbmDkXUtB1
|
||||
+o+ypJQ0saqoffzHq7URebrJU9u+AV51UWaqHjg5OAe8eElOou6MHYX8R9cWZmJX
|
||||
UQKPyVECgYEAyLqstNHtA7R7+r4bW8Tr/kF7z+VvCfV9wB6TPT+ycuv3aU5+HYgR
|
||||
YRs2RBRtwI625hPk7AXEdbMt3SKoKjcMNMSD3qUK+fJFEyvOqRXiMJ2pLg04GlYZ
|
||||
cOInJd0T1q3O2cNLZwcWB1L0/KiV0dYHc4p+p5hisai3T9w7QthTUr8CgYEA6QVW
|
||||
jcsSBRFCokf/GKpTCVXIeqDSwrcEwoZh/RN6PlvgDwjw08G2IxKdAFs3/wxbKWHT
|
||||
xss+LQiMyBL8aRJvBUfotj5e5ZYESaSDqdeYv0Sydl1vfxcknHpTBRUdbyDtsOQn
|
||||
4X1ZEmfa9vFWS5P9fTFBC0BU2zzrhSlfQb6g360CgYBmnT+zBGo07aw/p7XWuRmn
|
||||
lhRUWEbmgXAyqa69rfVs2IJXfD/umuO/j6izLvpYaNzJS7xIiD5BqUK1/ISZaCC+
|
||||
TQPY6uhslFSJk2iHed9y2PZmy2010XQaCBLZQWZl5d6L5lGCrtWtEtSY4RoN9mtC
|
||||
vrc2uCkkB0sG8V/+MRaPgwKBgBiML2oQkn1mLBbcbssyZjz9hHkmqA1LKn0zmu8G
|
||||
NkKLezcaQgSMy5s2QsPe2C9OJexeGek/T/V+iRYqqdyHzJpJ0QIh3+1fuGPpqNUj
|
||||
mTvNCN/fR/ejgH/bgxNt/gPO/Ds+TdU7Vz7RIggRtH2RwYqGvctpo4bVDBqjGR3b
|
||||
7yahAoGAAgH97uN2FU1ffK0OAfMA1N58ikq/bg07KnJxO2CP5hrgsWK2ZVfeHUmU
|
||||
3k+xqQHCIuew55yO0tARTrFAh3Rj+zarA+PrtnzqW82wCIn8Fym3PFzbK2qrIMie
|
||||
yp0p4nBXsRmzinrPWKUYlFyRNY3Tcbstm5gUw2S4czSwwQeM/No=
|
||||
-----END RSA PRIVATE KEY-----
|
23
vendor/github.com/cloudflare/cfssl/initca/testdata/5min-rsa.pem
generated
vendored
Normal file
23
vendor/github.com/cloudflare/cfssl/initca/testdata/5min-rsa.pem
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID3DCCAsSgAwIBAgIIfbm2I1hwBa8wDQYJKoZIhvcNAQELBQAwejELMAkGA1UE
|
||||
BhMCVVMxGTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIzAhBgNVBAsTGlRlc3Qg
|
||||
Q2VydGlmaWNhdGUgQXV0aG9yaXR5MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMw
|
||||
EQYDVQQIEwpDYWxpZm9ybmlhMB4XDTE1MTAwODIwMjEwMFoXDTE1MTAwODIwMjYw
|
||||
MFowejELMAkGA1UEBhMCVVMxGTAXBgNVBAoTEENsb3VkRmxhcmUsIEluYy4xIzAh
|
||||
BgNVBAsTGlRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MRYwFAYDVQQHEw1TYW4g
|
||||
RnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMIIBIjANBgkqhkiG9w0BAQEF
|
||||
AAOCAQ8AMIIBCgKCAQEAtrYWs9ao2CpLWWLMyJJr3Bw7eJu3vSImzoqsBuhAREMa
|
||||
euHmvAwqbByVpdxu1o+t0u6cMp/1M4YwDSxD4Ny3zEUUGse6yZpyph0+whdHSn1L
|
||||
OCxYKVwMtcYaEswenm0a+s/b9BYpbLv6lPoJ8+6bQNDuyyracDzlvGgk/HabemqD
|
||||
ly4+W64tlrMUDHBuHHIm5EMF1sqVcinLCS8KsVDVfg4qKfzsZbTw0dDo5GZh1lPs
|
||||
lkk9y8NzRltZjfJ3y5acv7SvIlETpy41VxScplR+Ot/6sXNJY3aEBT10smPXPABD
|
||||
eWjxFbnU5xacL/pC7pnKy734sL4lkvzKPDWZPsNMEwIDAQABo2YwZDAOBgNVHQ8B
|
||||
Af8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjAdBgNVHQ4EFgQUCHoGEI1RZ8JN
|
||||
7UZ4zcTRll8nnnAwHwYDVR0jBBgwFoAUCHoGEI1RZ8JN7UZ4zcTRll8nnnAwDQYJ
|
||||
KoZIhvcNAQELBQADggEBAHRcbd6cSXV6IuT4jLV8k6OUUlxzobbiRnXJrLjy9Anx
|
||||
tyIUWv2XSh/4IEJa+/MLNIb28gU9Sa2y4GV1qAgOM5qUM2iQJyLem0pTg0WTVKlj
|
||||
ytEK1kUwQCNkc/xpDrPo5CbN3aDuW/VPntOJL1GSQzS7jzK3NeQ9sah9YYhk4Wsk
|
||||
jzHVI1sX+qzcuUqCIPhqmGR0JE8ZI5YzbMTZ4/B+oWxZ7EyzB8O+v6HVD4eQFBSq
|
||||
tyGhGbh7mUvuMpVJ8FIX4BA7QL+RwqNNtAMZKcxPjhy5I23nVclbTCz/NC2Dgp8H
|
||||
13uQsEpUZ65clgiTo4LuPzPiIouZh5cBWP4gGqbyyS4=
|
||||
-----END CERTIFICATE-----
|
11
vendor/github.com/cloudflare/cfssl/initca/testdata/README.md
generated
vendored
Normal file
11
vendor/github.com/cloudflare/cfssl/initca/testdata/README.md
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
1. To generate 5min-rsa.pem and 5min-rsa-key.pem
|
||||
```
|
||||
$ GOPATH/bin/cfssl gencert -initca ca_csr_rsa.json | GOPATH/bin/cfssljson -bare 5min-rsa
|
||||
```
|
||||
2. To generate 5min-ecdsa.pem and 5min-ecdsa-key.pem
|
||||
```
|
||||
$ GOPATH/bin/cfssl gencert -initca ca_csr_ecdsa.json | GOPATH/bin/cfssljson -bare 5min-ecdsa
|
||||
```
|
||||
|
||||
The above commands will generate 5min-rsa.csr and 5min-ecdsa.csr as well, but those
|
||||
files can be ignored.
|
18
vendor/github.com/cloudflare/cfssl/initca/testdata/ca_csr_ecdsa.json
generated
vendored
Normal file
18
vendor/github.com/cloudflare/cfssl/initca/testdata/ca_csr_ecdsa.json
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"key": {
|
||||
"algo": "ecdsa",
|
||||
"size": 256
|
||||
},
|
||||
"names": [
|
||||
{
|
||||
"C": "US",
|
||||
"L": "San Francisco",
|
||||
"ST": "California",
|
||||
"O": "CloudFlare, Inc.",
|
||||
"OU": "Test Certificate Authority"
|
||||
}
|
||||
],
|
||||
"ca": {
|
||||
"expiry": "5m"
|
||||
}
|
||||
}
|
18
vendor/github.com/cloudflare/cfssl/initca/testdata/ca_csr_rsa.json
generated
vendored
Normal file
18
vendor/github.com/cloudflare/cfssl/initca/testdata/ca_csr_rsa.json
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"key": {
|
||||
"algo": "rsa",
|
||||
"size": 2048
|
||||
},
|
||||
"names": [
|
||||
{
|
||||
"C": "US",
|
||||
"L": "San Francisco",
|
||||
"ST": "California",
|
||||
"O": "CloudFlare, Inc.",
|
||||
"OU": "Test Certificate Authority"
|
||||
}
|
||||
],
|
||||
"ca": {
|
||||
"expiry": "5m"
|
||||
}
|
||||
}
|
11
vendor/github.com/cloudflare/cfssl/initca/testdata/ecdsa256.csr
generated
vendored
Normal file
11
vendor/github.com/cloudflare/cfssl/initca/testdata/ecdsa256.csr
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBgTCCASgCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
|
||||
LmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABBn9Ldie6BOcMHezn2dPuYqW
|
||||
z/NoLYMLGNBqhOxUyEidYClI0JW2pWyUgT3A2UazFp1WgE94y7Z+2YlfRz+vcrKg
|
||||
PzA9BgkqhkiG9w0BCQ4xMDAuMCwGA1UdEQQlMCOCDmNsb3VkZmxhcmUuY29tghF3
|
||||
d3djbG91ZGZsYXJlLmNvbTAKBggqhkjOPQQDAgNHADBEAiBM+QRxe8u6rkdr10Jy
|
||||
cxbR6NxrGrNeg5QqiOqF96JEmgIgDbtjd5e3y3I8W/+ih2us3WtMxgnTXfqPd48i
|
||||
VLcv28Q=
|
||||
-----END CERTIFICATE REQUEST-----
|
12
vendor/github.com/cloudflare/cfssl/initca/testdata/ecdsa384.csr
generated
vendored
Normal file
12
vendor/github.com/cloudflare/cfssl/initca/testdata/ecdsa384.csr
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBvzCCAUUCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
|
||||
LmNvbTB2MBAGByqGSM49AgEGBSuBBAAiA2IABBk/Q+zMsZOJGkufRzGCWtSUtRjq
|
||||
0QqChDGWbHLaa0h6ODVeEoKYOMvFJTg4V186tuuBe97KEey0OPDegzCBp5kBIiwg
|
||||
HB/0xWoKdnfdRk6VyjmubPx399cGoZn8aCqgC6A/MD0GCSqGSIb3DQEJDjEwMC4w
|
||||
LAYDVR0RBCUwI4IOY2xvdWRmbGFyZS5jb22CEXd3d2Nsb3VkZmxhcmUuY29tMAoG
|
||||
CCqGSM49BAMDA2gAMGUCMQC57VfwMXDyL5kM7vmO2ynbpgSAuFZT6Yd3C3NnV2jz
|
||||
Biozw3eqIDXqCb2LI09stZMCMGIwCuVARr2IRctxf7AmX7/O2SIaIhCpMFKRedQ7
|
||||
RiWGZIucp5r6AfT9381PB29bHA==
|
||||
-----END CERTIFICATE REQUEST-----
|
13
vendor/github.com/cloudflare/cfssl/initca/testdata/ecdsa521.csr
generated
vendored
Normal file
13
vendor/github.com/cloudflare/cfssl/initca/testdata/ecdsa521.csr
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICCjCCAWsCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
|
||||
LmNvbTCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEAHt/s9KTZETzu94JIAjZ3BaS
|
||||
toSG65hGIc1e0Gt7PhdQxPp5FP2D8rQ1wc+pcZhD2O8525kPxopaqTd+fWKBuD3O
|
||||
AULzoH2OX+atIuumTQzLNbTsIbP0tY3dh7d8LItuERkZn1NfsNl3z6bnNAaR137m
|
||||
f4aWv49ImbA/Tkv8VmoKX279oD8wPQYJKoZIhvcNAQkOMTAwLjAsBgNVHREEJTAj
|
||||
gg5jbG91ZGZsYXJlLmNvbYIRd3d3Y2xvdWRmbGFyZS5jb20wCgYIKoZIzj0EAwQD
|
||||
gYwAMIGIAkIA8OX9LxWOVnyfB25DFBz6JkjhyDpBM/PXlgLnWb/n2mEuMMB44DOG
|
||||
pljDV768PSW11AC3DtULoIyR92z0TyLEKYoCQgHdGd6PwUtDW5mrAMJQDgebjsxu
|
||||
MwfcdthzKlFlSmRpHMBnRMOJjlg5f9CTBg9d6wEdv7ZIrQSO6eqQHDQRM0VMnw==
|
||||
-----END CERTIFICATE REQUEST-----
|
19
vendor/github.com/cloudflare/cfssl/initca/testdata/rsa2048.csr
generated
vendored
Normal file
19
vendor/github.com/cloudflare/cfssl/initca/testdata/rsa2048.csr
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIDCTCCAfMCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
|
||||
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALTWdoYxX4KN51fP
|
||||
WxQAyGH++VsPbfpAoXIbCPXSmU04BvIxyjzpHQ0ChMKkT/2VNcUeFJwk2fCf+ZwU
|
||||
f0raTQTplofwkckE0gEYA3WcEfJp+hbvbTb/2recsf+JE6JACYJe2Uu5wsjtrE5j
|
||||
A+7aT2BEU9RWzBdSy/5281ZfW3PArqcWaf8+RUyA3WRxVWmjmhFsVB+mdNLhCpW0
|
||||
C0QNMYR1ppEZiKVnEdao8gcI5sOvSd+35t8g82aPXcNSPU6jKcx1YNUPX5wgPEmu
|
||||
+anfc9RliQbYqqJYVODgBmV8IR5grw93yTsODoWKtFQ4PKVlnt9CD8AS/iSMQYm3
|
||||
OUogqgMCAwEAAaA/MD0GCSqGSIb3DQEJDjEwMC4wLAYDVR0RBCUwI4IOY2xvdWRm
|
||||
bGFyZS5jb22CEXd3d2Nsb3VkZmxhcmUuY29tMAsGCSqGSIb3DQEBCwOCAQEAl809
|
||||
gk9uZkRK+MJVYDSLjgGR2xqk5qOwnhovnispA7N3Z1GshodJRQa6ngNCKuXIm2/6
|
||||
AxB9kDGK14n186Qq4odXqHSHs8FG9i0zUcBXeLv1rPAKtwKTas/SLmsOpPgWPZFa
|
||||
iYiHHeu4HjOQoF987d7uGRYwc3xfstKwJsEXc12eCw2NH8TM1tJgSc/o6CzIpA91
|
||||
QnZKhx6uGM4xI2gnOaJA1YikNhyFGBuOGMZgd0k2+/IcR2pg0z4pc5oQw1bXLANx
|
||||
anqlA/MDrCM9v9019bRJ73zK8LQ3k/FW61PA9nL7RZ8ku65R+uYcVEdLa8pUeqnH
|
||||
cJZNboDRsItpccZuRQ==
|
||||
-----END CERTIFICATE REQUEST-----
|
24
vendor/github.com/cloudflare/cfssl/initca/testdata/rsa3072.csr
generated
vendored
Normal file
24
vendor/github.com/cloudflare/cfssl/initca/testdata/rsa3072.csr
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIECTCCAnMCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
|
||||
LmNvbTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAL0zzgBv+VTwZOPy
|
||||
LtuLFweQrj5Lfrje2hnNB7Y3TD4+yCM/cA4yTILixCe/B+N7LQysJgVDbW8u6BZQ
|
||||
8ZqeDKOP6KCt37WhmcbT45tLpHmH+Z/uAnCz0hVc/7AyJ3CJXo6PaDCcJjgLuUun
|
||||
W47iy4h79AxyuzELmUeZZGYcO8nqClqcnAzQ6sClGZvJwSbYg2QAFGoA2lHqZ9uN
|
||||
ygAxNLd+rX9cP+yFwAeKzuKtOnVPiJD5lT3wufSkAbd6M7lOoqmTYnbv0A1WfA/e
|
||||
upXno9lbgB6iwF5U0V7OtxdA1bTbvgJgNLlxFF1do0sB28CWmqCFNwLfzcPzt5A4
|
||||
gLnOyLhNZOmUMXn35KOtp1Zv/yethlgZHxUYGcl6OYwMEFye3Du6dgnTwONzaLhA
|
||||
7hMI8R60p2YrTLkgSKdFohAY/mKuxHyXxugOHHthlRCOn9m49edcdZ1HrkJXm9jd
|
||||
P9katjCXgTwSdTQlvaMJkfH7wF3ZMjAxPcDf4RKFEpF2wABeNQIDAQABoD8wPQYJ
|
||||
KoZIhvcNAQkOMTAwLjAsBgNVHREEJTAjgg5jbG91ZGZsYXJlLmNvbYIRd3d3Y2xv
|
||||
dWRmbGFyZS5jb20wCwYJKoZIhvcNAQEMA4IBgQBF/RCHNAAOAaRI4VyO0tRPA5Dw
|
||||
0/1/pgmBm/VejHIwDJnMFCl9njh0RSo1RgsVLhw6ovYbk3ORb4OD4UczPTq3GrFp
|
||||
KP9uPR+2pR4FWJpCVfCl76YabQv6fUDdiT7ojzyRhsAmkd5rOdiMvWV3Rp+YmBuU
|
||||
KH/dwkukfn+OeJIbERS5unzOBtQL+g5dU4CHWAqJQIqHr373w38OlYN+JY9QLrYy
|
||||
sWU9Ye6RjdySXPJ5UzyfOEfc9Ji89RJsVeceB1+As5u5vBvtzGgIMSFUzN947RZo
|
||||
DZ48JiB71VpmKXbn9LIRn25dlbVMzxRdSeZ194L3JFVAf9OxJTsc1QNFhOacoFgy
|
||||
hqvtN2iKntEyPo2nacYhpz/FAdJ2JThNH+4WtpPWAqx8Lw/e1OttiDt+6M0FEuVz
|
||||
svkSHnK206yo+a9Md37nUDDYxtlJEB+9F2qUZNQ7Hv+dxjmJOIgHOXxy1pLEdpVU
|
||||
rGdGLVXeJNPCh9x+GK21QjdxZABmYAaF8k36Pv4=
|
||||
-----END CERTIFICATE REQUEST-----
|
29
vendor/github.com/cloudflare/cfssl/initca/testdata/rsa4096.csr
generated
vendored
Normal file
29
vendor/github.com/cloudflare/cfssl/initca/testdata/rsa4096.csr
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIFCTCCAvMCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRcwFQYDVQQDEw5jbG91ZGZsYXJl
|
||||
LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANkKL22jMn3eFCpj
|
||||
T6lbeq4nC3aEqwTGrLARidAmO29WIhzs6LxRpM6xSMoPI6DvJVUGpMFEKF4xNTc5
|
||||
X9/gSFrw2eI5Q3U3aGcaToSCxH4hXejwIzX8Ftlb/LfpXhbSsFr5MS3kiTY4zZxM
|
||||
n3dSy2gZljD/g0tlQf5BdHdR4WKRhWnqRiGng+BmW4rjbcO7SoN33jSXsMcguCg5
|
||||
8dmYuf5G5KVXsqwEoCQBeKGnca9orcm4i90VnGt4qZUpfAn1cADzYGpRzX79USJ6
|
||||
tol4ovgGPN08LJFqcVl+dK8VzJ03JWBhI1jePbWS4Bz5oNtkhQQXilU+G6FQxc6a
|
||||
UPf6KcFyOB+qMJmEwJZD9yaNK1YbsKfSztQEsb1JEezQnVHxp91Ch3AcWoikuOiY
|
||||
yCg0V5lcK15SLv1+5sj9YzF7ngMmThcIJ6B5gS3swpD5AX6FJaI1BrGwT/RXKKQP
|
||||
tRX1BySLx8RcINjFb5wv3q9QIE8vrW1BOk9f4dfmxiFYnc+6bCCbIrg7APQVtKTa
|
||||
ixNJFSqZz7fm9loeNPHHXfUT5RoW5yzVa8igc+yv4qeYsWHcZ4c/Y91OJp19HMjM
|
||||
bYm2alt8XagBgJjO0FW8wvsKwhhlhWK0WO6sQ7Fkl7fH1GtxEpc248hAW24SZMmS
|
||||
led3LblCT8IC3a9BLhqJ2q8cfPp9AgMBAAGgPzA9BgkqhkiG9w0BCQ4xMDAuMCwG
|
||||
A1UdEQQlMCOCDmNsb3VkZmxhcmUuY29tghF3d3djbG91ZGZsYXJlLmNvbTALBgkq
|
||||
hkiG9w0BAQ0DggIBAAgz3NuN43+F+8+WhQ9hb7DOp6Amut7XubOkEBtBVgP3R8U1
|
||||
uSsgocR1rvnZ1/bhkeGyTly0eQPhcSEdMo/GgIrcn+co0KLcDyV6Rf3Cgksx9dUZ
|
||||
TzHSkxmFkxlxYfIGes6abH+2OPiacwK2gLvvmXFYIxEhv+LKzzteQi0xlinewv7R
|
||||
FnSykZ4QialsFyCgOjOxa11aEdRv6T8qKwhjUOk0VedtzOkt/k95aydTNLjXl2OV
|
||||
jloeTsbB00yWIqdyhG12+TgcJOa0pNP1zTjgFPodMuRUuiAcbT7Mt7sLCefKNzvZ
|
||||
Ln6b4y7e6N3YLOHALTIP+LI4y8ar47WlXCNw/zeOM2sW8udjYrukN6WOV3X68oMf
|
||||
Zsv6jqyGSaCDwdImR4VECUVvkabg9Sq4pz+ijTT+9cNA66omYL+/QAh0GahlROgW
|
||||
kDGI8zeEUoAC8RkAbFGMJA8jEbAfbT000ZwnLX2SZ8YRQX4Jd1FTmAH99FkvvT8N
|
||||
ovaGRSQQI5rWQGQYqF67So7PywEaEXeUHTBrv41Msva6CdaWHn7bh/fj4B21ETS7
|
||||
VJvrk5DLJTyruqon7EVJU1pn38ppaXF4Z6a9n3C8TqudT/gdJUYn/SBo5jx20uGJ
|
||||
d9k6vDqixntvk/TRZ848k1AXiv5uUJTdnoPPhzSGjxEaeKuB0R1ZHomVdjU4
|
||||
-----END CERTIFICATE REQUEST-----
|
162
vendor/github.com/cloudflare/cfssl/log/log.go
generated
vendored
Normal file
162
vendor/github.com/cloudflare/cfssl/log/log.go
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
// Package log implements a wrapper around the Go standard library's
|
||||
// logging package. Clients should set the current log level; only
|
||||
// messages below that level will actually be logged. For example, if
|
||||
// Level is set to LevelWarning, only log messages at the Warning,
|
||||
// Error, and Critical levels will be logged.
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
// The following constants represent logging levels in increasing levels of seriousness.
|
||||
const (
|
||||
// LevelDebug is the log level for Debug statements.
|
||||
LevelDebug = iota
|
||||
// LevelInfo is the log level for Info statements.
|
||||
LevelInfo
|
||||
// LevelWarning is the log level for Warning statements.
|
||||
LevelWarning
|
||||
// LevelError is the log level for Error statements.
|
||||
LevelError
|
||||
// LevelCritical is the log level for Critical statements.
|
||||
LevelCritical
|
||||
// LevelFatal is the log level for Fatal statements.
|
||||
LevelFatal
|
||||
)
|
||||
|
||||
var levelPrefix = [...]string{
|
||||
LevelDebug: "DEBUG",
|
||||
LevelInfo: "INFO",
|
||||
LevelWarning: "WARNING",
|
||||
LevelError: "ERROR",
|
||||
LevelCritical: "CRITICAL",
|
||||
LevelFatal: "FATAL",
|
||||
}
|
||||
|
||||
// Level stores the current logging level.
|
||||
var Level = LevelInfo
|
||||
|
||||
// SyslogWriter specifies the necessary methods for an alternate output
|
||||
// destination passed in via SetLogger.
|
||||
//
|
||||
// SyslogWriter is satisfied by *syslog.Writer.
|
||||
type SyslogWriter interface {
|
||||
Debug(string)
|
||||
Info(string)
|
||||
Warning(string)
|
||||
Err(string)
|
||||
Crit(string)
|
||||
Emerg(string)
|
||||
}
|
||||
|
||||
// syslogWriter stores the SetLogger() parameter.
|
||||
var syslogWriter SyslogWriter
|
||||
|
||||
// SetLogger sets the output used for output by this package.
|
||||
// A *syslog.Writer is a good choice for the logger parameter.
|
||||
// Call with a nil parameter to revert to default behavior.
|
||||
func SetLogger(logger SyslogWriter) {
|
||||
syslogWriter = logger
|
||||
}
|
||||
|
||||
func print(l int, msg string) {
|
||||
if l >= Level {
|
||||
if syslogWriter != nil {
|
||||
switch l {
|
||||
case LevelDebug:
|
||||
syslogWriter.Debug(msg)
|
||||
case LevelInfo:
|
||||
syslogWriter.Info(msg)
|
||||
case LevelWarning:
|
||||
syslogWriter.Warning(msg)
|
||||
case LevelError:
|
||||
syslogWriter.Err(msg)
|
||||
case LevelCritical:
|
||||
syslogWriter.Crit(msg)
|
||||
case LevelFatal:
|
||||
syslogWriter.Emerg(msg)
|
||||
}
|
||||
} else {
|
||||
log.Printf("[%s] %s", levelPrefix[l], msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func outputf(l int, format string, v []interface{}) {
|
||||
print(l, fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
func output(l int, v []interface{}) {
|
||||
print(l, fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Fatalf logs a formatted message at the "fatal" level and then exits. The
|
||||
// arguments are handled in the same manner as fmt.Printf.
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
outputf(LevelFatal, format, v)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Fatal logs its arguments at the "fatal" level and then exits.
|
||||
func Fatal(v ...interface{}) {
|
||||
output(LevelFatal, v)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Criticalf logs a formatted message at the "critical" level. The
|
||||
// arguments are handled in the same manner as fmt.Printf.
|
||||
func Criticalf(format string, v ...interface{}) {
|
||||
outputf(LevelCritical, format, v)
|
||||
}
|
||||
|
||||
// Critical logs its arguments at the "critical" level.
|
||||
func Critical(v ...interface{}) {
|
||||
output(LevelCritical, v)
|
||||
}
|
||||
|
||||
// Errorf logs a formatted message at the "error" level. The arguments
|
||||
// are handled in the same manner as fmt.Printf.
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
outputf(LevelError, format, v)
|
||||
}
|
||||
|
||||
// Error logs its arguments at the "error" level.
|
||||
func Error(v ...interface{}) {
|
||||
output(LevelError, v)
|
||||
}
|
||||
|
||||
// Warningf logs a formatted message at the "warning" level. The
|
||||
// arguments are handled in the same manner as fmt.Printf.
|
||||
func Warningf(format string, v ...interface{}) {
|
||||
outputf(LevelWarning, format, v)
|
||||
}
|
||||
|
||||
// Warning logs its arguments at the "warning" level.
|
||||
func Warning(v ...interface{}) {
|
||||
output(LevelWarning, v)
|
||||
}
|
||||
|
||||
// Infof logs a formatted message at the "info" level. The arguments
|
||||
// are handled in the same manner as fmt.Printf.
|
||||
func Infof(format string, v ...interface{}) {
|
||||
outputf(LevelInfo, format, v)
|
||||
}
|
||||
|
||||
// Info logs its arguments at the "info" level.
|
||||
func Info(v ...interface{}) {
|
||||
output(LevelInfo, v)
|
||||
}
|
||||
|
||||
// Debugf logs a formatted message at the "debug" level. The arguments
|
||||
// are handled in the same manner as fmt.Printf.
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
outputf(LevelDebug, format, v)
|
||||
}
|
||||
|
||||
// Debug logs its arguments at the "debug" level.
|
||||
func Debug(v ...interface{}) {
|
||||
output(LevelDebug, v)
|
||||
}
|
186
vendor/github.com/cloudflare/cfssl/log/log_test.go
generated
vendored
Normal file
186
vendor/github.com/cloudflare/cfssl/log/log_test.go
generated
vendored
Normal file
@ -0,0 +1,186 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const teststring = "asdf123"
|
||||
|
||||
func TestOutputf(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Level = LevelDebug
|
||||
outputf(LevelDebug, teststring, nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
if !strings.Contains(buf.String(), teststring) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestOutput(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Level = LevelDebug
|
||||
output(LevelDebug, nil)
|
||||
|
||||
// outputf correctly prints string with proper Debug prefix
|
||||
if !strings.Contains(buf.String(), levelPrefix[LevelDebug]) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestCriticalf(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Criticalf(teststring, nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
// should never fail because critical > debug
|
||||
if !strings.Contains(buf.String(), teststring) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestCritical(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Critical(nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
if !strings.Contains(buf.String(), levelPrefix[LevelCritical]) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestWarningf(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Warningf(teststring, nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
// should never fail because fatal critical > debug
|
||||
if !strings.Contains(buf.String(), teststring) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestWarning(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Warning(nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
if !strings.Contains(buf.String(), levelPrefix[LevelWarning]) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestInfof(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Infof(teststring, nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
// should never fail because fatal info > debug
|
||||
if !strings.Contains(buf.String(), teststring) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Info(nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
if !strings.Contains(buf.String(), levelPrefix[LevelInfo]) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestDebugf(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Level = LevelDebug
|
||||
Debugf(teststring, nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
// should never fail because fatal debug >= debug
|
||||
if !strings.Contains(buf.String(), teststring) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TestDebug(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
log.SetOutput(buf)
|
||||
Level = LevelDebug
|
||||
Debug(nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
if !strings.Contains(buf.String(), levelPrefix[LevelDebug]) {
|
||||
t.Fail()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type testSyslogger struct {
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
func (l testSyslogger) Debug(s string) {
|
||||
l.WriteString("[DEBUG] ")
|
||||
_, _ = l.WriteString(s)
|
||||
}
|
||||
|
||||
func (l testSyslogger) Info(s string) {
|
||||
l.WriteString("[INFO] ")
|
||||
_, _ = l.WriteString(s)
|
||||
}
|
||||
|
||||
func (l testSyslogger) Warning(s string) {
|
||||
l.WriteString("[WARN] ")
|
||||
_, _ = l.WriteString(s)
|
||||
}
|
||||
|
||||
func (l testSyslogger) Err(s string) {
|
||||
l.WriteString("[ERROR] ")
|
||||
_, _ = l.WriteString(s)
|
||||
}
|
||||
|
||||
func (l testSyslogger) Crit(s string) {
|
||||
l.WriteString("[CRIT] ")
|
||||
_, _ = l.WriteString(s)
|
||||
}
|
||||
|
||||
func (l testSyslogger) Emerg(s string) {
|
||||
l.WriteString("[FATAL] ")
|
||||
_, _ = l.WriteString(s)
|
||||
}
|
||||
|
||||
func TestSetLogger(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
SetLogger(testSyslogger{buf})
|
||||
Level = LevelDebug
|
||||
outputf(LevelDebug, teststring, nil)
|
||||
|
||||
// outputf correctly prints string
|
||||
if !strings.Contains(buf.String(), teststring) {
|
||||
t.Fail()
|
||||
}
|
||||
SetLogger(nil)
|
||||
return
|
||||
}
|
13
vendor/github.com/cloudflare/cfssl/ocsp/config/config.go
generated
vendored
Normal file
13
vendor/github.com/cloudflare/cfssl/ocsp/config/config.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
// Package config in the ocsp directory provides configuration data for an OCSP
|
||||
// signer.
|
||||
package config
|
||||
|
||||
import "time"
|
||||
|
||||
// Config contains configuration information required to set up an OCSP signer.
|
||||
type Config struct {
|
||||
CACertFile string
|
||||
ResponderCertFile string
|
||||
KeyFile string
|
||||
Interval time.Duration
|
||||
}
|
27
vendor/github.com/cloudflare/cfssl/ocsp/testdata/ca-key.pem
generated
vendored
Normal file
27
vendor/github.com/cloudflare/cfssl/ocsp/testdata/ca-key.pem
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAvKOCXwP8Y6x1YkjcimQafnP1bRCF/iWY+z4ffuTWA150RRpA
|
||||
GnhwOen8muU5wxOEm1A2IkWhNfXQ9GYVdOnzXumTx9Go4Gm8/1nRCYG69GZbQAEr
|
||||
pNGx/l4wReLVj2iizCf/xkcch5ZM/5zplXWZXCQiavmKz6M+1aSYdsGP0mrLu31c
|
||||
yod2iJmlISt+nuP5yXkgoKxzGrKjP5qrs6XniVXrKMt+5g1Ta5blWUoft2pwM6yp
|
||||
8+IAtxh+iYTIJc8dDHbVl9AjVfsfaYeS8SkHcIRyIuD8/3HgLmP/gMLDzuLXvH+W
|
||||
slOEYqLGMkSo2JPOwLguggDyjt1rI2cEcFkgJwIDAQABAoIBAQCTAZW6+D87ag28
|
||||
f22nR+XBwBp2WVcivSggO8SNvkXuMDDKHW/xcQR8jZW3HIZMOSyxYOwe/0Zn595k
|
||||
aB22lA9+Wuc45HIIGT8ZfGREVV5d0lqwYXkio+xjgAF8pQ6rCO89zLouSgK4w2/U
|
||||
D/OU7yWJwfs0hK4hrGVuVywd+DBd2Fc7UfZ4oEcy89mwUIRVK8+eXrRCav6lGDrz
|
||||
I+GmW6GL16U8lS8vsUNciYyNYCzgSIIa/yyiZO/Aje93yJRVpmujAK2p6/w/7vmK
|
||||
OareeixlpNYpiY7Nk6o3w6sKEEVzf+AquDgeH5IkzD1nkYbd+JY7bdg1cgjz3kJg
|
||||
IhsiIER5AoGBAOkZpicTIsiAMxz43bzMt1IMYu1ezAEw4Vk2sVEbSfFXdbO5J9gW
|
||||
/Ou+AhwxhsDeO6vgh3mYkG+2s5U+ztk68X1BVIf87kYBQiz175XvxcLmDBFm5S6g
|
||||
eyTCwsop9J4XlgQQ5HNm80G9oHnF50oujCqpUiC5xj5fEd8vULmua5jTAoGBAM8r
|
||||
rTTpVBHKArDlzYF5EpyXDkcFT2uAgw9Xpc6xIl/UWQ+XU1qD5Te0fmjpdwo3VZTL
|
||||
W2e8eg0U9O2skrxBcRLREnh1U2znCMSIGTkwYQ2JDjhz2Jjbh8r/NhvSdydql9wQ
|
||||
LGyPOIpcURaD+ohOExF82EtEqWgNp4QfQHH70cbdAoGAPBoy7yxN8aishTHd6opW
|
||||
Uj+DWnTw4PW7hQdHHQSOQj4syRRao6r5t8ccQCy89AnZFO4lwEKIK2XOVBMHvpcm
|
||||
IQexRgb/YOl+KJ2ZEu3p7eDnB62iNi2G0ums0/eRbRnjwlSgsui+nBrKv9s5UbVC
|
||||
ytUxqeJ8rSRSNVu70sSYVaUCgYALYUrSbT7A+2fKb9UqF4x+LY4LOK90KEsKvLXO
|
||||
9Mv+l5uMz7M0dapRtQh8mtZ/KSr6UXFj8WaC8XPC2of072NWtUVeeJNsmARTR2ab
|
||||
TZ0HMVAmqbZsLyL2c651OMpyz9gnrnvCOtvQPeH2aqmIc0F45HK9L7hejuF00IKp
|
||||
wDt1wQKBgQC8sjlF/8e03m3AfLs2ZW/w0Rsggz52TgBdH24BMUmvd5McVZlH8uZq
|
||||
zwx5ht3ppVjObG28JPEj8c/FtAmsUjURDD7EVdjb5bDxrMtH++8sHrXUuMMBeUxl
|
||||
DN2IU+xL9MwMh5H0cyJbXnE+LWGpSefCccDnH5qlEjwNXE5/RggOrw==
|
||||
-----END RSA PRIVATE KEY-----
|
23
vendor/github.com/cloudflare/cfssl/ocsp/testdata/ca.pem
generated
vendored
Normal file
23
vendor/github.com/cloudflare/cfssl/ocsp/testdata/ca.pem
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDvjCCAqigAwIBAgIIWhorb65IXvUwCwYJKoZIhvcNAQELMG0xCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJlMRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2lu
|
||||
ZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9y
|
||||
bmlhMB4XDTE1MDQxOTE2MTAwMFoXDTIwMDQxNzE2MTAwMFowbTELMAkGA1UEBhMC
|
||||
VVMxEzARBgNVBAoTCkNsb3VkRmxhcmUxHDAaBgNVBAsTE1N5c3RlbXMgRW5naW5l
|
||||
ZXJpbmcxFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEzARBgNVBAgTCkNhbGlmb3Ju
|
||||
aWEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8o4JfA/xjrHViSNyK
|
||||
ZBp+c/VtEIX+JZj7Ph9+5NYDXnRFGkAaeHA56fya5TnDE4SbUDYiRaE19dD0ZhV0
|
||||
6fNe6ZPH0ajgabz/WdEJgbr0ZltAASuk0bH+XjBF4tWPaKLMJ//GRxyHlkz/nOmV
|
||||
dZlcJCJq+YrPoz7VpJh2wY/Sasu7fVzKh3aImaUhK36e4/nJeSCgrHMasqM/mquz
|
||||
peeJVesoy37mDVNrluVZSh+3anAzrKnz4gC3GH6JhMglzx0MdtWX0CNV+x9ph5Lx
|
||||
KQdwhHIi4Pz/ceAuY/+AwsPO4te8f5ayU4RiosYyRKjYk87AuC6CAPKO3WsjZwRw
|
||||
WSAnAgMBAAGjZjBkMA4GA1UdDwEB/wQEAwIABjASBgNVHRMBAf8ECDAGAQH/AgEC
|
||||
MB0GA1UdDgQWBBSrzjPP4Y5PLsqeyp6iddofBjoRmTAfBgNVHSMEGDAWgBSrzjPP
|
||||
4Y5PLsqeyp6iddofBjoRmTALBgkqhkiG9w0BAQsDggEBAH7McpSm7+DeIZPQKYpF
|
||||
kFUlNn3N4MRvek5lxOw6jLE1QmzG3lTB79g6iBiGKsYLPoJqNS6VxMoLrMC+qFhM
|
||||
0QM5eIzRpdfYa83IDIYcbUYx7fLG/azX+FMFh/O5yPtS+bqbxGinxofRIyuKGs9r
|
||||
dks6I5lGncRs0Liysp4mHJAjyj9G2W2onI3Y00BYhiOy4mYvZ5/S31KI4550HZ+p
|
||||
dnexuC29CsWGkOTXTOS7+e7Zmbh8UjsYcA5YOojew+EjJfETPVO+Pn7WGg/+XrFX
|
||||
8UOG3o9k8M0ePQof4R6FTJ+BQxtSkWWdp1HrMQbZ1TXfZx84XkmFdcmy8FjYiHbP
|
||||
M+M=
|
||||
-----END CERTIFICATE-----
|
23
vendor/github.com/cloudflare/cfssl/ocsp/testdata/cert.pem
generated
vendored
Normal file
23
vendor/github.com/cloudflare/cfssl/ocsp/testdata/cert.pem
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID4TCCAsugAwIBAgIIEoDcqfKl/s4wCwYJKoZIhvcNAQELMG0xCzAJBgNVBAYT
|
||||
AlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJlMRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2lu
|
||||
ZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9y
|
||||
bmlhMB4XDTE1MDQxOTE2MTkwMFoXDTE2MDQxODE2MTkwMFowXTELMAkGA1UEBhMC
|
||||
VVMxEDAOBgNVBAoTB0V4YW1wbGUxDzANBgNVBAsTBlRoaW5nczEWMBQGA1UEBxMN
|
||||
U2FuIEZyYW5jaXNjbzETMBEGA1UECBMKQ2FsaWZvcm5pYTCCASIwDQYJKoZIhvcN
|
||||
AQEBBQADggEPADCCAQoCggEBAK7jUnRUeD5QY9YPjbW6aiGkVWRWAebi4nZl++C+
|
||||
HEBHSyB0jXX+J93y97PuhgeguCuMM6KZU7C0tPZKjwdxBSqpXeyFpvcj+UWMjZjz
|
||||
9FrBAzZ1DIYquqfYuKUtavoFv29IomRqzyZ4FrMJ2qy0RudnWMTqn4P6/7DrWos+
|
||||
oJMCpl/mdWl+YXMXypgW5JwM7ladx8GkEKQwGMtXrG9pop7qS6LNikN76tLPYWjR
|
||||
DhrWLBe8gCGjuXkwvxw78CeeJNyWF+P/+x4lVsWphip3jX57SUx/bjaRjsWSfpMz
|
||||
xHueHtuCrGffgCkFzYH1/Z60FZNxuHYqJeL4V3gcR8IIaZECAwEAAaOBmDCBlTAO
|
||||
BgNVHQ8BAf8EBAMCAKAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwG
|
||||
A1UdEwEB/wQCMAAwHQYDVR0OBBYEFBnFrxc1gkG2CYImTYKL0DAaGxRBMB8GA1Ud
|
||||
IwQYMBaAFKvOM8/hjk8uyp7KnqJ12h8GOhGZMBYGA1UdEQQPMA2CC2V4YW1wbGUu
|
||||
Y29tMAsGCSqGSIb3DQEBCwOCAQEAX31Jk7R9gDMw/gepIxxeKx9m+c7eOYDxjJ12
|
||||
bfXQVKNNPLZsO9M9r2/0BCTFsNTF2jh6ZTeIf7qy+Jw08YqTcO5m8jhiGzCjOYu5
|
||||
tiGxCUe+cYjXcCRk83+XGkVrQm3fQ0cVtic0yfm/fez3iv915jH0GYO5X8/d7bKa
|
||||
0kWJ3uOjur6tenfnisypEsuYYjPRcQdXSG6/qgHEc4r279Z2ltjy1bFFr86hHUbj
|
||||
DX7XNWH/MXFgqLzfQm5VzmqBj9om+0/tgTWdkgI1DK/Hnvm9A4YZfaxh4fxv7ITo
|
||||
Ce8FWW13Wj55x64peb8ZiW1jUyoaJQcxQxFpRHIVu26nXApWtg==
|
||||
-----END CERTIFICATE-----
|
1
vendor/github.com/cloudflare/cfssl/ocsp/testdata/db-config.json
generated
vendored
Normal file
1
vendor/github.com/cloudflare/cfssl/ocsp/testdata/db-config.json
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"driver":"sqlite3","data_source":"sqlite_test.db"}
|
2
vendor/github.com/cloudflare/cfssl/ocsp/testdata/resp64.pem
generated
vendored
Normal file
2
vendor/github.com/cloudflare/cfssl/ocsp/testdata/resp64.pem
generated
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
MIIFCAoBAKCCBQEwggT9BgkrBgEFBQcwAQEEggTuMIIE6jCBrKADAgEAoS0wKzEpMCcGA1UEAwwgY2Fja2xpbmcgY3J5cHRvZ3JhcGhlciBmYWtlIFJPT1QYDzIwMTUxMDIxMjEyNjAwWjBlMGMwOzAJBgUrDgMCGgUABBSwLsMRhyg1dJUwnXWk++D57lvgagQU6aQ/7p6l5vLV13lgPJOmLiSOl6oCAhJNgAAYDzIwMTUwOTAxMDAwMDAwWqARGA8yMDE0MDEwMTAwMDAwMFowDQYJKoZIhvcNAQELBQADggEBAHlFcNKa7mZDJeWzJt1S45kx4gDqOLzyeZzflFbSjsrHRrLA7Y3RKoy0i4Y9Vi6Jfhe7xj6dgDMJy1Z1qayI/Q8QvnaU6V2kFcnaD7pah9uALu2xNYMJPllq8KsQYvDLa1E2PMvQTqDhY2/QrIuxw3jkqtzeI5aG0idFm3aF1z/v3dt6XPWjE8IlAJfXY4CeUorLvA+mK2YHJ3V7MSgymVXZdyth1rg0/0cP9v77Rlb8hmWA/EUMcIPKQqErVQK+gZiVC0SfElaMO25CD9cjY+fd904oC5+ahvhHXxOSEbXVZBT1FY2teFCKEpx86gAVcZWpGmVwJO+dpsrkgwpN786gggMjMIIDHzCCAxswggIDoAMCAQICCQDNMc/iNkPNdTANBgkqhkiG9w0BAQsFADArMSkwJwYDVQQDDCBjYWNrbGluZyBjcnlwdG9ncmFwaGVyIGZha2UgUk9PVDAeFw0xNTEwMjEyMDExNTJaFw0yMDEwMTkyMDExNTJaMCsxKTAnBgNVBAMMIGNhY2tsaW5nIGNyeXB0b2dyYXBoZXIgZmFrZSBST09UMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+TbvalHXQYO6GhJUJZI5mF2k4+nZDIvqWyrjw+2k9+UAcekuLKPpSclu9aBRvUggw3XFHAW95qW6Dv2+5gvinUmTq9Ry7kVTUYAxyZu1ydHt+wDETmFJfeY6/fpBHHIsuGLItqpUGmr8D6LROGEqfFY2B9+08O7Zs+FufDRgLHWEvLTdpPkrzeDJs9Oo6g38jfT9b4+9Ahs+FvvwqneAkbeZgBC2NWKB+drMuNBTPbF/W1a8czAzHeOs6qy0dBlTHNjL62/o9cRKNiKe3IqwHJdd01V1aLSUgIbe2HrP9EC1djnUXWR3jx3ursaKt7PTKsC52UJkRqnai80MzQj0WwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU6aQ/7p6l5vLV13lgPJOmLiSOl6owDQYJKoZIhvcNAQELBQADggEBACuwILDTvaBrdorv2zMsYnZuKvXtknWAf/DTcvF4N5PMOPBNkeHuGfv0VDe6VXpBHiU5G9E2RdU435W7o0kRSn27YcqrxaXGt9m2kArW6e49136+MnFx47jjk0p4T48s6MeaL5JVLJzxYouu1ZOZqlVokwNPO+8bxn6ALumIVUOD1jSBN7Y9pgLUS2rzO5pe5pxS2Ak/eO7Q7M21r1sEuG/uPuWqBFogk+4Z9omKVZdRDbzm9vYUATgEZdlTe2tct3BVBQ2zWbe0R2svIuCs8XzERykvfv1JawxI68I9vN0Dh9vj/xDM6udorfALlhjgQdftmbHovRLpJ1ZSOMIUNGY=
|
||||
MIIFCAoBAKCCBQEwggT9BgkrBgEFBQcwAQEEggTuMIIE6jCBrKADAgEAoS0wKzEpMCcGA1UEAwwgY2Fja2xpbmcgY3J5cHRvZ3JhcGhlciBmYWtlIFJPT1QYDzIwMTUxMDIxMjA1NTAwWjBlMGMwOzAJBgUrDgMCGgUABBSwLsMRhyg1dJUwnXWk++D57lvgagQU6aQ/7p6l5vLV13lgPJOmLiSOl6oCAhJNgAAYDzIwMTUxMDIwMDAwMDAwWqARGA8yMDMwMTAyMDAwMDAwMFowDQYJKoZIhvcNAQELBQADggEBAFgnZ/Ft1LTDYPwPlecOtLykgwS4HZTelUaSi841nq/tgfLM11G3D1AUXAT2V2jxiG+0YTxzkWd5v44KJGB9Mm+qjafPMKR3ULjQkJHJ8goFHpWkUtLrIYurj8N+4HpwZ+RJccieuZIX8SMeSWRq5w83okWZPGoUrl6GRdQDteE7imrNkBa35zrzUWozPqY8k90ttKfhZHRXNCJe8YbVfJRDh0vVZABzlfHeW8V+ie15HPVDx/M341KC3tBMM88e5/bt3sLyUU8SwxGH5nOe/ohVpjhkjk2Pz4TPdwD2ZK5Auc09VBfivdLYRE84BMhd8/yOEt53VWGPIMxWUVtrUyegggMjMIIDHzCCAxswggIDoAMCAQICCQDNMc/iNkPNdTANBgkqhkiG9w0BAQsFADArMSkwJwYDVQQDDCBjYWNrbGluZyBjcnlwdG9ncmFwaGVyIGZha2UgUk9PVDAeFw0xNTEwMjEyMDExNTJaFw0yMDEwMTkyMDExNTJaMCsxKTAnBgNVBAMMIGNhY2tsaW5nIGNyeXB0b2dyYXBoZXIgZmFrZSBST09UMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+TbvalHXQYO6GhJUJZI5mF2k4+nZDIvqWyrjw+2k9+UAcekuLKPpSclu9aBRvUggw3XFHAW95qW6Dv2+5gvinUmTq9Ry7kVTUYAxyZu1ydHt+wDETmFJfeY6/fpBHHIsuGLItqpUGmr8D6LROGEqfFY2B9+08O7Zs+FufDRgLHWEvLTdpPkrzeDJs9Oo6g38jfT9b4+9Ahs+FvvwqneAkbeZgBC2NWKB+drMuNBTPbF/W1a8czAzHeOs6qy0dBlTHNjL62/o9cRKNiKe3IqwHJdd01V1aLSUgIbe2HrP9EC1djnUXWR3jx3ursaKt7PTKsC52UJkRqnai80MzQj0WwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU6aQ/7p6l5vLV13lgPJOmLiSOl6owDQYJKoZIhvcNAQELBQADggEBACuwILDTvaBrdorv2zMsYnZuKvXtknWAf/DTcvF4N5PMOPBNkeHuGfv0VDe6VXpBHiU5G9E2RdU435W7o0kRSn27YcqrxaXGt9m2kArW6e49136+MnFx47jjk0p4T48s6MeaL5JVLJzxYouu1ZOZqlVokwNPO+8bxn6ALumIVUOD1jSBN7Y9pgLUS2rzO5pe5pxS2Ak/eO7Q7M21r1sEuG/uPuWqBFogk+4Z9omKVZdRDbzm9vYUATgEZdlTe2tct3BVBQ2zWbe0R2svIuCs8XzERykvfv1JawxI68I9vN0Dh9vj/xDM6udorfALlhjgQdftmbHovRLpJ1ZSOMIUNGY=
|
BIN
vendor/github.com/cloudflare/cfssl/ocsp/testdata/response.der
generated
vendored
Normal file
BIN
vendor/github.com/cloudflare/cfssl/ocsp/testdata/response.der
generated
vendored
Normal file
Binary file not shown.
1
vendor/github.com/cloudflare/cfssl/ocsp/testdata/response_broken.pem
generated
vendored
Normal file
1
vendor/github.com/cloudflare/cfssl/ocsp/testdata/response_broken.pem
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
MIICGAoBAKCCAhEwggINBgkrBgEFBQcwAQEEggH+OZ4ZSKS2J85Kr9UaI2LAEFKvOM8/hjk8uyp7KnqJ12h8GOhGZAgIBdaADAQH/GA8wMDAxMDEwMTAwMDAwMFqgERgPMDAwMTAxMDEwMDAwMDBaMA0GCSqGSIb3DQEBCwUAA4IBAQCBGs+8UNwUdkEBladnajZIV+sHtmao/mMTIvpyPqnmV2Ab9KfNWlSDSDuMtZYKS4VsEwtbZ+4kKWI8DugE6egjP3o64R7VP2aqrh41IORwccLGVsexILBpxg4h602JbhXM0sxgXoh5WAt9f1oy6PsHAt/XAuJGSo7yMNv3nHKNFwjExmZt21sNLYlWlljjtX92rlo/mBTWKO0js4YRNyeNQhchARbn9oL18jW0yAVqB9a8rees+EippbTfoktFf0cIhnmkiknPZSZ+dN2qHkxiXIujWlymZzUZcqRTNtrmmhlOdt35QSg7Vw8eyw2rl8ZU94zaI5DPWn1QYn0dk7l9
|
BIN
vendor/github.com/cloudflare/cfssl/ocsp/testdata/response_mix.pem
generated
vendored
Normal file
BIN
vendor/github.com/cloudflare/cfssl/ocsp/testdata/response_mix.pem
generated
vendored
Normal file
Binary file not shown.
13
vendor/github.com/cloudflare/cfssl/ocsp/testdata/server.crt
generated
vendored
Normal file
13
vendor/github.com/cloudflare/cfssl/ocsp/testdata/server.crt
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICATCCAWoCCQDidF+uNJR6czANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTEyMDUwMTIyNTUxN1oXDTEzMDUwMTIyNTUxN1owRTELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtpjl
|
||||
nodhz31kLEJoeLSkRmrv8l7exkGtO0REtIbirj9BBy64ZXVBE7khKGO2cnM8U7yj
|
||||
w7Ntfh+IvCjZVA3d2XqHS3Pjrt4HmU/cGCONE8+NEXoqdzLUDPOix1qDDRBvXs81
|
||||
KAV2qh6CYHZbdqixhDerjvJcD4Nsd7kExEZfHuECAwEAATANBgkqhkiG9w0BAQUF
|
||||
AAOBgQCyOqs7+qpMrYCgL6OamDeCVojLoEp036PsnaYWf2NPmsVXdpYW40Foyyjp
|
||||
iv5otkxO5rxtGPv7o2J1eMBpCuSkydvoz3Ey/QwGqbBwEXQ4xYCgra336gqW2KQt
|
||||
+LnDCkE8f5oBhCIisExc2i8PDvsRsY70g/2gs983ImJjVR8sDw==
|
||||
-----END CERTIFICATE-----
|
15
vendor/github.com/cloudflare/cfssl/ocsp/testdata/server.key
generated
vendored
Normal file
15
vendor/github.com/cloudflare/cfssl/ocsp/testdata/server.key
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIICXAIBAAKBgQC2mOWeh2HPfWQsQmh4tKRGau/yXt7GQa07RES0huKuP0EHLrhl
|
||||
dUETuSEoY7ZyczxTvKPDs21+H4i8KNlUDd3ZeodLc+Ou3geZT9wYI40Tz40Reip3
|
||||
MtQM86LHWoMNEG9ezzUoBXaqHoJgdlt2qLGEN6uO8lwPg2x3uQTERl8e4QIDAQAB
|
||||
AoGAVxnsPojZ8X4g8LPk3d9dlXGhb/4tSmk9102jcHH/Y5ssy95Pe6ZJGr1uwbN+
|
||||
7m1l05PikpHeoxEryoW51cyfjDVkXUT0zPp2JC38DUA/0A8qWav/aENM64wg1I0P
|
||||
Dil8FywzZEonRNJst53+9cxFye70ely5br/tWxEp4/MsM1kCQQDqV4Lwn8BXOeKg
|
||||
xOwNmcL+0XPedvSPBSPUoGJCzu12rH6Z+UHXipXsqRNSyQ+KGlur14y0kCh5uiVA
|
||||
jmWYVEEjAkEAx3keAo1nFsVW35EPt5LIbh6L6ty7GrvGRvOVeSd6YLtixMety24k
|
||||
hpt1cEv2xlFnbjbBbMkr9eUiUNpttLT6KwJBANGKaLoSjqEwUFYjX1OV/wdtcGcn
|
||||
BOzx0qUouFQ2xZ0NBrNVbyt1bzPLx0yKHkwF35ybw+Qc1yRpby/3ZB6+j/MCQFLl
|
||||
vtcItOL9uBDJVGLSGYHKKBO/D/MYPlqWOHRVN8KjnXRyF4QHjh5y1OeKalAY3Ict
|
||||
Mk1nfWF/jDdVz2neHGkCQHHBR4Xt1/euDku+14z5aLpphTEQVuRD2vQoeKi/W/CY
|
||||
OgNmKj1DzucnCS6yRCrF8Q0Pn8l054a3Wdbl1gqI/gA=
|
||||
-----END RSA PRIVATE KEY-----
|
9
vendor/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.crt
generated
vendored
Normal file
9
vendor/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.crt
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtpjl
|
||||
nodhz31kLEJoeLSkRmrv8l7exkGtO0REtIbirj9BBy64ZXVBE7khKGO2cnM8U7yj
|
||||
w7Ntfh+IvCjZVA3d2XqHS3Pjrt4HmU/cGCONE8+NEXoqdzLUDPOix1qDDRBvXs81
|
||||
KAV2qh6CYHZbdqixhDerjvJcD4Nsd7kExEZfHuECAwEAATANBgkqhkiG9w0BAQUF
|
||||
AAOBgQCyOqs7+qpMrYCgL6OamDeCVojLoEp036PsnaYWf2NPmsVXdpYW40Foyyjp
|
||||
iv5otkxO5rxtGPv7o2J1eMBpCuSkydvoz3Ey/QwGqbBwEXQ4xYCgra336gqW2KQt
|
||||
+LnDCkE8f5oBhCIisExc2i8PDvsRsY70g/2gs983ImJjVR8sDw==
|
||||
-----END CERTIFICATE-----
|
8
vendor/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.key
generated
vendored
Normal file
8
vendor/github.com/cloudflare/cfssl/ocsp/testdata/server_broken.key
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
jmWYVEEjAkEAx3keAo1nFsVW35EPt5LIbh6L6ty7GrvGRvOVeSd6YLtixMety24k
|
||||
hpt1cEv2xlFnbjbBbMkr9eUiUNpttLT6KwJBANGKaLoSjqEwUFYjX1OV/wdtcGcn
|
||||
BOzx0qUouFQ2xZ0NBrNVbyt1bzPLx0yKHkwF35ybw+Qc1yRpby/3ZB6+j/MCQFLl
|
||||
vtcItOL9uBDJVGLSGYHKKBO/D/MYPlqWOHRVN8KjnXRyF4QHjh5y1OeKalAY3Ict
|
||||
Mk1nfWF/jDdVz2neHGkCQHHBR4Xt1/euDku+14z5aLpphTEQVuRD2vQoeKi/W/CY
|
||||
OgNmKj1DzucnCS6yRCrF8Q0Pn8l054a3Wdbl1gqI/gA=
|
||||
-----END RSA PRIVATE KEY-----
|
22
vendor/github.com/cloudflare/cfssl/ocsp/testdata/sqlite_ca.pem
generated
vendored
Normal file
22
vendor/github.com/cloudflare/cfssl/ocsp/testdata/sqlite_ca.pem
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDqjCCApKgAwIBAgIUFqT7NscPhQ5kfZTYNhWTKXVekrswDQYJKoZIhvcNAQEL
|
||||
BQAwbTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCE5ldyBZb3JrMQ8wDQYDVQQHEwZJ
|
||||
dGhhY2ExLDAqBgNVBAoTI1RoZSBCZXN0IE9wZW4tU291cmNlIEhhY2thdGhvbiBU
|
||||
ZWFtMQwwCgYDVQQLEwNXV1cwHhcNMTcwMjExMTQxMDAwWhcNMjIwMjEwMTQxMDAw
|
||||
WjBtMQswCQYDVQQGEwJVUzERMA8GA1UECBMITmV3IFlvcmsxDzANBgNVBAcTBkl0
|
||||
aGFjYTEsMCoGA1UEChMjVGhlIEJlc3QgT3Blbi1Tb3VyY2UgSGFja2F0aG9uIFRl
|
||||
YW0xDDAKBgNVBAsTA1dXVzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
ANR66Ky8dBV2FVyDOGXFM4bF63EJxI7PgCKg8yiJsYihwo5wsABpiI66offWsJNV
|
||||
rRKT8QhGohm4V1B/MOpdb3slOYVFXAInjoKyClPYDK3GMkJ8mo6mFysm3q/JqlEl
|
||||
KjvVIb8Yq7cgPAj/MOb4rBJu5+c3sM37CwpUbxCTdPiuVMGYDjVKauloJfTir0HQ
|
||||
RMwREsO6fyzSia4qvfj4ljWGzPtEVrRmzs7LguLr3DkUjXMSq7AI3L+oUdiYR6kV
|
||||
c3rLucMQKRCNGMcU3T8Sq9Pwt2sUeAFNqcXk9E1FqesYwFoEejStU24wpTd4ah0g
|
||||
tL1LyoEYG6etUehrxlRlMJsCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
|
||||
EwEB/wQFMAMBAf8wHQYDVR0OBBYEFANQ4+9iVQzAZdHhb0fNXtrb3krdMA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQA4SKVpdJj40xaeyVkHWtrY4O8wB2J7Z6rsUf9jlEySeQaH
|
||||
GWI4LUOKjrU0u/NtuvTybDHyfc1VrdgZmfaukE35VyQ1+xWa/47Q7KISSCH1x0cF
|
||||
L+WdJqKHD0q/tR2uz/fw9AUlV1LkBEeAZclhPxCLv32gLExQrNCBVa7c9Xkq1muB
|
||||
o0ootJF9sTZopqnsMldvMBWOl/9cb2dxPKu3AcNpCm28wt+rwqHIu+Fna9Fe/n+y
|
||||
SmWTaP3l/eiLskFUvmHKSUVwTEPC6kbK9rxKPz7ijQ3h/YuWxxz32L2CpsOfekgT
|
||||
7jER0Y/xxZq7XykdwZ1VKKfZGnsH8mU2rU335Gd1
|
||||
-----END CERTIFICATE-----
|
BIN
vendor/github.com/cloudflare/cfssl/ocsp/testdata/sqlite_test.db
generated
vendored
Normal file
BIN
vendor/github.com/cloudflare/cfssl/ocsp/testdata/sqlite_test.db
generated
vendored
Normal file
Binary file not shown.
556
vendor/github.com/cloudflare/cfssl/signer/local/local.go
generated
vendored
Normal file
556
vendor/github.com/cloudflare/cfssl/signer/local/local.go
generated
vendored
Normal file
@ -0,0 +1,556 @@
|
||||
// Package local implements certificate signature functionality for CFSSL.
|
||||
package local
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/mail"
|
||||
"os"
|
||||
|
||||
"github.com/cloudflare/cfssl/certdb"
|
||||
"github.com/cloudflare/cfssl/config"
|
||||
cferr "github.com/cloudflare/cfssl/errors"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/info"
|
||||
"github.com/cloudflare/cfssl/log"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/google/certificate-transparency-go"
|
||||
"github.com/google/certificate-transparency-go/client"
|
||||
"github.com/google/certificate-transparency-go/jsonclient"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// Signer contains a signer that uses the standard library to
|
||||
// support both ECDSA and RSA CA keys.
|
||||
type Signer struct {
|
||||
ca *x509.Certificate
|
||||
priv crypto.Signer
|
||||
policy *config.Signing
|
||||
sigAlgo x509.SignatureAlgorithm
|
||||
dbAccessor certdb.Accessor
|
||||
}
|
||||
|
||||
// NewSigner creates a new Signer directly from a
|
||||
// private key and certificate, with optional policy.
|
||||
func NewSigner(priv crypto.Signer, cert *x509.Certificate, sigAlgo x509.SignatureAlgorithm, policy *config.Signing) (*Signer, error) {
|
||||
if policy == nil {
|
||||
policy = &config.Signing{
|
||||
Profiles: map[string]*config.SigningProfile{},
|
||||
Default: config.DefaultConfig()}
|
||||
}
|
||||
|
||||
if !policy.Valid() {
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidPolicy)
|
||||
}
|
||||
|
||||
return &Signer{
|
||||
ca: cert,
|
||||
priv: priv,
|
||||
sigAlgo: sigAlgo,
|
||||
policy: policy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewSignerFromFile generates a new local signer from a caFile
|
||||
// and a caKey file, both PEM encoded.
|
||||
func NewSignerFromFile(caFile, caKeyFile string, policy *config.Signing) (*Signer, error) {
|
||||
log.Debug("Loading CA: ", caFile)
|
||||
ca, err := helpers.ReadBytes(caFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug("Loading CA key: ", caKeyFile)
|
||||
cakey, err := helpers.ReadBytes(caKeyFile)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err)
|
||||
}
|
||||
|
||||
parsedCa, err := helpers.ParseCertificatePEM(ca)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD")
|
||||
password := []byte(strPassword)
|
||||
if strPassword == "" {
|
||||
password = nil
|
||||
}
|
||||
|
||||
priv, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password)
|
||||
if err != nil {
|
||||
log.Debug("Malformed private key %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewSigner(priv, parsedCa, signer.DefaultSigAlgo(priv), policy)
|
||||
}
|
||||
|
||||
func (s *Signer) sign(template *x509.Certificate) (cert []byte, err error) {
|
||||
var initRoot bool
|
||||
if s.ca == nil {
|
||||
if !template.IsCA {
|
||||
err = cferr.New(cferr.PolicyError, cferr.InvalidRequest)
|
||||
return
|
||||
}
|
||||
template.DNSNames = nil
|
||||
template.EmailAddresses = nil
|
||||
s.ca = template
|
||||
initRoot = true
|
||||
}
|
||||
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, template, s.ca, template.PublicKey, s.priv)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
|
||||
}
|
||||
if initRoot {
|
||||
s.ca, err = x509.ParseCertificate(derBytes)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
|
||||
}
|
||||
}
|
||||
|
||||
cert = pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||
log.Infof("signed certificate with serial number %d", template.SerialNumber)
|
||||
return
|
||||
}
|
||||
|
||||
// replaceSliceIfEmpty replaces the contents of replaced with newContents if
|
||||
// the slice referenced by replaced is empty
|
||||
func replaceSliceIfEmpty(replaced, newContents *[]string) {
|
||||
if len(*replaced) == 0 {
|
||||
*replaced = *newContents
|
||||
}
|
||||
}
|
||||
|
||||
// PopulateSubjectFromCSR has functionality similar to Name, except
|
||||
// it fills the fields of the resulting pkix.Name with req's if the
|
||||
// subject's corresponding fields are empty
|
||||
func PopulateSubjectFromCSR(s *signer.Subject, req pkix.Name) pkix.Name {
|
||||
// if no subject, use req
|
||||
if s == nil {
|
||||
return req
|
||||
}
|
||||
|
||||
name := s.Name()
|
||||
|
||||
if name.CommonName == "" {
|
||||
name.CommonName = req.CommonName
|
||||
}
|
||||
|
||||
replaceSliceIfEmpty(&name.Country, &req.Country)
|
||||
replaceSliceIfEmpty(&name.Province, &req.Province)
|
||||
replaceSliceIfEmpty(&name.Locality, &req.Locality)
|
||||
replaceSliceIfEmpty(&name.Organization, &req.Organization)
|
||||
replaceSliceIfEmpty(&name.OrganizationalUnit, &req.OrganizationalUnit)
|
||||
if name.SerialNumber == "" {
|
||||
name.SerialNumber = req.SerialNumber
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// OverrideHosts fills template's IPAddresses, EmailAddresses, and DNSNames with the
|
||||
// content of hosts, if it is not nil.
|
||||
func OverrideHosts(template *x509.Certificate, hosts []string) {
|
||||
if hosts != nil {
|
||||
template.IPAddresses = []net.IP{}
|
||||
template.EmailAddresses = []string{}
|
||||
template.DNSNames = []string{}
|
||||
}
|
||||
|
||||
for i := range hosts {
|
||||
if ip := net.ParseIP(hosts[i]); ip != nil {
|
||||
template.IPAddresses = append(template.IPAddresses, ip)
|
||||
} else if email, err := mail.ParseAddress(hosts[i]); err == nil && email != nil {
|
||||
template.EmailAddresses = append(template.EmailAddresses, email.Address)
|
||||
} else {
|
||||
template.DNSNames = append(template.DNSNames, hosts[i])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Sign signs a new certificate based on the PEM-encoded client
|
||||
// certificate or certificate request with the signing profile,
|
||||
// specified by profileName.
|
||||
func (s *Signer) Sign(req signer.SignRequest) (cert []byte, err error) {
|
||||
profile, err := signer.Profile(s, req.Profile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
block, _ := pem.Decode([]byte(req.Request))
|
||||
if block == nil {
|
||||
return nil, cferr.New(cferr.CSRError, cferr.DecodeFailed)
|
||||
}
|
||||
|
||||
if block.Type != "NEW CERTIFICATE REQUEST" && block.Type != "CERTIFICATE REQUEST" {
|
||||
return nil, cferr.Wrap(cferr.CSRError,
|
||||
cferr.BadRequest, errors.New("not a csr"))
|
||||
}
|
||||
|
||||
csrTemplate, err := signer.ParseCertificateRequest(s, block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Copy out only the fields from the CSR authorized by policy.
|
||||
safeTemplate := x509.Certificate{}
|
||||
// If the profile contains no explicit whitelist, assume that all fields
|
||||
// should be copied from the CSR.
|
||||
if profile.CSRWhitelist == nil {
|
||||
safeTemplate = *csrTemplate
|
||||
} else {
|
||||
if profile.CSRWhitelist.Subject {
|
||||
safeTemplate.Subject = csrTemplate.Subject
|
||||
}
|
||||
if profile.CSRWhitelist.PublicKeyAlgorithm {
|
||||
safeTemplate.PublicKeyAlgorithm = csrTemplate.PublicKeyAlgorithm
|
||||
}
|
||||
if profile.CSRWhitelist.PublicKey {
|
||||
safeTemplate.PublicKey = csrTemplate.PublicKey
|
||||
}
|
||||
if profile.CSRWhitelist.SignatureAlgorithm {
|
||||
safeTemplate.SignatureAlgorithm = csrTemplate.SignatureAlgorithm
|
||||
}
|
||||
if profile.CSRWhitelist.DNSNames {
|
||||
safeTemplate.DNSNames = csrTemplate.DNSNames
|
||||
}
|
||||
if profile.CSRWhitelist.IPAddresses {
|
||||
safeTemplate.IPAddresses = csrTemplate.IPAddresses
|
||||
}
|
||||
if profile.CSRWhitelist.EmailAddresses {
|
||||
safeTemplate.EmailAddresses = csrTemplate.EmailAddresses
|
||||
}
|
||||
}
|
||||
|
||||
if req.CRLOverride != "" {
|
||||
safeTemplate.CRLDistributionPoints = []string{req.CRLOverride}
|
||||
}
|
||||
|
||||
if safeTemplate.IsCA {
|
||||
if !profile.CAConstraint.IsCA {
|
||||
log.Error("local signer policy disallows issuing CA certificate")
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
|
||||
}
|
||||
|
||||
if s.ca != nil && s.ca.MaxPathLen > 0 {
|
||||
if safeTemplate.MaxPathLen >= s.ca.MaxPathLen {
|
||||
log.Error("local signer certificate disallows CA MaxPathLen extending")
|
||||
// do not sign a cert with pathlen > current
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
|
||||
}
|
||||
} else if s.ca != nil && s.ca.MaxPathLen == 0 && s.ca.MaxPathLenZero {
|
||||
log.Error("local signer certificate disallows issuing CA certificate")
|
||||
// signer has pathlen of 0, do not sign more intermediate CAs
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.InvalidRequest)
|
||||
}
|
||||
}
|
||||
|
||||
OverrideHosts(&safeTemplate, req.Hosts)
|
||||
safeTemplate.Subject = PopulateSubjectFromCSR(req.Subject, safeTemplate.Subject)
|
||||
|
||||
// If there is a whitelist, ensure that both the Common Name and SAN DNSNames match
|
||||
if profile.NameWhitelist != nil {
|
||||
if safeTemplate.Subject.CommonName != "" {
|
||||
if profile.NameWhitelist.Find([]byte(safeTemplate.Subject.CommonName)) == nil {
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
|
||||
}
|
||||
}
|
||||
for _, name := range safeTemplate.DNSNames {
|
||||
if profile.NameWhitelist.Find([]byte(name)) == nil {
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
|
||||
}
|
||||
}
|
||||
for _, name := range safeTemplate.EmailAddresses {
|
||||
if profile.NameWhitelist.Find([]byte(name)) == nil {
|
||||
return nil, cferr.New(cferr.PolicyError, cferr.UnmatchedWhitelist)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if profile.ClientProvidesSerialNumbers {
|
||||
if req.Serial == nil {
|
||||
return nil, cferr.New(cferr.CertificateError, cferr.MissingSerial)
|
||||
}
|
||||
safeTemplate.SerialNumber = req.Serial
|
||||
} else {
|
||||
// RFC 5280 4.1.2.2:
|
||||
// Certificate users MUST be able to handle serialNumber
|
||||
// values up to 20 octets. Conforming CAs MUST NOT use
|
||||
// serialNumber values longer than 20 octets.
|
||||
//
|
||||
// If CFSSL is providing the serial numbers, it makes
|
||||
// sense to use the max supported size.
|
||||
serialNumber := make([]byte, 20)
|
||||
_, err = io.ReadFull(rand.Reader, serialNumber)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.Unknown, err)
|
||||
}
|
||||
|
||||
// SetBytes interprets buf as the bytes of a big-endian
|
||||
// unsigned integer. The leading byte should be masked
|
||||
// off to ensure it isn't negative.
|
||||
serialNumber[0] &= 0x7F
|
||||
|
||||
safeTemplate.SerialNumber = new(big.Int).SetBytes(serialNumber)
|
||||
}
|
||||
|
||||
if len(req.Extensions) > 0 {
|
||||
for _, ext := range req.Extensions {
|
||||
oid := asn1.ObjectIdentifier(ext.ID)
|
||||
if !profile.ExtensionWhitelist[oid.String()] {
|
||||
return nil, cferr.New(cferr.CertificateError, cferr.InvalidRequest)
|
||||
}
|
||||
|
||||
rawValue, err := hex.DecodeString(ext.Value)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CertificateError, cferr.InvalidRequest, err)
|
||||
}
|
||||
|
||||
safeTemplate.ExtraExtensions = append(safeTemplate.ExtraExtensions, pkix.Extension{
|
||||
Id: oid,
|
||||
Critical: ext.Critical,
|
||||
Value: rawValue,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var distPoints = safeTemplate.CRLDistributionPoints
|
||||
err = signer.FillTemplate(&safeTemplate, s.policy.Default, profile, req.NotBefore, req.NotAfter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if distPoints != nil && len(distPoints) > 0 {
|
||||
safeTemplate.CRLDistributionPoints = distPoints
|
||||
}
|
||||
|
||||
var certTBS = safeTemplate
|
||||
|
||||
if len(profile.CTLogServers) > 0 || req.ReturnPrecert {
|
||||
// Add a poison extension which prevents validation
|
||||
var poisonExtension = pkix.Extension{Id: signer.CTPoisonOID, Critical: true, Value: []byte{0x05, 0x00}}
|
||||
var poisonedPreCert = certTBS
|
||||
poisonedPreCert.ExtraExtensions = append(safeTemplate.ExtraExtensions, poisonExtension)
|
||||
cert, err = s.sign(&poisonedPreCert)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if req.ReturnPrecert {
|
||||
return cert, nil
|
||||
}
|
||||
|
||||
derCert, _ := pem.Decode(cert)
|
||||
prechain := []ct.ASN1Cert{{Data: derCert.Bytes}, {Data: s.ca.Raw}}
|
||||
var sctList []ct.SignedCertificateTimestamp
|
||||
|
||||
for _, server := range profile.CTLogServers {
|
||||
log.Infof("submitting poisoned precertificate to %s", server)
|
||||
ctclient, err := client.New(server, nil, jsonclient.Options{})
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.PrecertSubmissionFailed, err)
|
||||
}
|
||||
var resp *ct.SignedCertificateTimestamp
|
||||
ctx := context.Background()
|
||||
resp, err = ctclient.AddPreChain(ctx, prechain)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.PrecertSubmissionFailed, err)
|
||||
}
|
||||
sctList = append(sctList, *resp)
|
||||
}
|
||||
|
||||
var serializedSCTList []byte
|
||||
serializedSCTList, err = helpers.SerializeSCTList(sctList)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
|
||||
// Serialize again as an octet string before embedding
|
||||
serializedSCTList, err = asn1.Marshal(serializedSCTList)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
|
||||
var SCTListExtension = pkix.Extension{Id: signer.SCTListOID, Critical: false, Value: serializedSCTList}
|
||||
certTBS.ExtraExtensions = append(certTBS.ExtraExtensions, SCTListExtension)
|
||||
}
|
||||
var signedCert []byte
|
||||
signedCert, err = s.sign(&certTBS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get the AKI from signedCert. This is required to support Go 1.9+.
|
||||
// In prior versions of Go, x509.CreateCertificate updated the
|
||||
// AuthorityKeyId of certTBS.
|
||||
parsedCert, _ := helpers.ParseCertificatePEM(signedCert)
|
||||
|
||||
if s.dbAccessor != nil {
|
||||
var certRecord = certdb.CertificateRecord{
|
||||
Serial: certTBS.SerialNumber.String(),
|
||||
// this relies on the specific behavior of x509.CreateCertificate
|
||||
// which sets the AuthorityKeyId from the signer's SubjectKeyId
|
||||
AKI: hex.EncodeToString(parsedCert.AuthorityKeyId),
|
||||
CALabel: req.Label,
|
||||
Status: "good",
|
||||
Expiry: certTBS.NotAfter,
|
||||
PEM: string(signedCert),
|
||||
}
|
||||
|
||||
err = s.dbAccessor.InsertCertificate(certRecord)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debug("saved certificate with serial number ", certTBS.SerialNumber)
|
||||
}
|
||||
|
||||
return signedCert, nil
|
||||
}
|
||||
|
||||
// SignFromPrecert creates and signs a certificate from an existing precertificate
|
||||
// that was previously signed by Signer.ca and inserts the provided SCTs into the
|
||||
// new certificate. The resulting certificate will be a exact copy of the precert
|
||||
// except for the removal of the poison extension and the addition of the SCT list
|
||||
// extension. SignFromPrecert does not verify that the contents of the certificate
|
||||
// still match the signing profile of the signer, it only requires that the precert
|
||||
// was previously signed by the Signers CA.
|
||||
func (s *Signer) SignFromPrecert(precert *x509.Certificate, scts []ct.SignedCertificateTimestamp) ([]byte, error) {
|
||||
// Verify certificate was signed by s.ca
|
||||
if err := precert.CheckSignatureFrom(s.ca); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Verify certificate is a precert
|
||||
isPrecert := false
|
||||
poisonIndex := 0
|
||||
for i, ext := range precert.Extensions {
|
||||
if ext.Id.Equal(signer.CTPoisonOID) {
|
||||
if !ext.Critical {
|
||||
return nil, cferr.New(cferr.CTError, cferr.PrecertInvalidPoison)
|
||||
}
|
||||
// Check extension contains ASN.1 NULL
|
||||
if bytes.Compare(ext.Value, []byte{0x05, 0x00}) != 0 {
|
||||
return nil, cferr.New(cferr.CTError, cferr.PrecertInvalidPoison)
|
||||
}
|
||||
isPrecert = true
|
||||
poisonIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isPrecert {
|
||||
return nil, cferr.New(cferr.CTError, cferr.PrecertMissingPoison)
|
||||
}
|
||||
|
||||
// Serialize SCTs into list format and create extension
|
||||
serializedList, err := helpers.SerializeSCTList(scts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Serialize again as an octet string before embedding
|
||||
serializedList, err = asn1.Marshal(serializedList)
|
||||
if err != nil {
|
||||
return nil, cferr.Wrap(cferr.CTError, cferr.Unknown, err)
|
||||
}
|
||||
sctExt := pkix.Extension{Id: signer.SCTListOID, Critical: false, Value: serializedList}
|
||||
|
||||
// Create the new tbsCert from precert. Do explicit copies of any slices so that we don't
|
||||
// use memory that may be altered by us or the caller at a later stage.
|
||||
tbsCert := x509.Certificate{
|
||||
SignatureAlgorithm: precert.SignatureAlgorithm,
|
||||
PublicKeyAlgorithm: precert.PublicKeyAlgorithm,
|
||||
PublicKey: precert.PublicKey,
|
||||
Version: precert.Version,
|
||||
SerialNumber: precert.SerialNumber,
|
||||
Issuer: precert.Issuer,
|
||||
Subject: precert.Subject,
|
||||
NotBefore: precert.NotBefore,
|
||||
NotAfter: precert.NotAfter,
|
||||
KeyUsage: precert.KeyUsage,
|
||||
BasicConstraintsValid: precert.BasicConstraintsValid,
|
||||
IsCA: precert.IsCA,
|
||||
MaxPathLen: precert.MaxPathLen,
|
||||
MaxPathLenZero: precert.MaxPathLenZero,
|
||||
PermittedDNSDomainsCritical: precert.PermittedDNSDomainsCritical,
|
||||
}
|
||||
if len(precert.Extensions) > 0 {
|
||||
tbsCert.ExtraExtensions = make([]pkix.Extension, len(precert.Extensions))
|
||||
copy(tbsCert.ExtraExtensions, precert.Extensions)
|
||||
}
|
||||
|
||||
// Remove the poison extension from ExtraExtensions
|
||||
tbsCert.ExtraExtensions = append(tbsCert.ExtraExtensions[:poisonIndex], tbsCert.ExtraExtensions[poisonIndex+1:]...)
|
||||
// Insert the SCT list extension
|
||||
tbsCert.ExtraExtensions = append(tbsCert.ExtraExtensions, sctExt)
|
||||
|
||||
// Sign the tbsCert
|
||||
return s.sign(&tbsCert)
|
||||
}
|
||||
|
||||
// Info return a populated info.Resp struct or an error.
|
||||
func (s *Signer) Info(req info.Req) (resp *info.Resp, err error) {
|
||||
cert, err := s.Certificate(req.Label, req.Profile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
profile, err := signer.Profile(s, req.Profile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
resp = new(info.Resp)
|
||||
if cert.Raw != nil {
|
||||
resp.Certificate = string(bytes.TrimSpace(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})))
|
||||
}
|
||||
resp.Usage = profile.Usage
|
||||
resp.ExpiryString = profile.ExpiryString
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SigAlgo returns the RSA signer's signature algorithm.
|
||||
func (s *Signer) SigAlgo() x509.SignatureAlgorithm {
|
||||
return s.sigAlgo
|
||||
}
|
||||
|
||||
// Certificate returns the signer's certificate.
|
||||
func (s *Signer) Certificate(label, profile string) (*x509.Certificate, error) {
|
||||
cert := *s.ca
|
||||
return &cert, nil
|
||||
}
|
||||
|
||||
// SetPolicy sets the signer's signature policy.
|
||||
func (s *Signer) SetPolicy(policy *config.Signing) {
|
||||
s.policy = policy
|
||||
}
|
||||
|
||||
// SetDBAccessor sets the signers' cert db accessor
|
||||
func (s *Signer) SetDBAccessor(dba certdb.Accessor) {
|
||||
s.dbAccessor = dba
|
||||
}
|
||||
|
||||
// GetDBAccessor returns the signers' cert db accessor
|
||||
func (s *Signer) GetDBAccessor() certdb.Accessor {
|
||||
return s.dbAccessor
|
||||
}
|
||||
|
||||
// SetReqModifier does nothing for local
|
||||
func (s *Signer) SetReqModifier(func(*http.Request, []byte)) {
|
||||
// noop
|
||||
}
|
||||
|
||||
// Policy returns the signer's policy.
|
||||
func (s *Signer) Policy() *config.Signing {
|
||||
return s.policy
|
||||
}
|
1423
vendor/github.com/cloudflare/cfssl/signer/local/local_test.go
generated
vendored
Normal file
1423
vendor/github.com/cloudflare/cfssl/signer/local/local_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
vendor/github.com/cloudflare/cfssl/signer/local/testdata/build_inter_pathlen_csrs.sh
generated
vendored
Normal file
3
vendor/github.com/cloudflare/cfssl/signer/local/testdata/build_inter_pathlen_csrs.sh
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
echo '{ "CN": "Pathlen 0 Issuer", "ca": { "pathlen": 0, "pathlenzero": true } }' | cfssl genkey -initca - | cfssljson -bare inter_pathlen_0
|
||||
echo '{ "CN": "Pathlen 1 Issuer", "ca": { "pathlen": 1 } }' | cfssl genkey -initca - | cfssljson -bare inter_pathlen_1
|
||||
echo '{ "CN": "Pathlen Unspecified", "ca": {} }' | cfssl genkey -initca - | cfssljson -bare inter_pathlen_unspecified
|
27
vendor/github.com/cloudflare/cfssl/signer/local/testdata/ca.pem
generated
vendored
Normal file
27
vendor/github.com/cloudflare/cfssl/signer/local/testdata/ca.pem
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEmzCCA4OgAwIBAgIMAMSvNBgypwaaSQ5iMA0GCSqGSIb3DQEBBQUAMIGMMQsw
|
||||
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
|
||||
YW5jaXNjbzETMBEGA1UEChMKQ0ZTU0wgVEVTVDEbMBkGA1UEAxMSQ0ZTU0wgVEVT
|
||||
VCBSb290IENBMR4wHAYJKoZIhvcNAQkBFg90ZXN0QHRlc3QubG9jYWwwHhcNMTIx
|
||||
MjEyMDIxMDMxWhcNMjIxMDIxMDIxMDMxWjCBjDELMAkGA1UEBhMCVVMxEzARBgNV
|
||||
BAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEzARBgNVBAoT
|
||||
CkNGU1NMIFRFU1QxGzAZBgNVBAMTEkNGU1NMIFRFU1QgUm9vdCBDQTEeMBwGCSqG
|
||||
SIb3DQEJARYPdGVzdEB0ZXN0LmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEAsRp1xSfIDoD/40Bo4Hls3sFn4dav5NgxbZGpVyGF7dJI9u0eEnL4
|
||||
BUGssPaUFLWC83CZxujUEiEfE0oKX+uOhhGv3+j5xSTNM764m2eSiN53cdZtK05d
|
||||
hwq9uS8LtjKOQeN1mQ5qmiqxBMdjkKgMsVw5lMCgoYKo57kaKFyXzdpNVDzqw+pt
|
||||
HWmuNtDQjK3qT5Ma06mYPmIGYhIZYLY7oJGg9ZEaNR0GIw4zIT5JRsNiaSb5wTLw
|
||||
aa0n/4vLJyVjLJcYmJBvZWj8g+taK+C4INu/jGux+bmsC9hq14tbOaTNAn/NE0qN
|
||||
8oHwcRBEqfOdEYdZkxI5NWPiKNW/Q+AeXQIDAQABo4H6MIH3MB0GA1UdDgQWBBS3
|
||||
0veEuqg51fusEM4p/YuWpBPsvTCBxAYDVR0jBIG8MIG5gBS30veEuqg51fusEM4p
|
||||
/YuWpBPsvaGBkqSBjzCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3Ju
|
||||
aWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xEzARBgNVBAoTCkNGU1NMIFRFU1Qx
|
||||
GzAZBgNVBAMTEkNGU1NMIFRFU1QgUm9vdCBDQTEeMBwGCSqGSIb3DQEJARYPdGVz
|
||||
dEB0ZXN0LmxvY2FsggwAxK80GDKnBppJDmIwDwYDVR0TBAgwBgEB/wIBADANBgkq
|
||||
hkiG9w0BAQUFAAOCAQEAJ7r1EZYDwed6rS0+YKHdkRGRQ5Rz6A9DIVBPXrSMAGj3
|
||||
F5EF2m/GJbhpVbnNJTVlgP9DDyabOZNxzdrCr4cHMkYYnocDdgAodnkw6GZ/GJTc
|
||||
depbVTR4TpihFNzeDEGJePrEwM1DouGswpu97jyuCYZ3z1a60+a+3C1GwWaJ7Aet
|
||||
Uqm+yLTUrMISsfnDPqJdM1NeqW3jiZ4IgcqJkieCCSpag9Xuzrp9q6rjmePvlQkv
|
||||
qz020JGg6VijJ+c6Tf5y0XqbAhkBTqYtVamu9gEth9utn12EhdNjTZMPKMjjgFUd
|
||||
H0N6yOEuQMl4ky7RxZBM0iPyeob6i4z2LEQilgv9MQ==
|
||||
-----END CERTIFICATE-----
|
28
vendor/github.com/cloudflare/cfssl/signer/local/testdata/ca_key.pem
generated
vendored
Normal file
28
vendor/github.com/cloudflare/cfssl/signer/local/testdata/ca_key.pem
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCxGnXFJ8gOgP/j
|
||||
QGjgeWzewWfh1q/k2DFtkalXIYXt0kj27R4ScvgFQayw9pQUtYLzcJnG6NQSIR8T
|
||||
Sgpf646GEa/f6PnFJM0zvribZ5KI3ndx1m0rTl2HCr25Lwu2Mo5B43WZDmqaKrEE
|
||||
x2OQqAyxXDmUwKChgqjnuRooXJfN2k1UPOrD6m0daa420NCMrepPkxrTqZg+YgZi
|
||||
EhlgtjugkaD1kRo1HQYjDjMhPklGw2JpJvnBMvBprSf/i8snJWMslxiYkG9laPyD
|
||||
61or4Lgg27+Ma7H5uawL2GrXi1s5pM0Cf80TSo3ygfBxEESp850Rh1mTEjk1Y+Io
|
||||
1b9D4B5dAgMBAAECggEAKHhjcSomDSptTwDo9mLI/h40HudwSlsc8GzYxZBjinUD
|
||||
N2n39T9QbeMUE1xFenX/9qFEgq+xxnLLJx1EQacSapCgIAqdCO/f9HMgvGJumdg8
|
||||
c0cMq1i9Bp7tu+OESZ5D48qWlOM2eQRIb08g8W11eRIaFmPuUPoKnuktkQuXpPJc
|
||||
YbS/+JuA8SDwe6sV0cMCQuS+iHFfeGwWCKrDUkhLwcL3waW3od2XFyOeFFWFhl0h
|
||||
HmM/mWKRuRdqR7hrmArTwFZVkB+o/1ywVYXIv+JQm0eNZ5PKLNJGL2f5oxbMR/JI
|
||||
AoK0bAlJmYaFp96h1KpbPwLEL/0hHSWA7sAyJIgQAQKBgQDaEAZor/w4ZUTekT1+
|
||||
cbId0yA+ikDXQOfXaNCSh9Pex+Psjd5zVVOqyVFJ29daRju3d7rmpN4Cm5V4h0l1
|
||||
/2ad207rjCAnpCHtaddJWNyJzF2IL2IaoCZQRp0k7zOjBGQpoWDTwBaEin5CCv3P
|
||||
kkdQkKz6FDP1xskHSLZr21/QCQKBgQDP6jXutEgGjf3yKpMFk/69EamJdon8clbt
|
||||
hl7cOyWtobnZhdOWVZPe00Oo3Jag2aWgFFsm3EtwnUCnR4d4+fXRKS2LkhfIUZcz
|
||||
cKy17Ileggdd8UGhL4RDrF/En9tJL86WcVkcoOrqLcGB2FLWrVhVpHFK74eLMCH/
|
||||
uc/+ioPItQKBgHYoDsD08s7AGMQcoNx90MyWVLduhFnegoFW+wUa8jOZzieka6/E
|
||||
wVQeR5yksZjpy3vLNYu6M83n7eLkM2rrm/fXGHlLcTTpm7SgEBZfPwivotKjEh5p
|
||||
PrlqucWEk082lutz1RqHz+u7e1Rfzk2F7nx6GDBdeBYpw03eGXJx6QW5AoGBAIJq
|
||||
4puyAEAET1fZNtHX7IGCk7sDXTi6LCbgE57HhzHr8V0t4fQ6CABMuvMwM1gATjEk
|
||||
s6yjoLqqGUUUzDipanViBAy5fiuManC868lN7zkWDTLzQ3ytBqVAee4na/DziP27
|
||||
ae9YTSLJwskE/alloLRP6zTbHUXE0n7LelmrX1DFAoGBAMFLl+Lu+WFgCHxBjn43
|
||||
rHpJbQZQmsFhAMhkN4hsj6dJfAGn2gRLRiVRAika+8QF65xMZiVQWUVSUZADWERi
|
||||
0SXGjzN1wYxO3Qzy3LYwws6fxFAq5lo79eb38yFT2lHdqK3x/QgiDSRVl+R6cExV
|
||||
xQB518/lp2eIeMpglWByDwJX
|
||||
-----END PRIVATE KEY-----
|
10
vendor/github.com/cloudflare/cfssl/signer/local/testdata/ecdsa256-inter.csr
generated
vendored
Normal file
10
vendor/github.com/cloudflare/cfssl/signer/local/testdata/ecdsa256-inter.csr
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIIBezCCASECAQAwgYwxCzAJBgNVBAYTAlVTMRMwEQYDVQQKEwpDbG91ZEZsYXJl
|
||||
MRwwGgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRYwFAYDVQQHEw1TYW4gRnJh
|
||||
bmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMR0wGwYDVQQDExRjbG91ZGZsYXJl
|
||||
LWludGVyLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLgOKlWwIAIeURde
|
||||
yvDMhgfn6xPp1gn8oUeLmsniBm7I+j84IsVzUso8/MpjMZ9nB8lQUanhv3Kmqcyj
|
||||
HNj+iFegMjAwBgkqhkiG9w0BCQ4xIzAhMB8GA1UdEQQYMBaCFGNsb3VkZmxhcmUt
|
||||
aW50ZXIuY29tMAoGCCqGSM49BAMCA0gAMEUCIEJcy2mn2YyK8lVE+HHmr2OsmdbH
|
||||
4CLDVXFBwxke8ObqAiEAx/il1cDKvQ/I36b4XjBnOX2jcQ5oaCNPFFBE74WQ/ps=
|
||||
-----END CERTIFICATE REQUEST-----
|
5
vendor/github.com/cloudflare/cfssl/signer/local/testdata/ecdsa256-inter.key
generated
vendored
Normal file
5
vendor/github.com/cloudflare/cfssl/signer/local/testdata/ecdsa256-inter.key
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEILbwI4u4bw+HtafMqFnrL7LOrqNEZH5rW5ygSrigfrVLoAoGCCqGSM49
|
||||
AwEHoUQDQgAEuA4qVbAgAh5RF17K8MyGB+frE+nWCfyhR4uayeIGbsj6PzgixXNS
|
||||
yjz8ymMxn2cHyVBRqeG/cqapzKMc2P6IVw==
|
||||
-----END EC PRIVATE KEY-----
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user