vendor
This commit is contained in:
143
vendor/github.com/google/certificate-transparency-go/x509/cert_pool.go
generated
vendored
Normal file
143
vendor/github.com/google/certificate-transparency-go/x509/cert_pool.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// CertPool is a set of certificates.
|
||||
type CertPool struct {
|
||||
bySubjectKeyId map[string][]int
|
||||
byName map[string][]int
|
||||
certs []*Certificate
|
||||
}
|
||||
|
||||
// NewCertPool returns a new, empty CertPool.
|
||||
func NewCertPool() *CertPool {
|
||||
return &CertPool{
|
||||
bySubjectKeyId: make(map[string][]int),
|
||||
byName: make(map[string][]int),
|
||||
}
|
||||
}
|
||||
|
||||
// SystemCertPool returns a copy of the system cert pool.
|
||||
//
|
||||
// Any mutations to the returned pool are not written to disk and do
|
||||
// not affect any other pool.
|
||||
func SystemCertPool() (*CertPool, error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// Issue 16736, 18609:
|
||||
return nil, errors.New("crypto/x509: system root pool is not available on Windows")
|
||||
}
|
||||
|
||||
return loadSystemRoots()
|
||||
}
|
||||
|
||||
// findVerifiedParents attempts to find certificates in s which have signed the
|
||||
// given certificate. If any candidates were rejected then errCert will be set
|
||||
// to one of them, arbitrarily, and err will contain the reason that it was
|
||||
// rejected.
|
||||
func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
var candidates []int
|
||||
|
||||
if len(cert.AuthorityKeyId) > 0 {
|
||||
candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
candidates = s.byName[string(cert.RawIssuer)]
|
||||
}
|
||||
|
||||
for _, c := range candidates {
|
||||
if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
|
||||
parents = append(parents, c)
|
||||
} else {
|
||||
errCert = s.certs[c]
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *CertPool) contains(cert *Certificate) bool {
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
candidates := s.byName[string(cert.RawSubject)]
|
||||
for _, c := range candidates {
|
||||
if s.certs[c].Equal(cert) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// AddCert adds a certificate to a pool.
|
||||
func (s *CertPool) AddCert(cert *Certificate) {
|
||||
if cert == nil {
|
||||
panic("adding nil Certificate to CertPool")
|
||||
}
|
||||
|
||||
// Check that the certificate isn't being added twice.
|
||||
if s.contains(cert) {
|
||||
return
|
||||
}
|
||||
|
||||
n := len(s.certs)
|
||||
s.certs = append(s.certs, cert)
|
||||
|
||||
if len(cert.SubjectKeyId) > 0 {
|
||||
keyId := string(cert.SubjectKeyId)
|
||||
s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
|
||||
}
|
||||
name := string(cert.RawSubject)
|
||||
s.byName[name] = append(s.byName[name], n)
|
||||
}
|
||||
|
||||
// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
|
||||
// It appends any certificates found to s and reports whether any certificates
|
||||
// were successfully parsed.
|
||||
//
|
||||
// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
|
||||
// of root CAs in a format suitable for this function.
|
||||
func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
|
||||
for len(pemCerts) > 0 {
|
||||
var block *pem.Block
|
||||
block, pemCerts = pem.Decode(pemCerts)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
s.AddCert(cert)
|
||||
ok = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Subjects returns a list of the DER-encoded subjects of
|
||||
// all of the certificates in the pool.
|
||||
func (s *CertPool) Subjects() [][]byte {
|
||||
res := make([][]byte, len(s.certs))
|
||||
for i, c := range s.certs {
|
||||
res[i] = c.RawSubject
|
||||
}
|
||||
return res
|
||||
}
|
230
vendor/github.com/google/certificate-transparency-go/x509/error.go
generated
vendored
Normal file
230
vendor/github.com/google/certificate-transparency-go/x509/error.go
generated
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
package x509
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Error implements the error interface and describes a single error in an X.509 certificate or CRL.
|
||||
type Error struct {
|
||||
ID ErrorID
|
||||
Category ErrCategory
|
||||
Summary string
|
||||
Field string
|
||||
SpecRef string
|
||||
SpecText string
|
||||
// Fatal indicates that parsing has been aborted.
|
||||
Fatal bool
|
||||
}
|
||||
|
||||
func (err Error) Error() string {
|
||||
var msg bytes.Buffer
|
||||
if err.ID != ErrInvalidID {
|
||||
if err.Fatal {
|
||||
msg.WriteRune('E')
|
||||
} else {
|
||||
msg.WriteRune('W')
|
||||
}
|
||||
msg.WriteString(fmt.Sprintf("%03d: ", err.ID))
|
||||
}
|
||||
msg.WriteString(err.Summary)
|
||||
return msg.String()
|
||||
}
|
||||
|
||||
// VerboseError creates a more verbose error string, including spec details.
|
||||
func (err Error) VerboseError() string {
|
||||
var msg bytes.Buffer
|
||||
msg.WriteString(err.Error())
|
||||
if len(err.Field) > 0 || err.Category != UnknownCategory || len(err.SpecRef) > 0 || len(err.SpecText) > 0 {
|
||||
msg.WriteString(" (")
|
||||
needSep := false
|
||||
if len(err.Field) > 0 {
|
||||
msg.WriteString(err.Field)
|
||||
needSep = true
|
||||
}
|
||||
if err.Category != UnknownCategory {
|
||||
if needSep {
|
||||
msg.WriteString(": ")
|
||||
}
|
||||
msg.WriteString(err.Category.String())
|
||||
needSep = true
|
||||
}
|
||||
if len(err.SpecRef) > 0 {
|
||||
if needSep {
|
||||
msg.WriteString(": ")
|
||||
}
|
||||
msg.WriteString(err.SpecRef)
|
||||
needSep = true
|
||||
}
|
||||
if len(err.SpecText) > 0 {
|
||||
if needSep {
|
||||
if len(err.SpecRef) > 0 {
|
||||
msg.WriteString(", ")
|
||||
} else {
|
||||
msg.WriteString(": ")
|
||||
}
|
||||
}
|
||||
msg.WriteString("'")
|
||||
msg.WriteString(err.SpecText)
|
||||
msg.WriteString("'")
|
||||
}
|
||||
msg.WriteString(")")
|
||||
}
|
||||
|
||||
return msg.String()
|
||||
}
|
||||
|
||||
// ErrCategory indicates the category of an x509.Error.
|
||||
type ErrCategory int
|
||||
|
||||
// ErrCategory values.
|
||||
const (
|
||||
UnknownCategory ErrCategory = iota
|
||||
// Errors in ASN.1 encoding
|
||||
InvalidASN1Encoding
|
||||
InvalidASN1Content
|
||||
InvalidASN1DER
|
||||
// Errors in ASN.1 relative to schema
|
||||
InvalidValueRange
|
||||
InvalidASN1Type
|
||||
UnexpectedAdditionalData
|
||||
// Errors in X.509
|
||||
PoorlyFormedCertificate // Fails a SHOULD clause
|
||||
MalformedCertificate // Fails a MUST clause
|
||||
PoorlyFormedCRL // Fails a SHOULD clause
|
||||
MalformedCRL // Fails a MUST clause
|
||||
// Errors relative to CA/Browser Forum guidelines
|
||||
BaselineRequirementsFailure
|
||||
EVRequirementsFailure
|
||||
// Other errors
|
||||
InsecureAlgorithm
|
||||
UnrecognizedValue
|
||||
)
|
||||
|
||||
func (category ErrCategory) String() string {
|
||||
switch category {
|
||||
case InvalidASN1Encoding:
|
||||
return "Invalid ASN.1 encoding"
|
||||
case InvalidASN1Content:
|
||||
return "Invalid ASN.1 content"
|
||||
case InvalidASN1DER:
|
||||
return "Invalid ASN.1 distinguished encoding"
|
||||
case InvalidValueRange:
|
||||
return "Invalid value for range given in schema"
|
||||
case InvalidASN1Type:
|
||||
return "Invalid ASN.1 type for schema"
|
||||
case UnexpectedAdditionalData:
|
||||
return "Unexpected additional data present"
|
||||
case PoorlyFormedCertificate:
|
||||
return "Certificate does not comply with SHOULD clause in spec"
|
||||
case MalformedCertificate:
|
||||
return "Certificate does not comply with MUST clause in spec"
|
||||
case PoorlyFormedCRL:
|
||||
return "Certificate Revocation List does not comply with SHOULD clause in spec"
|
||||
case MalformedCRL:
|
||||
return "Certificate Revocation List does not comply with MUST clause in spec"
|
||||
case BaselineRequirementsFailure:
|
||||
return "Certificate does not comply with CA/BF baseline requirements"
|
||||
case EVRequirementsFailure:
|
||||
return "Certificate does not comply with CA/BF EV requirements"
|
||||
case InsecureAlgorithm:
|
||||
return "Certificate uses an insecure algorithm"
|
||||
case UnrecognizedValue:
|
||||
return "Certificate uses an unrecognized value"
|
||||
default:
|
||||
return fmt.Sprintf("Unknown (%d)", category)
|
||||
}
|
||||
}
|
||||
|
||||
// ErrorID is an identifier for an x509.Error, to allow filtering.
|
||||
type ErrorID int
|
||||
|
||||
// Errors implements the error interface and holds a collection of errors found in a certificate or CRL.
|
||||
type Errors struct {
|
||||
Errs []Error
|
||||
}
|
||||
|
||||
// Error converts to a string.
|
||||
func (e *Errors) Error() string {
|
||||
return e.combineErrors(Error.Error)
|
||||
}
|
||||
|
||||
// VerboseError creates a more verbose error string, including spec details.
|
||||
func (e *Errors) VerboseError() string {
|
||||
return e.combineErrors(Error.VerboseError)
|
||||
}
|
||||
|
||||
// Fatal indicates whether e includes a fatal error
|
||||
func (e *Errors) Fatal() bool {
|
||||
return (e.FirstFatal() != nil)
|
||||
}
|
||||
|
||||
// Empty indicates whether e has no errors.
|
||||
func (e *Errors) Empty() bool {
|
||||
return len(e.Errs) == 0
|
||||
}
|
||||
|
||||
// FirstFatal returns the first fatal error in e, or nil
|
||||
// if there is no fatal error.
|
||||
func (e *Errors) FirstFatal() error {
|
||||
for _, err := range e.Errs {
|
||||
if err.Fatal {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// AddID adds the Error identified by the given id to an x509.Errors.
|
||||
func (e *Errors) AddID(id ErrorID, args ...interface{}) {
|
||||
e.Errs = append(e.Errs, NewError(id, args...))
|
||||
}
|
||||
|
||||
func (e Errors) combineErrors(errfn func(Error) string) string {
|
||||
if len(e.Errs) == 0 {
|
||||
return ""
|
||||
}
|
||||
if len(e.Errs) == 1 {
|
||||
return errfn((e.Errs)[0])
|
||||
}
|
||||
var msg bytes.Buffer
|
||||
msg.WriteString("Errors:")
|
||||
for _, err := range e.Errs {
|
||||
msg.WriteString("\n ")
|
||||
msg.WriteString(errfn(err))
|
||||
}
|
||||
return msg.String()
|
||||
}
|
||||
|
||||
// Filter creates a new Errors object with any entries from the filtered
|
||||
// list of IDs removed.
|
||||
func (e Errors) Filter(filtered []ErrorID) Errors {
|
||||
var results Errors
|
||||
eloop:
|
||||
for _, v := range e.Errs {
|
||||
for _, f := range filtered {
|
||||
if v.ID == f {
|
||||
break eloop
|
||||
}
|
||||
}
|
||||
results.Errs = append(results.Errs, v)
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
// ErrorFilter builds a list of error IDs (suitable for use with Errors.Filter) from a comma-separated string.
|
||||
func ErrorFilter(ignore string) []ErrorID {
|
||||
var ids []ErrorID
|
||||
filters := strings.Split(ignore, ",")
|
||||
for _, f := range filters {
|
||||
v, err := strconv.Atoi(f)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, ErrorID(v))
|
||||
}
|
||||
return ids
|
||||
}
|
192
vendor/github.com/google/certificate-transparency-go/x509/error_test.go
generated
vendored
Normal file
192
vendor/github.com/google/certificate-transparency-go/x509/error_test.go
generated
vendored
Normal file
@ -0,0 +1,192 @@
|
||||
package x509_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/google/certificate-transparency-go/x509"
|
||||
)
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
var tests = []struct {
|
||||
errs []x509.Error
|
||||
want string
|
||||
wantVerbose string
|
||||
wantFatal bool
|
||||
}{
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{Summary: "Error", Field: "a.b.c"},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error (a.b.c)",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{
|
||||
Summary: "Error",
|
||||
Field: "a.b.c",
|
||||
SpecRef: "RFC5280 s4.1.2.2",
|
||||
SpecText: "The serial number MUST be a positive integer",
|
||||
Category: x509.MalformedCertificate,
|
||||
},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error (a.b.c: Certificate does not comply with MUST clause in spec: RFC5280 s4.1.2.2, 'The serial number MUST be a positive integer')",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{
|
||||
Summary: "Error",
|
||||
Field: "a.b.c",
|
||||
SpecRef: "RFC5280 s4.1.2.2",
|
||||
SpecText: "The serial number MUST be a positive integer",
|
||||
},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error (a.b.c: RFC5280 s4.1.2.2, 'The serial number MUST be a positive integer')",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{
|
||||
Summary: "Error",
|
||||
Field: "a.b.c",
|
||||
SpecRef: "RFC5280 s4.1.2.2",
|
||||
Category: x509.MalformedCertificate,
|
||||
},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error (a.b.c: Certificate does not comply with MUST clause in spec: RFC5280 s4.1.2.2)",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{
|
||||
Summary: "Error",
|
||||
Field: "a.b.c",
|
||||
SpecText: "The serial number MUST be a positive integer",
|
||||
Category: x509.MalformedCertificate,
|
||||
},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error (a.b.c: Certificate does not comply with MUST clause in spec: 'The serial number MUST be a positive integer')",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{
|
||||
Summary: "Error",
|
||||
Field: "a.b.c",
|
||||
SpecRef: "RFC5280 s4.1.2.2",
|
||||
},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error (a.b.c: RFC5280 s4.1.2.2)",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{
|
||||
Summary: "Error",
|
||||
Field: "a.b.c",
|
||||
SpecText: "The serial number MUST be a positive integer",
|
||||
},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error (a.b.c: 'The serial number MUST be a positive integer')",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{
|
||||
Summary: "Error",
|
||||
Field: "a.b.c",
|
||||
Category: x509.MalformedCertificate,
|
||||
},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error (a.b.c: Certificate does not comply with MUST clause in spec)",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{Summary: "Error"},
|
||||
},
|
||||
want: "Error",
|
||||
wantVerbose: "Error",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{Summary: "Error\nwith newline", Field: "x", Category: x509.InvalidASN1DER},
|
||||
},
|
||||
want: "Error\nwith newline",
|
||||
wantVerbose: "Error\nwith newline (x: Invalid ASN.1 distinguished encoding)",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{Summary: "Error1", Field: "a.b.c"},
|
||||
{Summary: "Error2", Field: "a.b.c.d"},
|
||||
{Summary: "Error3", Field: "x.y.z"},
|
||||
},
|
||||
want: "Errors:\n Error1\n Error2\n Error3",
|
||||
wantVerbose: "Errors:\n Error1 (a.b.c)\n Error2 (a.b.c.d)\n Error3 (x.y.z)",
|
||||
},
|
||||
{
|
||||
errs: []x509.Error{
|
||||
{Summary: "Error1", Field: "a.b.c"},
|
||||
{Summary: "Error2", Field: "a.b.c.d", Fatal: true},
|
||||
{Summary: "Error3", Field: "x.y.z"},
|
||||
},
|
||||
want: "Errors:\n Error1\n Error2\n Error3",
|
||||
wantVerbose: "Errors:\n Error1 (a.b.c)\n Error2 (a.b.c.d)\n Error3 (x.y.z)",
|
||||
wantFatal: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
errs := x509.Errors{Errs: test.errs}
|
||||
if got := errs.Error(); got != test.want {
|
||||
t.Errorf("Errors(%+v).Error()=%q; want %q", test.errs, got, test.want)
|
||||
}
|
||||
if got := errs.VerboseError(); got != test.wantVerbose {
|
||||
t.Errorf("Errors(%+v).VerboseError()=%q; want %q", test.errs, got, test.wantVerbose)
|
||||
}
|
||||
if got := errs.Fatal(); got != test.wantFatal {
|
||||
t.Errorf("Errors(%+v).Fatal()=%v; want %v", test.errs, got, test.wantFatal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorsAppend(t *testing.T) {
|
||||
var errs x509.Errors
|
||||
if got, want := errs.Error(), ""; got != want {
|
||||
t.Errorf("Errors().Error()=%q; want %q", got, want)
|
||||
}
|
||||
if got, want := errs.Empty(), true; got != want {
|
||||
t.Errorf("Errors().Empty()=%t; want %t", got, want)
|
||||
}
|
||||
errs.Errs = append(errs.Errs, x509.Error{
|
||||
Summary: "Error",
|
||||
Field: "a.b.c",
|
||||
SpecRef: "RFC5280 s4.1.2.2"})
|
||||
if got, want := errs.VerboseError(), "Error (a.b.c: RFC5280 s4.1.2.2)"; got != want {
|
||||
t.Errorf("Errors(%+v).Error=%q; want %q", errs, got, want)
|
||||
}
|
||||
if got, want := errs.Empty(), false; got != want {
|
||||
t.Errorf("Errors().Empty()=%t; want %t", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorsFilter(t *testing.T) {
|
||||
var errs x509.Errors
|
||||
id := x509.ErrMaxID + 2
|
||||
errs.AddID(id, "arg1", 2, "arg3")
|
||||
baseErr := errs.Error()
|
||||
|
||||
errs.AddID(x509.ErrMaxID + 1)
|
||||
if got, want := errs.Error(), fmt.Sprintf("Errors:\n %s\n E%03d: Unknown error ID %v: args []", baseErr, x509.ErrMaxID+1, x509.ErrMaxID+1); got != want {
|
||||
t.Errorf("Errors(%+v).Error=%q; want %q", errs, got, want)
|
||||
}
|
||||
|
||||
errList := fmt.Sprintf("%d, %d", x509.ErrMaxID+1, x509.ErrMaxID+1)
|
||||
filter := x509.ErrorFilter(errList)
|
||||
errs2 := errs.Filter(filter)
|
||||
if got, want := errs2.Error(), baseErr; got != want {
|
||||
t.Errorf("Errors(%+v).Error=%q; want %q", errs, got, want)
|
||||
}
|
||||
}
|
302
vendor/github.com/google/certificate-transparency-go/x509/errors.go
generated
vendored
Normal file
302
vendor/github.com/google/certificate-transparency-go/x509/errors.go
generated
vendored
Normal file
@ -0,0 +1,302 @@
|
||||
package x509
|
||||
|
||||
import "fmt"
|
||||
|
||||
// To preserve error IDs, only append to this list, never insert.
|
||||
const (
|
||||
ErrInvalidID ErrorID = iota
|
||||
ErrInvalidCertList
|
||||
ErrTrailingCertList
|
||||
ErrUnexpectedlyCriticalCertListExtension
|
||||
ErrUnexpectedlyNonCriticalCertListExtension
|
||||
ErrInvalidCertListAuthKeyID
|
||||
ErrTrailingCertListAuthKeyID
|
||||
ErrInvalidCertListIssuerAltName
|
||||
ErrInvalidCertListCRLNumber
|
||||
ErrTrailingCertListCRLNumber
|
||||
ErrNegativeCertListCRLNumber
|
||||
ErrInvalidCertListDeltaCRL
|
||||
ErrTrailingCertListDeltaCRL
|
||||
ErrNegativeCertListDeltaCRL
|
||||
ErrInvalidCertListIssuingDP
|
||||
ErrTrailingCertListIssuingDP
|
||||
ErrCertListIssuingDPMultipleTypes
|
||||
ErrCertListIssuingDPInvalidFullName
|
||||
ErrInvalidCertListFreshestCRL
|
||||
ErrInvalidCertListAuthInfoAccess
|
||||
ErrTrailingCertListAuthInfoAccess
|
||||
ErrUnhandledCriticalCertListExtension
|
||||
ErrUnexpectedlyCriticalRevokedCertExtension
|
||||
ErrUnexpectedlyNonCriticalRevokedCertExtension
|
||||
ErrInvalidRevocationReason
|
||||
ErrTrailingRevocationReason
|
||||
ErrInvalidRevocationInvalidityDate
|
||||
ErrTrailingRevocationInvalidityDate
|
||||
ErrInvalidRevocationIssuer
|
||||
ErrUnhandledCriticalRevokedCertExtension
|
||||
|
||||
ErrMaxID
|
||||
)
|
||||
|
||||
// idToError gives a template x509.Error for each defined ErrorID; where the Summary
|
||||
// field may hold format specifiers that take field parameters.
|
||||
var idToError map[ErrorID]Error
|
||||
|
||||
var errorInfo = []Error{
|
||||
{
|
||||
ID: ErrInvalidCertList,
|
||||
Summary: "x509: failed to parse CertificateList: %v",
|
||||
Field: "CertificateList",
|
||||
SpecRef: "RFC 5280 s5.1",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrTrailingCertList,
|
||||
Summary: "x509: trailing data after CertificateList",
|
||||
Field: "CertificateList",
|
||||
SpecRef: "RFC 5280 s5.1",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
|
||||
{
|
||||
ID: ErrUnexpectedlyCriticalCertListExtension,
|
||||
Summary: "x509: certificate list extension %v marked critical but expected to be non-critical",
|
||||
Field: "tbsCertList.crlExtensions.*.critical",
|
||||
SpecRef: "RFC 5280 s5.2",
|
||||
Category: MalformedCRL,
|
||||
},
|
||||
{
|
||||
ID: ErrUnexpectedlyNonCriticalCertListExtension,
|
||||
Summary: "x509: certificate list extension %v marked non-critical but expected to be critical",
|
||||
Field: "tbsCertList.crlExtensions.*.critical",
|
||||
SpecRef: "RFC 5280 s5.2",
|
||||
Category: MalformedCRL,
|
||||
},
|
||||
|
||||
{
|
||||
ID: ErrInvalidCertListAuthKeyID,
|
||||
Summary: "x509: failed to unmarshal certificate-list authority key-id: %v",
|
||||
Field: "tbsCertList.crlExtensions.*.AuthorityKeyIdentifier",
|
||||
SpecRef: "RFC 5280 s5.2.1",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrTrailingCertListAuthKeyID,
|
||||
Summary: "x509: trailing data after certificate list auth key ID",
|
||||
Field: "tbsCertList.crlExtensions.*.AuthorityKeyIdentifier",
|
||||
SpecRef: "RFC 5280 s5.2.1",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrInvalidCertListIssuerAltName,
|
||||
Summary: "x509: failed to parse CRL issuer alt name: %v",
|
||||
Field: "tbsCertList.crlExtensions.*.IssuerAltName",
|
||||
SpecRef: "RFC 5280 s5.2.2",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrInvalidCertListCRLNumber,
|
||||
Summary: "x509: failed to unmarshal certificate-list crl-number: %v",
|
||||
Field: "tbsCertList.crlExtensions.*.CRLNumber",
|
||||
SpecRef: "RFC 5280 s5.2.3",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrTrailingCertListCRLNumber,
|
||||
Summary: "x509: trailing data after certificate list crl-number",
|
||||
Field: "tbsCertList.crlExtensions.*.CRLNumber",
|
||||
SpecRef: "RFC 5280 s5.2.3",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrNegativeCertListCRLNumber,
|
||||
Summary: "x509: negative certificate list crl-number: %d",
|
||||
Field: "tbsCertList.crlExtensions.*.CRLNumber",
|
||||
SpecRef: "RFC 5280 s5.2.3",
|
||||
Category: MalformedCRL,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrInvalidCertListDeltaCRL,
|
||||
Summary: "x509: failed to unmarshal certificate-list delta-crl: %v",
|
||||
Field: "tbsCertList.crlExtensions.*.BaseCRLNumber",
|
||||
SpecRef: "RFC 5280 s5.2.4",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrTrailingCertListDeltaCRL,
|
||||
Summary: "x509: trailing data after certificate list delta-crl",
|
||||
Field: "tbsCertList.crlExtensions.*.BaseCRLNumber",
|
||||
SpecRef: "RFC 5280 s5.2.4",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrNegativeCertListDeltaCRL,
|
||||
Summary: "x509: negative certificate list base-crl-number: %d",
|
||||
Field: "tbsCertList.crlExtensions.*.BaseCRLNumber",
|
||||
SpecRef: "RFC 5280 s5.2.4",
|
||||
Category: MalformedCRL,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrInvalidCertListIssuingDP,
|
||||
Summary: "x509: failed to unmarshal certificate list issuing distribution point: %v",
|
||||
Field: "tbsCertList.crlExtensions.*.IssuingDistributionPoint",
|
||||
SpecRef: "RFC 5280 s5.2.5",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrTrailingCertListIssuingDP,
|
||||
Summary: "x509: trailing data after certificate list issuing distribution point",
|
||||
Field: "tbsCertList.crlExtensions.*.IssuingDistributionPoint",
|
||||
SpecRef: "RFC 5280 s5.2.5",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrCertListIssuingDPMultipleTypes,
|
||||
Summary: "x509: multiple cert types set in issuing-distribution-point: user:%v CA:%v attr:%v",
|
||||
Field: "tbsCertList.crlExtensions.*.IssuingDistributionPoint",
|
||||
SpecRef: "RFC 5280 s5.2.5",
|
||||
SpecText: "at most one of onlyContainsUserCerts, onlyContainsCACerts, and onlyContainsAttributeCerts may be set to TRUE.",
|
||||
Category: MalformedCRL,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrCertListIssuingDPInvalidFullName,
|
||||
Summary: "x509: failed to parse CRL issuing-distribution-point fullName: %v",
|
||||
Field: "tbsCertList.crlExtensions.*.IssuingDistributionPoint.distributionPoint",
|
||||
SpecRef: "RFC 5280 s5.2.5",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrInvalidCertListFreshestCRL,
|
||||
Summary: "x509: failed to unmarshal certificate list freshestCRL: %v",
|
||||
Field: "tbsCertList.crlExtensions.*.FreshestCRL",
|
||||
SpecRef: "RFC 5280 s5.2.6",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrInvalidCertListAuthInfoAccess,
|
||||
Summary: "x509: failed to unmarshal certificate list authority info access: %v",
|
||||
Field: "tbsCertList.crlExtensions.*.AuthorityInfoAccess",
|
||||
SpecRef: "RFC 5280 s5.2.7",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrTrailingCertListAuthInfoAccess,
|
||||
Summary: "x509: trailing data after certificate list authority info access",
|
||||
Field: "tbsCertList.crlExtensions.*.AuthorityInfoAccess",
|
||||
SpecRef: "RFC 5280 s5.2.7",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrUnhandledCriticalCertListExtension,
|
||||
Summary: "x509: unhandled critical extension in certificate list: %v",
|
||||
Field: "tbsCertList.revokedCertificates.crlExtensions.*",
|
||||
SpecRef: "RFC 5280 s5.2",
|
||||
SpecText: "If a CRL contains a critical extension that the application cannot process, then the application MUST NOT use that CRL to determine the status of certificates.",
|
||||
Category: MalformedCRL,
|
||||
Fatal: true,
|
||||
},
|
||||
|
||||
{
|
||||
ID: ErrUnexpectedlyCriticalRevokedCertExtension,
|
||||
Summary: "x509: revoked certificate extension %v marked critical but expected to be non-critical",
|
||||
Field: "tbsCertList.revokedCertificates.crlEntryExtensions.*.critical",
|
||||
SpecRef: "RFC 5280 s5.3",
|
||||
Category: MalformedCRL,
|
||||
},
|
||||
{
|
||||
ID: ErrUnexpectedlyNonCriticalRevokedCertExtension,
|
||||
Summary: "x509: revoked certificate extension %v marked non-critical but expected to be critical",
|
||||
Field: "tbsCertList.revokedCertificates.crlEntryExtensions.*.critical",
|
||||
SpecRef: "RFC 5280 s5.3",
|
||||
Category: MalformedCRL,
|
||||
},
|
||||
|
||||
{
|
||||
ID: ErrInvalidRevocationReason,
|
||||
Summary: "x509: failed to parse revocation reason: %v",
|
||||
Field: "tbsCertList.revokedCertificates.crlEntryExtensions.*.CRLReason",
|
||||
SpecRef: "RFC 5280 s5.3.1",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrTrailingRevocationReason,
|
||||
Summary: "x509: trailing data after revoked certificate reason",
|
||||
Field: "tbsCertList.revokedCertificates.crlEntryExtensions.*.CRLReason",
|
||||
SpecRef: "RFC 5280 s5.3.1",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrInvalidRevocationInvalidityDate,
|
||||
Summary: "x509: failed to parse revoked certificate invalidity date: %v",
|
||||
Field: "tbsCertList.revokedCertificates.crlEntryExtensions.*.InvalidityDate",
|
||||
SpecRef: "RFC 5280 s5.3.2",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrTrailingRevocationInvalidityDate,
|
||||
Summary: "x509: trailing data after revoked certificate invalidity date",
|
||||
Field: "tbsCertList.revokedCertificates.crlEntryExtensions.*.InvalidityDate",
|
||||
SpecRef: "RFC 5280 s5.3.2",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrInvalidRevocationIssuer,
|
||||
Summary: "x509: failed to parse revocation issuer %v",
|
||||
Field: "tbsCertList.revokedCertificates.crlEntryExtensions.*.CertificateIssuer",
|
||||
SpecRef: "RFC 5280 s5.3.3",
|
||||
Category: InvalidASN1Content,
|
||||
Fatal: true,
|
||||
},
|
||||
{
|
||||
ID: ErrUnhandledCriticalRevokedCertExtension,
|
||||
Summary: "x509: unhandled critical extension in revoked certificate: %v",
|
||||
Field: "tbsCertList.revokedCertificates.crlEntryExtensions.*",
|
||||
SpecRef: "RFC 5280 s5.3",
|
||||
SpecText: "If a CRL contains a critical CRL entry extension that the application cannot process, then the application MUST NOT use that CRL to determine the status of any certificates.",
|
||||
Category: MalformedCRL,
|
||||
Fatal: true,
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
idToError = make(map[ErrorID]Error, len(errorInfo))
|
||||
for _, info := range errorInfo {
|
||||
idToError[info.ID] = info
|
||||
}
|
||||
}
|
||||
|
||||
// NewError builds a new x509.Error based on the template for the given id.
|
||||
func NewError(id ErrorID, args ...interface{}) Error {
|
||||
var err Error
|
||||
if id >= ErrMaxID {
|
||||
err.ID = id
|
||||
err.Summary = fmt.Sprintf("Unknown error ID %v: args %+v", id, args)
|
||||
err.Fatal = true
|
||||
} else {
|
||||
err = idToError[id]
|
||||
err.Summary = fmt.Sprintf(err.Summary, args...)
|
||||
}
|
||||
return err
|
||||
}
|
13
vendor/github.com/google/certificate-transparency-go/x509/errors_test.go
generated
vendored
Normal file
13
vendor/github.com/google/certificate-transparency-go/x509/errors_test.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package x509
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTemplateIDs(t *testing.T) {
|
||||
for id, template := range idToError {
|
||||
if template.ID != id {
|
||||
t.Errorf("idToError[%v].id=%v; want %v", id, template.ID, id)
|
||||
}
|
||||
}
|
||||
}
|
135
vendor/github.com/google/certificate-transparency-go/x509/example_test.go
generated
vendored
Normal file
135
vendor/github.com/google/certificate-transparency-go/x509/example_test.go
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509_test
|
||||
|
||||
import (
|
||||
"crypto/dsa"
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/certificate-transparency-go/x509"
|
||||
)
|
||||
|
||||
func ExampleCertificate_Verify() {
|
||||
// Verifying with a custom list of root certificates.
|
||||
|
||||
const rootPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
|
||||
MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
|
||||
YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG
|
||||
EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy
|
||||
bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP
|
||||
VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv
|
||||
h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE
|
||||
ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ
|
||||
EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC
|
||||
DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7
|
||||
qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD
|
||||
VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g
|
||||
K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI
|
||||
KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n
|
||||
ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB
|
||||
BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY
|
||||
/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/
|
||||
zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza
|
||||
HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto
|
||||
WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6
|
||||
yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const certPEM = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDujCCAqKgAwIBAgIIE31FZVaPXTUwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
|
||||
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
|
||||
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMTI5MTMyNzQzWhcNMTQwNTI5MDAwMDAw
|
||||
WjBpMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
|
||||
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEYMBYGA1UEAwwPbWFp
|
||||
bC5nb29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfRrObuSW5T7q
|
||||
5CnSEqefEmtH4CCv6+5EckuriNr1CjfVvqzwfAhopXkLrq45EQm8vkmf7W96XJhC
|
||||
7ZM0dYi1/qOCAU8wggFLMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAa
|
||||
BgNVHREEEzARgg9tYWlsLmdvb2dsZS5jb20wCwYDVR0PBAQDAgeAMGgGCCsGAQUF
|
||||
BwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUuY29tL0dJQUcy
|
||||
LmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2dsZS5jb20vb2Nz
|
||||
cDAdBgNVHQ4EFgQUiJxtimAuTfwb+aUtBn5UYKreKvMwDAYDVR0TAQH/BAIwADAf
|
||||
BgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAXBgNVHSAEEDAOMAwGCisG
|
||||
AQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29nbGUuY29t
|
||||
L0dJQUcyLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAH6RYHxHdcGpMpFE3oxDoFnP+
|
||||
gtuBCHan2yE2GRbJ2Cw8Lw0MmuKqHlf9RSeYfd3BXeKkj1qO6TVKwCh+0HdZk283
|
||||
TZZyzmEOyclm3UGFYe82P/iDFt+CeQ3NpmBg+GoaVCuWAARJN/KfglbLyyYygcQq
|
||||
0SgeDh8dRKUiaW3HQSoYvTvdTuqzwK4CXsr3b5/dAOY8uMuG/IAR3FgwTbZ1dtoW
|
||||
RvOTa8hYiU6A475WuZKyEHcwnGYe57u2I2KbMgcKjPniocj4QzgYsVAVKW3IwaOh
|
||||
yE+vPxsiUkvQHdO2fojCkY8jg70jxM+gu59tPDNbw3Uh/2Ij310FgTHsnGQMyA==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
// First, create the set of root certificates. For this example we only
|
||||
// have one. It's also possible to omit this in order to use the
|
||||
// default root set of the current operating system.
|
||||
roots := x509.NewCertPool()
|
||||
ok := roots.AppendCertsFromPEM([]byte(rootPEM))
|
||||
if !ok {
|
||||
panic("failed to parse root certificate")
|
||||
}
|
||||
|
||||
block, _ := pem.Decode([]byte(certPEM))
|
||||
if block == nil {
|
||||
panic("failed to parse certificate PEM")
|
||||
}
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
panic("failed to parse certificate: " + err.Error())
|
||||
}
|
||||
|
||||
opts := x509.VerifyOptions{
|
||||
DNSName: "mail.google.com",
|
||||
Roots: roots,
|
||||
}
|
||||
|
||||
if _, err := cert.Verify(opts); err != nil {
|
||||
panic("failed to verify certificate: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleParsePKIXPublicKey() {
|
||||
const pubPEM = `
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlRuRnThUjU8/prwYxbty
|
||||
WPT9pURI3lbsKMiB6Fn/VHOKE13p4D8xgOCADpdRagdT6n4etr9atzDKUSvpMtR3
|
||||
CP5noNc97WiNCggBjVWhs7szEe8ugyqF23XwpHQ6uV1LKH50m92MbOWfCtjU9p/x
|
||||
qhNpQQ1AZhqNy5Gevap5k8XzRmjSldNAFZMY7Yv3Gi+nyCwGwpVtBUwhuLzgNFK/
|
||||
yDtw2WcWmUU7NuC8Q6MWvPebxVtCfVp/iQU6q60yyt6aGOBkhAX0LpKAEhKidixY
|
||||
nP9PNVBvxgu3XZ4P36gZV6+ummKdBVnc3NqwBLu5+CcdRdusmHPHd5pHf4/38Z3/
|
||||
6qU2a/fPvWzceVTEgZ47QjFMTCTmCwNt29cvi7zZeQzjtwQgn4ipN9NibRH/Ax/q
|
||||
TbIzHfrJ1xa2RteWSdFjwtxi9C20HUkjXSeI4YlzQMH0fPX6KCE7aVePTOnB69I/
|
||||
a9/q96DiXZajwlpq3wFctrs1oXqBp5DVrCIj8hU2wNgB7LtQ1mCtsYz//heai0K9
|
||||
PhE4X6hiE0YmeAZjR0uHl8M/5aW9xCoJ72+12kKpWAa0SFRWLy6FejNYCYpkupVJ
|
||||
yecLk/4L1W0l6jQQZnWErXZYe0PNFcmwGXy1Rep83kfBRNKRy5tvocalLlwXLdUk
|
||||
AIU+2GKjyT3iMuzZxxFxPFMCAwEAAQ==
|
||||
-----END PUBLIC KEY-----`
|
||||
|
||||
block, _ := pem.Decode([]byte(pubPEM))
|
||||
if block == nil {
|
||||
panic("failed to parse PEM block containing the public key")
|
||||
}
|
||||
|
||||
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
||||
if err != nil {
|
||||
panic("failed to parse DER encoded public key: " + err.Error())
|
||||
}
|
||||
|
||||
switch pub := pub.(type) {
|
||||
case *rsa.PublicKey:
|
||||
fmt.Println("pub is of type RSA:", pub)
|
||||
case *dsa.PublicKey:
|
||||
fmt.Println("pub is of type DSA:", pub)
|
||||
case *ecdsa.PublicKey:
|
||||
fmt.Println("pub is of type ECDSA:", pub)
|
||||
default:
|
||||
panic("unknown type of public key")
|
||||
}
|
||||
}
|
2003
vendor/github.com/google/certificate-transparency-go/x509/name_constraints_test.go
generated
vendored
Normal file
2003
vendor/github.com/google/certificate-transparency-go/x509/name_constraints_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
164
vendor/github.com/google/certificate-transparency-go/x509/names.go
generated
vendored
Normal file
164
vendor/github.com/google/certificate-transparency-go/x509/names.go
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
"github.com/google/certificate-transparency-go/x509/pkix"
|
||||
)
|
||||
|
||||
const (
|
||||
// GeneralName tag values from RFC 5280, 4.2.1.6
|
||||
tagOtherName = 0
|
||||
tagRFC822Name = 1
|
||||
tagDNSName = 2
|
||||
tagX400Address = 3
|
||||
tagDirectoryName = 4
|
||||
tagEDIPartyName = 5
|
||||
tagURI = 6
|
||||
tagIPAddress = 7
|
||||
tagRegisteredID = 8
|
||||
)
|
||||
|
||||
// OtherName describes a name related to a certificate which is not in one
|
||||
// of the standard name formats. RFC 5280, 4.2.1.6:
|
||||
// OtherName ::= SEQUENCE {
|
||||
// type-id OBJECT IDENTIFIER,
|
||||
// value [0] EXPLICIT ANY DEFINED BY type-id }
|
||||
type OtherName struct {
|
||||
TypeID asn1.ObjectIdentifier
|
||||
Value asn1.RawValue
|
||||
}
|
||||
|
||||
// GeneralNames holds a collection of names related to a certificate.
|
||||
type GeneralNames struct {
|
||||
DNSNames []string
|
||||
EmailAddresses []string
|
||||
DirectoryNames []pkix.Name
|
||||
URIs []string
|
||||
IPNets []net.IPNet
|
||||
RegisteredIDs []asn1.ObjectIdentifier
|
||||
OtherNames []OtherName
|
||||
}
|
||||
|
||||
// Len returns the total number of names in a GeneralNames object.
|
||||
func (gn GeneralNames) Len() int {
|
||||
return (len(gn.DNSNames) + len(gn.EmailAddresses) + len(gn.DirectoryNames) +
|
||||
len(gn.URIs) + len(gn.IPNets) + len(gn.RegisteredIDs) + len(gn.OtherNames))
|
||||
}
|
||||
|
||||
// Empty indicates whether a GeneralNames object is empty.
|
||||
func (gn GeneralNames) Empty() bool {
|
||||
return gn.Len() == 0
|
||||
}
|
||||
|
||||
func parseGeneralNames(value []byte, gname *GeneralNames) error {
|
||||
// RFC 5280, 4.2.1.6
|
||||
// GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
|
||||
//
|
||||
// GeneralName ::= CHOICE {
|
||||
// otherName [0] OtherName,
|
||||
// rfc822Name [1] IA5String,
|
||||
// dNSName [2] IA5String,
|
||||
// x400Address [3] ORAddress,
|
||||
// directoryName [4] Name,
|
||||
// ediPartyName [5] EDIPartyName,
|
||||
// uniformResourceIdentifier [6] IA5String,
|
||||
// iPAddress [7] OCTET STRING,
|
||||
// registeredID [8] OBJECT IDENTIFIER }
|
||||
var seq asn1.RawValue
|
||||
var rest []byte
|
||||
if rest, err := asn1.Unmarshal(value, &seq); err != nil {
|
||||
return fmt.Errorf("x509: failed to parse GeneralNames: %v", err)
|
||||
} else if len(rest) != 0 {
|
||||
return fmt.Errorf("x509: trailing data after GeneralNames")
|
||||
}
|
||||
if !seq.IsCompound || seq.Tag != asn1.TagSequence || seq.Class != asn1.ClassUniversal {
|
||||
return fmt.Errorf("x509: failed to parse GeneralNames sequence, tag %+v", seq)
|
||||
}
|
||||
|
||||
rest = seq.Bytes
|
||||
for len(rest) > 0 {
|
||||
var err error
|
||||
rest, err = parseGeneralName(rest, gname, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("x509: failed to parse GeneralName: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseGeneralName(data []byte, gname *GeneralNames, withMask bool) ([]byte, error) {
|
||||
var v asn1.RawValue
|
||||
var rest []byte
|
||||
var err error
|
||||
rest, err = asn1.Unmarshal(data, &v)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames: %v", err)
|
||||
}
|
||||
switch v.Tag {
|
||||
case tagOtherName:
|
||||
if !v.IsCompound {
|
||||
return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.otherName: not compound")
|
||||
}
|
||||
var other OtherName
|
||||
v.FullBytes = append([]byte{}, v.FullBytes...)
|
||||
v.FullBytes[0] = asn1.TagSequence | 0x20
|
||||
_, err = asn1.Unmarshal(v.FullBytes, &other)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.otherName: %v", err)
|
||||
}
|
||||
gname.OtherNames = append(gname.OtherNames, other)
|
||||
case tagRFC822Name:
|
||||
gname.EmailAddresses = append(gname.EmailAddresses, string(v.Bytes))
|
||||
case tagDNSName:
|
||||
dns := string(v.Bytes)
|
||||
gname.DNSNames = append(gname.DNSNames, dns)
|
||||
case tagDirectoryName:
|
||||
var rdnSeq pkix.RDNSequence
|
||||
if _, err := asn1.Unmarshal(v.Bytes, &rdnSeq); err != nil {
|
||||
return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.directoryName: %v", err)
|
||||
}
|
||||
var dirName pkix.Name
|
||||
dirName.FillFromRDNSequence(&rdnSeq)
|
||||
gname.DirectoryNames = append(gname.DirectoryNames, dirName)
|
||||
case tagURI:
|
||||
gname.URIs = append(gname.URIs, string(v.Bytes))
|
||||
case tagIPAddress:
|
||||
vlen := len(v.Bytes)
|
||||
if withMask {
|
||||
switch vlen {
|
||||
case (2 * net.IPv4len), (2 * net.IPv6len):
|
||||
ipNet := net.IPNet{IP: v.Bytes[0 : vlen/2], Mask: v.Bytes[vlen/2:]}
|
||||
gname.IPNets = append(gname.IPNets, ipNet)
|
||||
default:
|
||||
return nil, fmt.Errorf("x509: invalid IP/mask length %d in GeneralNames.iPAddress", vlen)
|
||||
}
|
||||
} else {
|
||||
switch vlen {
|
||||
case net.IPv4len, net.IPv6len:
|
||||
ipNet := net.IPNet{IP: v.Bytes}
|
||||
gname.IPNets = append(gname.IPNets, ipNet)
|
||||
default:
|
||||
return nil, fmt.Errorf("x509: invalid IP length %d in GeneralNames.iPAddress", vlen)
|
||||
}
|
||||
}
|
||||
case tagRegisteredID:
|
||||
var oid asn1.ObjectIdentifier
|
||||
v.FullBytes = append([]byte{}, v.FullBytes...)
|
||||
v.FullBytes[0] = asn1.TagOID
|
||||
_, err = asn1.Unmarshal(v.FullBytes, &oid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.registeredID: %v", err)
|
||||
}
|
||||
gname.RegisteredIDs = append(gname.RegisteredIDs, oid)
|
||||
default:
|
||||
return nil, fmt.Errorf("x509: failed to unmarshal GeneralName: unknown tag %d", v.Tag)
|
||||
}
|
||||
return rest, nil
|
||||
}
|
267
vendor/github.com/google/certificate-transparency-go/x509/names_test.go
generated
vendored
Normal file
267
vendor/github.com/google/certificate-transparency-go/x509/names_test.go
generated
vendored
Normal file
@ -0,0 +1,267 @@
|
||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
"github.com/google/certificate-transparency-go/x509/pkix"
|
||||
)
|
||||
|
||||
func TestParseGeneralNames(t *testing.T) {
|
||||
var tests = []struct {
|
||||
data string // as hex
|
||||
want GeneralNames
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
data: ("3012" +
|
||||
("8210" + "7777772e676f6f676c652e636f2e756b")),
|
||||
want: GeneralNames{
|
||||
DNSNames: []string{"www.google.co.uk"},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("3024" +
|
||||
("8210" + "7777772e676f6f676c652e636f2e756b") +
|
||||
("8610" + "7777772e676f6f676c652e636f2e756b")),
|
||||
want: GeneralNames{
|
||||
DNSNames: []string{"www.google.co.uk"},
|
||||
URIs: []string{"www.google.co.uk"},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: "0a0101",
|
||||
wantErr: "failed to parse GeneralNames sequence",
|
||||
},
|
||||
{
|
||||
data: "0a",
|
||||
wantErr: "failed to parse GeneralNames:",
|
||||
},
|
||||
{
|
||||
data: "03000a0101",
|
||||
wantErr: "trailing data",
|
||||
},
|
||||
{
|
||||
data: ("3005" + ("8703" + "010203")),
|
||||
wantErr: "invalid IP length",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
inData := fromHex(test.data)
|
||||
var got GeneralNames
|
||||
err := parseGeneralNames(inData, &got)
|
||||
if err != nil {
|
||||
if test.wantErr == "" {
|
||||
t.Errorf("parseGeneralNames(%s)=%v; want nil", test.data, err)
|
||||
} else if !strings.Contains(err.Error(), test.wantErr) {
|
||||
t.Errorf("parseGeneralNames(%s)=%v; want %q", test.data, err, test.wantErr)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if test.wantErr != "" {
|
||||
t.Errorf("parseGeneralNames(%s)=%+v,nil; want %q", test.data, got, test.wantErr)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(got, test.want) {
|
||||
t.Errorf("parseGeneralNames(%s)=%+v; want %+v", test.data, got, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseGeneralName(t *testing.T) {
|
||||
var tests = []struct {
|
||||
data string // as hex
|
||||
withMask bool
|
||||
want GeneralNames
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
data: ("a008" +
|
||||
("0603" + "551d0e") + // OID: subject-key-id
|
||||
("0a01" + "01")), // enum=1
|
||||
want: GeneralNames{
|
||||
OtherNames: []OtherName{
|
||||
{
|
||||
TypeID: OIDExtensionSubjectKeyId,
|
||||
Value: asn1.RawValue{
|
||||
Class: asn1.ClassUniversal,
|
||||
Tag: asn1.TagEnum,
|
||||
IsCompound: false,
|
||||
Bytes: fromHex("01"),
|
||||
FullBytes: fromHex("0a0101"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("8008" +
|
||||
("0603" + "551d0e") + // OID: subject-key-id
|
||||
("0a01" + "01")), // enum=1
|
||||
wantErr: "not compound",
|
||||
},
|
||||
{
|
||||
data: ("a005" +
|
||||
("0603" + "551d0e")), // OID: subject-key-id
|
||||
wantErr: "sequence truncated",
|
||||
},
|
||||
{
|
||||
data: ("8110" + "77777740676f6f676c652e636f2e756b"),
|
||||
want: GeneralNames{
|
||||
EmailAddresses: []string{"www@google.co.uk"},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("8210" + "7777772e676f6f676c652e636f2e756b"),
|
||||
want: GeneralNames{
|
||||
DNSNames: []string{"www.google.co.uk"},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("844b" +
|
||||
("3049" +
|
||||
("310b" +
|
||||
("3009" +
|
||||
("0603" + "550406") +
|
||||
("1302" + "5553"))) + // "US"
|
||||
("3113" +
|
||||
("3011" +
|
||||
("0603" + "55040a") +
|
||||
("130a" + "476f6f676c6520496e63"))) + // "Google Inc"
|
||||
("3125" +
|
||||
("3023" +
|
||||
("0603" + "550403") +
|
||||
("131c" + "476f6f676c6520496e7465726e657420417574686f72697479204732"))))), // "GoogleInternet Authority G2"
|
||||
want: GeneralNames{
|
||||
DirectoryNames: []pkix.Name{
|
||||
{
|
||||
Country: []string{"US"},
|
||||
Organization: []string{"Google Inc"},
|
||||
CommonName: "Google Internet Authority G2",
|
||||
Names: []pkix.AttributeTypeAndValue{
|
||||
{Type: pkix.OIDCountry, Value: "US"},
|
||||
{Type: pkix.OIDOrganization, Value: "Google Inc"},
|
||||
{Type: pkix.OIDCommonName, Value: "Google Internet Authority G2"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("8410" + "7777772e676f6f676c652e636f2e756b"),
|
||||
wantErr: "failed to unmarshal GeneralNames.directoryName",
|
||||
},
|
||||
{
|
||||
data: ("8610" + "7777772e676f6f676c652e636f2e756b"),
|
||||
want: GeneralNames{
|
||||
URIs: []string{"www.google.co.uk"},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("8704" + "01020304"),
|
||||
want: GeneralNames{
|
||||
IPNets: []net.IPNet{{IP: net.IP{1, 2, 3, 4}}},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("8708" + "01020304ffffff00"),
|
||||
withMask: true,
|
||||
want: GeneralNames{
|
||||
IPNets: []net.IPNet{{IP: net.IP{1, 2, 3, 4}, Mask: net.IPMask{0xff, 0xff, 0xff, 0x00}}},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("8710" + "01020304111213142122232431323334"),
|
||||
want: GeneralNames{
|
||||
IPNets: []net.IPNet{{IP: net.IP{1, 2, 3, 4, 0x11, 0x12, 0x13, 0x14, 0x21, 0x22, 0x23, 0x24, 0x31, 0x32, 0x33, 0x34}}},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("8703" + "010203"),
|
||||
wantErr: "invalid IP length",
|
||||
},
|
||||
{
|
||||
data: ("8707" + "01020304ffffff"),
|
||||
withMask: true,
|
||||
wantErr: "invalid IP/mask length",
|
||||
},
|
||||
{
|
||||
data: ("8803" + "551d0e"), // OID: subject-key-id
|
||||
want: GeneralNames{
|
||||
RegisteredIDs: []asn1.ObjectIdentifier{OIDExtensionSubjectKeyId},
|
||||
},
|
||||
},
|
||||
{
|
||||
data: ("8803" + "551d8e"),
|
||||
wantErr: "syntax error",
|
||||
},
|
||||
{
|
||||
data: ("9003" + "551d8e"),
|
||||
wantErr: "unknown tag",
|
||||
},
|
||||
{
|
||||
data: ("8803"),
|
||||
wantErr: "data truncated",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
inData := fromHex(test.data)
|
||||
var got GeneralNames
|
||||
_, err := parseGeneralName(inData, &got, test.withMask)
|
||||
if err != nil {
|
||||
if test.wantErr == "" {
|
||||
t.Errorf("parseGeneralName(%s)=%v; want nil", test.data, err)
|
||||
} else if !strings.Contains(err.Error(), test.wantErr) {
|
||||
t.Errorf("parseGeneralName(%s)=%v; want %q", test.data, err, test.wantErr)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if test.wantErr != "" {
|
||||
t.Errorf("parseGeneralName(%s)=%+v,nil; want %q", test.data, got, test.wantErr)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(got, test.want) {
|
||||
t.Errorf("parseGeneralName(%s)=%+v; want %+v", test.data, got, test.want)
|
||||
}
|
||||
if got.Empty() {
|
||||
t.Errorf("parseGeneralName(%s).Empty(%+v)=true; want false", test.data, got)
|
||||
}
|
||||
if gotLen, wantLen := got.Len(), 1; gotLen != wantLen {
|
||||
t.Errorf("parseGeneralName(%s).Len(%+v)=%d; want %d", test.data, got, gotLen, wantLen)
|
||||
}
|
||||
if !bytes.Equal(inData, fromHex(test.data)) {
|
||||
t.Errorf("parseGeneralName(%s) modified data to %x", test.data, inData)
|
||||
}
|
||||
|
||||
// Wrap the GeneralName up in a SEQUENCE and check that we get the same result using parseGeneralNames.
|
||||
if test.withMask {
|
||||
continue
|
||||
}
|
||||
seqData := append([]byte{0x30, byte(len(inData))}, inData...)
|
||||
var gotSeq GeneralNames
|
||||
err = parseGeneralNames(seqData, &gotSeq)
|
||||
if err != nil {
|
||||
t.Errorf("parseGeneralNames(%x)=%v; want nil", seqData, err)
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(gotSeq, test.want) {
|
||||
t.Errorf("parseGeneralNames(%x)=%+v; want %+v", seqData, gotSeq, test.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fromHex(s string) []byte {
|
||||
d, _ := hex.DecodeString(s)
|
||||
return d
|
||||
}
|
26
vendor/github.com/google/certificate-transparency-go/x509/nilref_nil_darwin.go
generated
vendored
Normal file
26
vendor/github.com/google/certificate-transparency-go/x509/nilref_nil_darwin.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo,!arm,!arm64,!ios,!go1.10
|
||||
|
||||
package x509
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1080
|
||||
#cgo LDFLAGS: -framework CoreFoundation -framework Security
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// For Go versions before 1.10, nil values for Apple's CoreFoundation
|
||||
// CF*Ref types were represented by nil. See:
|
||||
// https://github.com/golang/go/commit/b868616b63a8
|
||||
func setNilCFRef(v *C.CFDataRef) {
|
||||
*v = nil
|
||||
}
|
||||
|
||||
func isNilCFRef(v C.CFDataRef) bool {
|
||||
return v == nil
|
||||
}
|
26
vendor/github.com/google/certificate-transparency-go/x509/nilref_zero_darwin.go
generated
vendored
Normal file
26
vendor/github.com/google/certificate-transparency-go/x509/nilref_zero_darwin.go
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo,!arm,!arm64,!ios,go1.10
|
||||
|
||||
package x509
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1080
|
||||
#cgo LDFLAGS: -framework CoreFoundation -framework Security
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
*/
|
||||
import "C"
|
||||
|
||||
// For Go versions >= 1.10, nil values for Apple's CoreFoundation
|
||||
// CF*Ref types are represented by zero. See:
|
||||
// https://github.com/golang/go/commit/b868616b63a8
|
||||
func setNilCFRef(v *C.CFDataRef) {
|
||||
*v = 0
|
||||
}
|
||||
|
||||
func isNilCFRef(v C.CFDataRef) bool {
|
||||
return v == 0
|
||||
}
|
240
vendor/github.com/google/certificate-transparency-go/x509/pem_decrypt.go
generated
vendored
Normal file
240
vendor/github.com/google/certificate-transparency-go/x509/pem_decrypt.go
generated
vendored
Normal file
@ -0,0 +1,240 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
// RFC 1423 describes the encryption of PEM blocks. The algorithm used to
|
||||
// generate a key from the password was derived by looking at the OpenSSL
|
||||
// implementation.
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/des"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PEMCipher int
|
||||
|
||||
// Possible values for the EncryptPEMBlock encryption algorithm.
|
||||
const (
|
||||
_ PEMCipher = iota
|
||||
PEMCipherDES
|
||||
PEMCipher3DES
|
||||
PEMCipherAES128
|
||||
PEMCipherAES192
|
||||
PEMCipherAES256
|
||||
)
|
||||
|
||||
// rfc1423Algo holds a method for enciphering a PEM block.
|
||||
type rfc1423Algo struct {
|
||||
cipher PEMCipher
|
||||
name string
|
||||
cipherFunc func(key []byte) (cipher.Block, error)
|
||||
keySize int
|
||||
blockSize int
|
||||
}
|
||||
|
||||
// rfc1423Algos holds a slice of the possible ways to encrypt a PEM
|
||||
// block. The ivSize numbers were taken from the OpenSSL source.
|
||||
var rfc1423Algos = []rfc1423Algo{{
|
||||
cipher: PEMCipherDES,
|
||||
name: "DES-CBC",
|
||||
cipherFunc: des.NewCipher,
|
||||
keySize: 8,
|
||||
blockSize: des.BlockSize,
|
||||
}, {
|
||||
cipher: PEMCipher3DES,
|
||||
name: "DES-EDE3-CBC",
|
||||
cipherFunc: des.NewTripleDESCipher,
|
||||
keySize: 24,
|
||||
blockSize: des.BlockSize,
|
||||
}, {
|
||||
cipher: PEMCipherAES128,
|
||||
name: "AES-128-CBC",
|
||||
cipherFunc: aes.NewCipher,
|
||||
keySize: 16,
|
||||
blockSize: aes.BlockSize,
|
||||
}, {
|
||||
cipher: PEMCipherAES192,
|
||||
name: "AES-192-CBC",
|
||||
cipherFunc: aes.NewCipher,
|
||||
keySize: 24,
|
||||
blockSize: aes.BlockSize,
|
||||
}, {
|
||||
cipher: PEMCipherAES256,
|
||||
name: "AES-256-CBC",
|
||||
cipherFunc: aes.NewCipher,
|
||||
keySize: 32,
|
||||
blockSize: aes.BlockSize,
|
||||
},
|
||||
}
|
||||
|
||||
// deriveKey uses a key derivation function to stretch the password into a key
|
||||
// with the number of bits our cipher requires. This algorithm was derived from
|
||||
// the OpenSSL source.
|
||||
func (c rfc1423Algo) deriveKey(password, salt []byte) []byte {
|
||||
hash := md5.New()
|
||||
out := make([]byte, c.keySize)
|
||||
var digest []byte
|
||||
|
||||
for i := 0; i < len(out); i += len(digest) {
|
||||
hash.Reset()
|
||||
hash.Write(digest)
|
||||
hash.Write(password)
|
||||
hash.Write(salt)
|
||||
digest = hash.Sum(digest[:0])
|
||||
copy(out[i:], digest)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// IsEncryptedPEMBlock returns if the PEM block is password encrypted.
|
||||
func IsEncryptedPEMBlock(b *pem.Block) bool {
|
||||
_, ok := b.Headers["DEK-Info"]
|
||||
return ok
|
||||
}
|
||||
|
||||
// IncorrectPasswordError is returned when an incorrect password is detected.
|
||||
var IncorrectPasswordError = errors.New("x509: decryption password incorrect")
|
||||
|
||||
// DecryptPEMBlock takes a password encrypted PEM block and the password used to
|
||||
// encrypt it and returns a slice of decrypted DER encoded bytes. It inspects
|
||||
// the DEK-Info header to determine the algorithm used for decryption. If no
|
||||
// DEK-Info header is present, an error is returned. If an incorrect password
|
||||
// is detected an IncorrectPasswordError is returned. Because of deficiencies
|
||||
// in the encrypted-PEM format, it's not always possible to detect an incorrect
|
||||
// password. In these cases no error will be returned but the decrypted DER
|
||||
// bytes will be random noise.
|
||||
func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) {
|
||||
dek, ok := b.Headers["DEK-Info"]
|
||||
if !ok {
|
||||
return nil, errors.New("x509: no DEK-Info header in block")
|
||||
}
|
||||
|
||||
idx := strings.Index(dek, ",")
|
||||
if idx == -1 {
|
||||
return nil, errors.New("x509: malformed DEK-Info header")
|
||||
}
|
||||
|
||||
mode, hexIV := dek[:idx], dek[idx+1:]
|
||||
ciph := cipherByName(mode)
|
||||
if ciph == nil {
|
||||
return nil, errors.New("x509: unknown encryption mode")
|
||||
}
|
||||
iv, err := hex.DecodeString(hexIV)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(iv) != ciph.blockSize {
|
||||
return nil, errors.New("x509: incorrect IV size")
|
||||
}
|
||||
|
||||
// Based on the OpenSSL implementation. The salt is the first 8 bytes
|
||||
// of the initialization vector.
|
||||
key := ciph.deriveKey(password, iv[:8])
|
||||
block, err := ciph.cipherFunc(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(b.Bytes)%block.BlockSize() != 0 {
|
||||
return nil, errors.New("x509: encrypted PEM data is not a multiple of the block size")
|
||||
}
|
||||
|
||||
data := make([]byte, len(b.Bytes))
|
||||
dec := cipher.NewCBCDecrypter(block, iv)
|
||||
dec.CryptBlocks(data, b.Bytes)
|
||||
|
||||
// Blocks are padded using a scheme where the last n bytes of padding are all
|
||||
// equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423.
|
||||
// For example:
|
||||
// [x y z 2 2]
|
||||
// [x y 7 7 7 7 7 7 7]
|
||||
// If we detect a bad padding, we assume it is an invalid password.
|
||||
dlen := len(data)
|
||||
if dlen == 0 || dlen%ciph.blockSize != 0 {
|
||||
return nil, errors.New("x509: invalid padding")
|
||||
}
|
||||
last := int(data[dlen-1])
|
||||
if dlen < last {
|
||||
return nil, IncorrectPasswordError
|
||||
}
|
||||
if last == 0 || last > ciph.blockSize {
|
||||
return nil, IncorrectPasswordError
|
||||
}
|
||||
for _, val := range data[dlen-last:] {
|
||||
if int(val) != last {
|
||||
return nil, IncorrectPasswordError
|
||||
}
|
||||
}
|
||||
return data[:dlen-last], nil
|
||||
}
|
||||
|
||||
// EncryptPEMBlock returns a PEM block of the specified type holding the
|
||||
// given DER-encoded data encrypted with the specified algorithm and
|
||||
// password.
|
||||
func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) {
|
||||
ciph := cipherByKey(alg)
|
||||
if ciph == nil {
|
||||
return nil, errors.New("x509: unknown encryption mode")
|
||||
}
|
||||
iv := make([]byte, ciph.blockSize)
|
||||
if _, err := io.ReadFull(rand, iv); err != nil {
|
||||
return nil, errors.New("x509: cannot generate IV: " + err.Error())
|
||||
}
|
||||
// The salt is the first 8 bytes of the initialization vector,
|
||||
// matching the key derivation in DecryptPEMBlock.
|
||||
key := ciph.deriveKey(password, iv[:8])
|
||||
block, err := ciph.cipherFunc(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
enc := cipher.NewCBCEncrypter(block, iv)
|
||||
pad := ciph.blockSize - len(data)%ciph.blockSize
|
||||
encrypted := make([]byte, len(data), len(data)+pad)
|
||||
// We could save this copy by encrypting all the whole blocks in
|
||||
// the data separately, but it doesn't seem worth the additional
|
||||
// code.
|
||||
copy(encrypted, data)
|
||||
// See RFC 1423, section 1.1
|
||||
for i := 0; i < pad; i++ {
|
||||
encrypted = append(encrypted, byte(pad))
|
||||
}
|
||||
enc.CryptBlocks(encrypted, encrypted)
|
||||
|
||||
return &pem.Block{
|
||||
Type: blockType,
|
||||
Headers: map[string]string{
|
||||
"Proc-Type": "4,ENCRYPTED",
|
||||
"DEK-Info": ciph.name + "," + hex.EncodeToString(iv),
|
||||
},
|
||||
Bytes: encrypted,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func cipherByName(name string) *rfc1423Algo {
|
||||
for i := range rfc1423Algos {
|
||||
alg := &rfc1423Algos[i]
|
||||
if alg.name == name {
|
||||
return alg
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func cipherByKey(key PEMCipher) *rfc1423Algo {
|
||||
for i := range rfc1423Algos {
|
||||
alg := &rfc1423Algos[i]
|
||||
if alg.cipher == key {
|
||||
return alg
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
247
vendor/github.com/google/certificate-transparency-go/x509/pem_decrypt_test.go
generated
vendored
Normal file
247
vendor/github.com/google/certificate-transparency-go/x509/pem_decrypt_test.go
generated
vendored
Normal file
@ -0,0 +1,247 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDecrypt(t *testing.T) {
|
||||
for i, data := range testData {
|
||||
t.Logf("test %v. %v", i, data.kind)
|
||||
block, rest := pem.Decode(data.pemData)
|
||||
if len(rest) > 0 {
|
||||
t.Error("extra data")
|
||||
}
|
||||
der, err := DecryptPEMBlock(block, data.password)
|
||||
if err != nil {
|
||||
t.Error("decrypt failed: ", err)
|
||||
continue
|
||||
}
|
||||
if _, err := ParsePKCS1PrivateKey(der); err != nil {
|
||||
t.Error("invalid private key: ", err)
|
||||
}
|
||||
plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
|
||||
if err != nil {
|
||||
t.Fatal("cannot decode test DER data: ", err)
|
||||
}
|
||||
if !bytes.Equal(der, plainDER) {
|
||||
t.Error("data mismatch")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncrypt(t *testing.T) {
|
||||
for i, data := range testData {
|
||||
t.Logf("test %v. %v", i, data.kind)
|
||||
plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
|
||||
if err != nil {
|
||||
t.Fatal("cannot decode test DER data: ", err)
|
||||
}
|
||||
password := []byte("kremvax1")
|
||||
block, err := EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", plainDER, password, data.kind)
|
||||
if err != nil {
|
||||
t.Error("encrypt: ", err)
|
||||
continue
|
||||
}
|
||||
if !IsEncryptedPEMBlock(block) {
|
||||
t.Error("PEM block does not appear to be encrypted")
|
||||
}
|
||||
if block.Type != "RSA PRIVATE KEY" {
|
||||
t.Errorf("unexpected block type; got %q want %q", block.Type, "RSA PRIVATE KEY")
|
||||
}
|
||||
if block.Headers["Proc-Type"] != "4,ENCRYPTED" {
|
||||
t.Errorf("block does not have correct Proc-Type header")
|
||||
}
|
||||
der, err := DecryptPEMBlock(block, password)
|
||||
if err != nil {
|
||||
t.Error("decrypt: ", err)
|
||||
continue
|
||||
}
|
||||
if !bytes.Equal(der, plainDER) {
|
||||
t.Errorf("data mismatch")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testData = []struct {
|
||||
kind PEMCipher
|
||||
password []byte
|
||||
pemData []byte
|
||||
plainDER string
|
||||
}{
|
||||
{
|
||||
kind: PEMCipherDES,
|
||||
password: []byte("asdf"),
|
||||
pemData: []byte(`
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-CBC,34F09A4FC8DE22B5
|
||||
|
||||
WXxy8kbZdiZvANtKvhmPBLV7eVFj2A5z6oAxvI9KGyhG0ZK0skfnt00C24vfU7m5
|
||||
ICXeoqP67lzJ18xCzQfHjDaBNs53DSDT+Iz4e8QUep1xQ30+8QKX2NA2coee3nwc
|
||||
6oM1cuvhNUDemBH2i3dKgMVkfaga0zQiiOq6HJyGSncCMSruQ7F9iWEfRbFcxFCx
|
||||
qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz
|
||||
XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm
|
||||
4C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD
|
||||
r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug==
|
||||
-----END RSA PRIVATE KEY-----`),
|
||||
plainDER: `
|
||||
MIIBPAIBAAJBAPASZe+tCPU6p80AjHhDkVsLYa51D35e/YGa8QcZyooeZM8EHozo
|
||||
KD0fNiKI+53bHdy07N+81VQ8/ejPcRoXPlsCAwEAAQJBAMTxIuSq27VpR+zZ7WJf
|
||||
c6fvv1OBvpMZ0/d1pxL/KnOAgq2rD5hDtk9b0LGhTPgQAmrrMTKuSeGoIuYE+gKQ
|
||||
QvkCIQD+GC1m+/do+QRurr0uo46Kx1LzLeSCrjBk34wiOp2+dwIhAPHfTLRXS2fv
|
||||
7rljm0bYa4+eDZpz+E8RcXEgzhhvcQQ9AiAI5eHZJGOyml3MXnQjiPi55WcDOw0w
|
||||
glcRgT6QCEtz2wIhANSyqaFtosIkHKqrDUGfz/bb5tqMYTAnBruVPaf/WEOBAiEA
|
||||
9xORWeRG1tRpso4+dYy4KdDkuLPIO01KY6neYGm3BCM=`,
|
||||
},
|
||||
{
|
||||
kind: PEMCipher3DES,
|
||||
password: []byte("asdf"),
|
||||
pemData: []byte(`
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7
|
||||
|
||||
0JqVdBEH6iqM7drTkj+e2W/bE3LqakaiWhb9WUVonFkhyu8ca/QzebY3b5gCvAZQ
|
||||
YwBvDcT/GHospKqPx+cxDHJNsUASDZws6bz8ZXWJGwZGExKzr0+Qx5fgXn44Ms3x
|
||||
8g1ENFuTXtxo+KoNK0zuAMAqp66Llcds3Fjl4XR18QaD0CrVNAfOdgATWZm5GJxk
|
||||
Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB
|
||||
ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w
|
||||
3z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq
|
||||
gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk=
|
||||
-----END RSA PRIVATE KEY-----`),
|
||||
plainDER: `
|
||||
MIIBOwIBAAJBANOCXKdoNS/iP/MAbl9cf1/SF3P+Ns7ZeNL27CfmDh0O6Zduaax5
|
||||
NBiumd2PmjkaCu7lQ5JOibHfWn+xJsc3kw0CAwEAAQJANX/W8d1Q/sCqzkuAn4xl
|
||||
B5a7qfJWaLHndu1QRLNTRJPn0Ee7OKJ4H0QKOhQM6vpjRrz+P2u9thn6wUxoPsef
|
||||
QQIhAP/jCkfejFcy4v15beqKzwz08/tslVjF+Yq41eJGejmxAiEA05pMoqfkyjcx
|
||||
fyvGhpoOyoCp71vSGUfR2I9CR65oKh0CIC1Msjs66LlfJtQctRq6bCEtFCxEcsP+
|
||||
eEjYo/Sk6WphAiEAxpgWPMJeU/shFT28gS+tmhjPZLpEoT1qkVlC14u0b3ECIQDX
|
||||
tZZZxCtPAm7shftEib0VU77Lk8MsXJcx2C4voRsjEw==`,
|
||||
},
|
||||
{
|
||||
kind: PEMCipherAES128,
|
||||
password: []byte("asdf"),
|
||||
pemData: []byte(`
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A
|
||||
|
||||
EyfQSzXSjv6BaNH+NHdXRlkHdimpF9izWlugVJAPApgXrq5YldPe2aGIOFXyJ+QE
|
||||
ZIG20DYqaPzJRjTEbPNZ6Es0S2JJ5yCpKxwJuDkgJZKtF39Q2i36JeGbSZQIuWJE
|
||||
GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D
|
||||
33U43LLb7+9zD4y3Q9OVHqBFGyHcxCY9+9Qh4ZnFp7DTf6RY5TNEvE3s4g6aDpBs
|
||||
3NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E
|
||||
080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo
|
||||
AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0=
|
||||
-----END RSA PRIVATE KEY-----`),
|
||||
plainDER: `
|
||||
MIIBOgIBAAJBAMBlj5FxYtqbcy8wY89d/S7n0+r5MzD9F63BA/Lpl78vQKtdJ5dT
|
||||
cDGh/rBt1ufRrNp0WihcmZi7Mpl/3jHjiWECAwEAAQJABNOHYnKhtDIqFYj1OAJ3
|
||||
k3GlU0OlERmIOoeY/cL2V4lgwllPBEs7r134AY4wMmZSBUj8UR/O4SNO668ElKPE
|
||||
cQIhAOuqY7/115x5KCdGDMWi+jNaMxIvI4ETGwV40ykGzqlzAiEA0P9oEC3m9tHB
|
||||
kbpjSTxaNkrXxDgdEOZz8X0uOUUwHNsCIAwzcSCiGLyYJTULUmP1ESERfW1mlV78
|
||||
XzzESaJpIM/zAiBQkSTcl9VhcJreQqvjn5BnPZLP4ZHS4gPwJAGdsj5J4QIhAOVR
|
||||
B3WlRNTXR2WsJ5JdByezg9xzdXzULqmga0OE339a`,
|
||||
},
|
||||
{
|
||||
kind: PEMCipherAES192,
|
||||
password: []byte("asdf"),
|
||||
pemData: []byte(`
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369
|
||||
|
||||
cqVslvHqDDM6qwU6YjezCRifXmKsrgEev7ng6Qs7UmDJOpHDgJQZI9fwMFUhIyn5
|
||||
FbCu1SHkLMW52Ld3CuEqMnzWMlhPrW8tFvUOrMWPYSisv7nNq88HobZEJcUNL2MM
|
||||
Y15XmHW6IJwPqhKyLHpWXyOCVEh4ODND2nV15PCoi18oTa475baxSk7+1qH7GuIs
|
||||
Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG
|
||||
ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6
|
||||
xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t
|
||||
Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw=
|
||||
-----END RSA PRIVATE KEY-----`),
|
||||
plainDER: `
|
||||
MIIBOwIBAAJBAMGcRrZiNNmtF20zyS6MQ7pdGx17aFDl+lTl+qnLuJRUCMUG05xs
|
||||
OmxmL/O1Qlf+bnqR8Bgg65SfKg21SYuLhiMCAwEAAQJBAL94uuHyO4wux2VC+qpj
|
||||
IzPykjdU7XRcDHbbvksf4xokSeUFjjD3PB0Qa83M94y89ZfdILIqS9x5EgSB4/lX
|
||||
qNkCIQD6cCIqLfzq/lYbZbQgAAjpBXeQVYsbvVtJrPrXJAlVVQIhAMXpDKMeFPMn
|
||||
J0g2rbx1gngx0qOa5r5iMU5w/noN4W2XAiBjf+WzCG5yFvazD+dOx3TC0A8+4x3P
|
||||
uZ3pWbaXf5PNuQIgAcdXarvhelH2w2piY1g3BPeFqhzBSCK/yLGxR82KIh8CIQDD
|
||||
+qGKsd09NhQ/G27y/DARzOYtml1NvdmCQAgsDIIOLA==`,
|
||||
},
|
||||
{
|
||||
kind: PEMCipherAES256,
|
||||
password: []byte("asdf"),
|
||||
pemData: []byte(`
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD
|
||||
|
||||
4Mxr+KIzRVwoOP0wwq6caSkvW0iS+GE2h2Ov/u+n9ZTMwL83PRnmjfjzBgfRZLVf
|
||||
JFPXxUK26kMNpIdssNnqGOds+DhB+oSrsNKoxgxSl5OBoYv9eJTVYm7qOyAFIsjr
|
||||
DRKAcjYCmzfesr7PVTowwy0RtHmYwyXMGDlAzzZrEvaiySFFmMyKKvtoavwaFoc7
|
||||
Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/
|
||||
2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N
|
||||
sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk
|
||||
clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0=
|
||||
-----END RSA PRIVATE KEY-----`),
|
||||
plainDER: `
|
||||
MIIBOgIBAAJBAKy3GFkstoCHIEeUU/qO8207m8WSrjksR+p9B4tf1w5k+2O1V/GY
|
||||
AQ5WFCApItcOkQe/I0yZZJk/PmCqMzSxrc8CAwEAAQJAOCAz0F7AW9oNelVQSP8F
|
||||
Sfzx7O1yom+qWyAQQJF/gFR11gpf9xpVnnyu1WxIRnDUh1LZwUsjwlDYb7MB74id
|
||||
oQIhANPcOiLwOPT4sIUpRM5HG6BF1BI7L77VpyGVk8xNP7X/AiEA0LMHZtk4I+lJ
|
||||
nClgYp4Yh2JZ1Znbu7IoQMCEJCjwKDECIGd8Dzm5tViTkUW6Hs3Tlf73nNs65duF
|
||||
aRnSglss8I3pAiEAonEnKruawgD8RavDFR+fUgmQiPz4FnGGeVgfwpGG1JECIBYq
|
||||
PXHYtPqxQIbD2pScR5qum7iGUh11lEUPkmt+2uqS`,
|
||||
},
|
||||
{
|
||||
// generated with:
|
||||
// openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128
|
||||
kind: PEMCipherAES128,
|
||||
password: []byte("asdf"),
|
||||
pemData: []byte(`
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7
|
||||
|
||||
6ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3
|
||||
eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD
|
||||
hTP8O1mS/MHl92NE0nhv0w==
|
||||
-----END RSA PRIVATE KEY-----`),
|
||||
plainDER: `
|
||||
MGMCAQACEQC6ssxmYuauuHGOCDAI54RdAgMBAAECEQCWIn6Yv2O+kBcDF7STctKB
|
||||
AgkA8SEfu/2i3g0CCQDGNlXbBHX7kQIIK3Ww5o0cYbECCQDCimPb0dYGsQIIeQ7A
|
||||
jryIst8=`,
|
||||
},
|
||||
}
|
||||
|
||||
const incompleteBlockPEM = `
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7
|
||||
|
||||
6L8yXK2MTQUWBk4ZD6OvCiYp+mXyR1594TQ1K38MxGvDw5pwcDME2Lek8RrR5fd40P2XsL2Z4KKt
|
||||
ai+OP1BZUetfK6AW4MiqB2FDyIdOAJ8XeWuZy21Wtsh8wPD6yYOFM/w7WZL8weX3Y0TSeG/T
|
||||
-----END RSA PRIVATE KEY-----`
|
||||
|
||||
func TestIncompleteBlock(t *testing.T) {
|
||||
// incompleteBlockPEM contains ciphertext that is not a multiple of the
|
||||
// block size. This previously panicked. See #11215.
|
||||
block, _ := pem.Decode([]byte(incompleteBlockPEM))
|
||||
_, err := DecryptPEMBlock(block, []byte("foo"))
|
||||
if err == nil {
|
||||
t.Fatal("Bad PEM data decrypted successfully")
|
||||
}
|
||||
const expectedSubstr = "block size"
|
||||
if e := err.Error(); !strings.Contains(e, expectedSubstr) {
|
||||
t.Fatalf("Expected error containing %q but got: %q", expectedSubstr, e)
|
||||
}
|
||||
}
|
155
vendor/github.com/google/certificate-transparency-go/x509/pkcs1.go
generated
vendored
Normal file
155
vendor/github.com/google/certificate-transparency-go/x509/pkcs1.go
generated
vendored
Normal file
@ -0,0 +1,155 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
)
|
||||
|
||||
// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
|
||||
type pkcs1PrivateKey struct {
|
||||
Version int
|
||||
N *big.Int
|
||||
E int
|
||||
D *big.Int
|
||||
P *big.Int
|
||||
Q *big.Int
|
||||
// We ignore these values, if present, because rsa will calculate them.
|
||||
Dp *big.Int `asn1:"optional"`
|
||||
Dq *big.Int `asn1:"optional"`
|
||||
Qinv *big.Int `asn1:"optional"`
|
||||
|
||||
AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"`
|
||||
}
|
||||
|
||||
type pkcs1AdditionalRSAPrime struct {
|
||||
Prime *big.Int
|
||||
|
||||
// We ignore these values because rsa will calculate them.
|
||||
Exp *big.Int
|
||||
Coeff *big.Int
|
||||
}
|
||||
|
||||
// pkcs1PublicKey reflects the ASN.1 structure of a PKCS#1 public key.
|
||||
type pkcs1PublicKey struct {
|
||||
N *big.Int
|
||||
E int
|
||||
}
|
||||
|
||||
// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
|
||||
func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) {
|
||||
var priv pkcs1PrivateKey
|
||||
rest, err := asn1.Unmarshal(der, &priv)
|
||||
if len(rest) > 0 {
|
||||
return nil, asn1.SyntaxError{Msg: "trailing data"}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if priv.Version > 1 {
|
||||
return nil, errors.New("x509: unsupported private key version")
|
||||
}
|
||||
|
||||
if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
|
||||
return nil, errors.New("x509: private key contains zero or negative value")
|
||||
}
|
||||
|
||||
key := new(rsa.PrivateKey)
|
||||
key.PublicKey = rsa.PublicKey{
|
||||
E: priv.E,
|
||||
N: priv.N,
|
||||
}
|
||||
|
||||
key.D = priv.D
|
||||
key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
|
||||
key.Primes[0] = priv.P
|
||||
key.Primes[1] = priv.Q
|
||||
for i, a := range priv.AdditionalPrimes {
|
||||
if a.Prime.Sign() <= 0 {
|
||||
return nil, errors.New("x509: private key contains zero or negative prime")
|
||||
}
|
||||
key.Primes[i+2] = a.Prime
|
||||
// We ignore the other two values because rsa will calculate
|
||||
// them as needed.
|
||||
}
|
||||
|
||||
err = key.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key.Precompute()
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
|
||||
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
|
||||
key.Precompute()
|
||||
|
||||
version := 0
|
||||
if len(key.Primes) > 2 {
|
||||
version = 1
|
||||
}
|
||||
|
||||
priv := pkcs1PrivateKey{
|
||||
Version: version,
|
||||
N: key.N,
|
||||
E: key.PublicKey.E,
|
||||
D: key.D,
|
||||
P: key.Primes[0],
|
||||
Q: key.Primes[1],
|
||||
Dp: key.Precomputed.Dp,
|
||||
Dq: key.Precomputed.Dq,
|
||||
Qinv: key.Precomputed.Qinv,
|
||||
}
|
||||
|
||||
priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
|
||||
for i, values := range key.Precomputed.CRTValues {
|
||||
priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
|
||||
priv.AdditionalPrimes[i].Exp = values.Exp
|
||||
priv.AdditionalPrimes[i].Coeff = values.Coeff
|
||||
}
|
||||
|
||||
b, _ := asn1.Marshal(priv)
|
||||
return b
|
||||
}
|
||||
|
||||
// ParsePKCS1PublicKey parses a PKCS#1 public key in ASN.1 DER form.
|
||||
func ParsePKCS1PublicKey(der []byte) (*rsa.PublicKey, error) {
|
||||
var pub pkcs1PublicKey
|
||||
rest, err := asn1.Unmarshal(der, &pub)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rest) > 0 {
|
||||
return nil, asn1.SyntaxError{Msg: "trailing data"}
|
||||
}
|
||||
|
||||
if pub.N.Sign() <= 0 || pub.E <= 0 {
|
||||
return nil, errors.New("x509: public key contains zero or negative value")
|
||||
}
|
||||
if pub.E > 1<<31-1 {
|
||||
return nil, errors.New("x509: public key contains large public exponent")
|
||||
}
|
||||
|
||||
return &rsa.PublicKey{
|
||||
E: pub.E,
|
||||
N: pub.N,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MarshalPKCS1PublicKey converts an RSA public key to PKCS#1, ASN.1 DER form.
|
||||
func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte {
|
||||
derBytes, _ := asn1.Marshal(pkcs1PublicKey{
|
||||
N: key.N,
|
||||
E: key.E,
|
||||
})
|
||||
return derBytes
|
||||
}
|
102
vendor/github.com/google/certificate-transparency-go/x509/pkcs8.go
generated
vendored
Normal file
102
vendor/github.com/google/certificate-transparency-go/x509/pkcs8.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
"github.com/google/certificate-transparency-go/x509/pkix"
|
||||
)
|
||||
|
||||
// pkcs8 reflects an ASN.1, PKCS#8 PrivateKey. See
|
||||
// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn
|
||||
// and RFC 5208.
|
||||
type pkcs8 struct {
|
||||
Version int
|
||||
Algo pkix.AlgorithmIdentifier
|
||||
PrivateKey []byte
|
||||
// optional attributes omitted.
|
||||
}
|
||||
|
||||
// ParsePKCS8PrivateKey parses an unencrypted, PKCS#8 private key.
|
||||
// See RFC 5208.
|
||||
func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
|
||||
var privKey pkcs8
|
||||
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch {
|
||||
case privKey.Algo.Algorithm.Equal(OIDPublicKeyRSA):
|
||||
key, err = ParsePKCS1PrivateKey(privKey.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error())
|
||||
}
|
||||
return key, nil
|
||||
|
||||
case privKey.Algo.Algorithm.Equal(OIDPublicKeyECDSA):
|
||||
bytes := privKey.Algo.Parameters.FullBytes
|
||||
namedCurveOID := new(asn1.ObjectIdentifier)
|
||||
if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
|
||||
namedCurveOID = nil
|
||||
}
|
||||
key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
|
||||
}
|
||||
return key, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalPKCS8PrivateKey converts a private key to PKCS#8 encoded form.
|
||||
// The following key types are supported: *rsa.PrivateKey, *ecdsa.PublicKey.
|
||||
// Unsupported key types result in an error.
|
||||
//
|
||||
// See RFC 5208.
|
||||
func MarshalPKCS8PrivateKey(key interface{}) ([]byte, error) {
|
||||
var privKey pkcs8
|
||||
|
||||
switch k := key.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
privKey.Algo = pkix.AlgorithmIdentifier{
|
||||
Algorithm: OIDPublicKeyRSA,
|
||||
Parameters: asn1.NullRawValue,
|
||||
}
|
||||
privKey.PrivateKey = MarshalPKCS1PrivateKey(k)
|
||||
|
||||
case *ecdsa.PrivateKey:
|
||||
oid, ok := OIDFromNamedCurve(k.Curve)
|
||||
if !ok {
|
||||
return nil, errors.New("x509: unknown curve while marshalling to PKCS#8")
|
||||
}
|
||||
|
||||
oidBytes, err := asn1.Marshal(oid)
|
||||
if err != nil {
|
||||
return nil, errors.New("x509: failed to marshal curve OID: " + err.Error())
|
||||
}
|
||||
|
||||
privKey.Algo = pkix.AlgorithmIdentifier{
|
||||
Algorithm: OIDPublicKeyECDSA,
|
||||
Parameters: asn1.RawValue{
|
||||
FullBytes: oidBytes,
|
||||
},
|
||||
}
|
||||
|
||||
if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil {
|
||||
return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error())
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("x509: unknown key type while marshalling PKCS#8: %T", key)
|
||||
}
|
||||
|
||||
return asn1.Marshal(privKey)
|
||||
}
|
109
vendor/github.com/google/certificate-transparency-go/x509/pkcs8_test.go
generated
vendored
Normal file
109
vendor/github.com/google/certificate-transparency-go/x509/pkcs8_test.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rsa"
|
||||
"encoding/hex"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Generated using:
|
||||
// openssl genrsa 1024 | openssl pkcs8 -topk8 -nocrypt
|
||||
var pkcs8RSAPrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031`
|
||||
|
||||
// Generated using:
|
||||
// openssl ecparam -genkey -name secp224r1 | openssl pkcs8 -topk8 -nocrypt
|
||||
var pkcs8P224PrivateKeyHex = `3078020100301006072a8648ce3d020106052b810400210461305f020101041cca3d72b3e88fed2684576dad9b80a9180363a5424986900e3abcab3fa13c033a0004f8f2a6372872a4e61263ed893afb919576a4cacfecd6c081a2cbc76873cf4ba8530703c6042b3a00e2205087e87d2435d2e339e25702fae1`
|
||||
|
||||
// Generated using:
|
||||
// openssl ecparam -genkey -name secp256r1 | openssl pkcs8 -topk8 -nocrypt
|
||||
var pkcs8P256PrivateKeyHex = `308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420dad6b2f49ca774c36d8ae9517e935226f667c929498f0343d2424d0b9b591b43a14403420004b9c9b90095476afe7b860d8bd43568cab7bcb2eed7b8bf2fa0ce1762dd20b04193f859d2d782b1e4cbfd48492f1f533113a6804903f292258513837f07fda735`
|
||||
|
||||
// Generated using:
|
||||
// openssl ecparam -genkey -name secp384r1 | openssl pkcs8 -topk8 -nocrypt
|
||||
var pkcs8P384PrivateKeyHex = `3081b6020100301006072a8648ce3d020106052b8104002204819e30819b02010104309bf832f6aaaeacb78ce47ffb15e6fd0fd48683ae79df6eca39bfb8e33829ac94aa29d08911568684c2264a08a4ceb679a164036200049070ad4ed993c7770d700e9f6dc2baa83f63dd165b5507f98e8ff29b5d2e78ccbe05c8ddc955dbf0f7497e8222cfa49314fe4e269459f8e880147f70d785e530f2939e4bf9f838325bb1a80ad4cf59272ae0e5efe9a9dc33d874492596304bd3`
|
||||
|
||||
// Generated using:
|
||||
// openssl ecparam -genkey -name secp521r1 | openssl pkcs8 -topk8 -nocrypt
|
||||
//
|
||||
// Note that OpenSSL will truncate the private key if it can (i.e. it emits it
|
||||
// like an integer, even though it's an OCTET STRING field). Thus if you
|
||||
// regenerate this you may, randomly, find that it's a byte shorter than
|
||||
// expected and the Go test will fail to recreate it exactly.
|
||||
var pkcs8P521PrivateKeyHex = `3081ee020100301006072a8648ce3d020106052b810400230481d63081d3020101044200cfe0b87113a205cf291bb9a8cd1a74ac6c7b2ebb8199aaa9a5010d8b8012276fa3c22ac913369fa61beec2a3b8b4516bc049bde4fb3b745ac11b56ab23ac52e361a1818903818600040138f75acdd03fbafa4f047a8e4b272ba9d555c667962b76f6f232911a5786a0964e5edea6bd21a6f8725720958de049c6e3e6661c1c91b227cebee916c0319ed6ca003db0a3206d372229baf9dd25d868bf81140a518114803ce40c1855074d68c4e9dab9e65efba7064c703b400f1767f217dac82715ac1f6d88c74baf47a7971de4ea`
|
||||
|
||||
func TestPKCS8(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
keyHex string
|
||||
keyType reflect.Type
|
||||
curve elliptic.Curve
|
||||
}{
|
||||
{
|
||||
name: "RSA private key",
|
||||
keyHex: pkcs8RSAPrivateKeyHex,
|
||||
keyType: reflect.TypeOf(&rsa.PrivateKey{}),
|
||||
},
|
||||
{
|
||||
name: "P-224 private key",
|
||||
keyHex: pkcs8P224PrivateKeyHex,
|
||||
keyType: reflect.TypeOf(&ecdsa.PrivateKey{}),
|
||||
curve: elliptic.P224(),
|
||||
},
|
||||
{
|
||||
name: "P-256 private key",
|
||||
keyHex: pkcs8P256PrivateKeyHex,
|
||||
keyType: reflect.TypeOf(&ecdsa.PrivateKey{}),
|
||||
curve: elliptic.P256(),
|
||||
},
|
||||
{
|
||||
name: "P-384 private key",
|
||||
keyHex: pkcs8P384PrivateKeyHex,
|
||||
keyType: reflect.TypeOf(&ecdsa.PrivateKey{}),
|
||||
curve: elliptic.P384(),
|
||||
},
|
||||
{
|
||||
name: "P-521 private key",
|
||||
keyHex: pkcs8P521PrivateKeyHex,
|
||||
keyType: reflect.TypeOf(&ecdsa.PrivateKey{}),
|
||||
curve: elliptic.P521(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
derBytes, err := hex.DecodeString(test.keyHex)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed to decode hex: %s", test.name, err)
|
||||
continue
|
||||
}
|
||||
privKey, err := ParsePKCS8PrivateKey(derBytes)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed to decode PKCS#8: %s", test.name, err)
|
||||
continue
|
||||
}
|
||||
if reflect.TypeOf(privKey) != test.keyType {
|
||||
t.Errorf("%s: decoded PKCS#8 returned unexpected key type: %T", test.name, privKey)
|
||||
continue
|
||||
}
|
||||
if ecKey, isEC := privKey.(*ecdsa.PrivateKey); isEC && ecKey.Curve != test.curve {
|
||||
t.Errorf("%s: decoded PKCS#8 returned unexpected curve %#v", test.name, ecKey.Curve)
|
||||
continue
|
||||
}
|
||||
reserialised, err := MarshalPKCS8PrivateKey(privKey)
|
||||
if err != nil {
|
||||
t.Errorf("%s: failed to marshal into PKCS#8: %s", test.name, err)
|
||||
continue
|
||||
}
|
||||
if !bytes.Equal(derBytes, reserialised) {
|
||||
t.Errorf("%s: marshalled PKCS#8 didn't match original: got %x, want %x", test.name, reserialised, derBytes)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
288
vendor/github.com/google/certificate-transparency-go/x509/pkix/pkix.go
generated
vendored
Normal file
288
vendor/github.com/google/certificate-transparency-go/x509/pkix/pkix.go
generated
vendored
Normal file
@ -0,0 +1,288 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package pkix contains shared, low level structures used for ASN.1 parsing
|
||||
// and serialization of X.509 certificates, CRL and OCSP.
|
||||
package pkix
|
||||
|
||||
import (
|
||||
// START CT CHANGES
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
// END CT CHANGES
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
// AlgorithmIdentifier represents the ASN.1 structure of the same name. See RFC
|
||||
// 5280, section 4.1.1.2.
|
||||
type AlgorithmIdentifier struct {
|
||||
Algorithm asn1.ObjectIdentifier
|
||||
Parameters asn1.RawValue `asn1:"optional"`
|
||||
}
|
||||
|
||||
type RDNSequence []RelativeDistinguishedNameSET
|
||||
|
||||
var attributeTypeNames = map[string]string{
|
||||
"2.5.4.6": "C",
|
||||
"2.5.4.10": "O",
|
||||
"2.5.4.11": "OU",
|
||||
"2.5.4.3": "CN",
|
||||
"2.5.4.5": "SERIALNUMBER",
|
||||
"2.5.4.7": "L",
|
||||
"2.5.4.8": "ST",
|
||||
"2.5.4.9": "STREET",
|
||||
"2.5.4.17": "POSTALCODE",
|
||||
}
|
||||
|
||||
// String returns a string representation of the sequence r,
|
||||
// roughly following the RFC 2253 Distinguished Names syntax.
|
||||
func (r RDNSequence) String() string {
|
||||
s := ""
|
||||
for i := 0; i < len(r); i++ {
|
||||
rdn := r[len(r)-1-i]
|
||||
if i > 0 {
|
||||
s += ","
|
||||
}
|
||||
for j, tv := range rdn {
|
||||
if j > 0 {
|
||||
s += "+"
|
||||
}
|
||||
|
||||
oidString := tv.Type.String()
|
||||
typeName, ok := attributeTypeNames[oidString]
|
||||
if !ok {
|
||||
derBytes, err := asn1.Marshal(tv.Value)
|
||||
if err == nil {
|
||||
s += oidString + "=#" + hex.EncodeToString(derBytes)
|
||||
continue // No value escaping necessary.
|
||||
}
|
||||
|
||||
typeName = oidString
|
||||
}
|
||||
|
||||
valueString := fmt.Sprint(tv.Value)
|
||||
escaped := make([]rune, 0, len(valueString))
|
||||
|
||||
for k, c := range valueString {
|
||||
escape := false
|
||||
|
||||
switch c {
|
||||
case ',', '+', '"', '\\', '<', '>', ';':
|
||||
escape = true
|
||||
|
||||
case ' ':
|
||||
escape = k == 0 || k == len(valueString)-1
|
||||
|
||||
case '#':
|
||||
escape = k == 0
|
||||
}
|
||||
|
||||
if escape {
|
||||
escaped = append(escaped, '\\', c)
|
||||
} else {
|
||||
escaped = append(escaped, c)
|
||||
}
|
||||
}
|
||||
|
||||
s += typeName + "=" + string(escaped)
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
type RelativeDistinguishedNameSET []AttributeTypeAndValue
|
||||
|
||||
// AttributeTypeAndValue mirrors the ASN.1 structure of the same name in
|
||||
// http://tools.ietf.org/html/rfc5280#section-4.1.2.4
|
||||
type AttributeTypeAndValue struct {
|
||||
Type asn1.ObjectIdentifier
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// AttributeTypeAndValueSET represents a set of ASN.1 sequences of
|
||||
// AttributeTypeAndValue sequences from RFC 2986 (PKCS #10).
|
||||
type AttributeTypeAndValueSET struct {
|
||||
Type asn1.ObjectIdentifier
|
||||
Value [][]AttributeTypeAndValue `asn1:"set"`
|
||||
}
|
||||
|
||||
// Extension represents the ASN.1 structure of the same name. See RFC
|
||||
// 5280, section 4.2.
|
||||
type Extension struct {
|
||||
Id asn1.ObjectIdentifier
|
||||
Critical bool `asn1:"optional"`
|
||||
Value []byte
|
||||
}
|
||||
|
||||
// Name represents an X.509 distinguished name. This only includes the common
|
||||
// elements of a DN. When parsing, all elements are stored in Names and
|
||||
// non-standard elements can be extracted from there. When marshaling, elements
|
||||
// in ExtraNames are appended and override other values with the same OID.
|
||||
type Name struct {
|
||||
Country, Organization, OrganizationalUnit []string
|
||||
Locality, Province []string
|
||||
StreetAddress, PostalCode []string
|
||||
SerialNumber, CommonName string
|
||||
|
||||
Names []AttributeTypeAndValue
|
||||
ExtraNames []AttributeTypeAndValue
|
||||
}
|
||||
|
||||
func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
|
||||
for _, rdn := range *rdns {
|
||||
if len(rdn) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, atv := range rdn {
|
||||
n.Names = append(n.Names, atv)
|
||||
value, ok := atv.Value.(string)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
t := atv.Type
|
||||
if len(t) == 4 && t[0] == OIDAttribute[0] && t[1] == OIDAttribute[1] && t[2] == OIDAttribute[2] {
|
||||
switch t[3] {
|
||||
case OIDCommonName[3]:
|
||||
n.CommonName = value
|
||||
case OIDSerialNumber[3]:
|
||||
n.SerialNumber = value
|
||||
case OIDCountry[3]:
|
||||
n.Country = append(n.Country, value)
|
||||
case OIDLocality[3]:
|
||||
n.Locality = append(n.Locality, value)
|
||||
case OIDProvince[3]:
|
||||
n.Province = append(n.Province, value)
|
||||
case OIDStreetAddress[3]:
|
||||
n.StreetAddress = append(n.StreetAddress, value)
|
||||
case OIDOrganization[3]:
|
||||
n.Organization = append(n.Organization, value)
|
||||
case OIDOrganizationalUnit[3]:
|
||||
n.OrganizationalUnit = append(n.OrganizationalUnit, value)
|
||||
case OIDPostalCode[3]:
|
||||
n.PostalCode = append(n.PostalCode, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
OIDAttribute = asn1.ObjectIdentifier{2, 5, 4}
|
||||
OIDCountry = asn1.ObjectIdentifier{2, 5, 4, 6}
|
||||
OIDOrganization = asn1.ObjectIdentifier{2, 5, 4, 10}
|
||||
OIDOrganizationalUnit = asn1.ObjectIdentifier{2, 5, 4, 11}
|
||||
OIDCommonName = asn1.ObjectIdentifier{2, 5, 4, 3}
|
||||
OIDSerialNumber = asn1.ObjectIdentifier{2, 5, 4, 5}
|
||||
OIDLocality = asn1.ObjectIdentifier{2, 5, 4, 7}
|
||||
OIDProvince = asn1.ObjectIdentifier{2, 5, 4, 8}
|
||||
OIDStreetAddress = asn1.ObjectIdentifier{2, 5, 4, 9}
|
||||
OIDPostalCode = asn1.ObjectIdentifier{2, 5, 4, 17}
|
||||
|
||||
OIDPseudonym = asn1.ObjectIdentifier{2, 5, 4, 65}
|
||||
OIDTitle = asn1.ObjectIdentifier{2, 5, 4, 12}
|
||||
OIDDnQualifier = asn1.ObjectIdentifier{2, 5, 4, 46}
|
||||
OIDName = asn1.ObjectIdentifier{2, 5, 4, 41}
|
||||
OIDSurname = asn1.ObjectIdentifier{2, 5, 4, 4}
|
||||
OIDGivenName = asn1.ObjectIdentifier{2, 5, 4, 42}
|
||||
OIDInitials = asn1.ObjectIdentifier{2, 5, 4, 43}
|
||||
OIDGenerationQualifier = asn1.ObjectIdentifier{2, 5, 4, 44}
|
||||
)
|
||||
|
||||
// appendRDNs appends a relativeDistinguishedNameSET to the given RDNSequence
|
||||
// and returns the new value. The relativeDistinguishedNameSET contains an
|
||||
// attributeTypeAndValue for each of the given values. See RFC 5280, A.1, and
|
||||
// search for AttributeTypeAndValue.
|
||||
func (n Name) appendRDNs(in RDNSequence, values []string, oid asn1.ObjectIdentifier) RDNSequence {
|
||||
if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) {
|
||||
return in
|
||||
}
|
||||
|
||||
s := make([]AttributeTypeAndValue, len(values))
|
||||
for i, value := range values {
|
||||
s[i].Type = oid
|
||||
s[i].Value = value
|
||||
}
|
||||
|
||||
return append(in, s)
|
||||
}
|
||||
|
||||
func (n Name) ToRDNSequence() (ret RDNSequence) {
|
||||
ret = n.appendRDNs(ret, n.Country, OIDCountry)
|
||||
ret = n.appendRDNs(ret, n.Province, OIDProvince)
|
||||
ret = n.appendRDNs(ret, n.Locality, OIDLocality)
|
||||
ret = n.appendRDNs(ret, n.StreetAddress, OIDStreetAddress)
|
||||
ret = n.appendRDNs(ret, n.PostalCode, OIDPostalCode)
|
||||
ret = n.appendRDNs(ret, n.Organization, OIDOrganization)
|
||||
ret = n.appendRDNs(ret, n.OrganizationalUnit, OIDOrganizationalUnit)
|
||||
if len(n.CommonName) > 0 {
|
||||
ret = n.appendRDNs(ret, []string{n.CommonName}, OIDCommonName)
|
||||
}
|
||||
if len(n.SerialNumber) > 0 {
|
||||
ret = n.appendRDNs(ret, []string{n.SerialNumber}, OIDSerialNumber)
|
||||
}
|
||||
for _, atv := range n.ExtraNames {
|
||||
ret = append(ret, []AttributeTypeAndValue{atv})
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// String returns the string form of n, roughly following
|
||||
// the RFC 2253 Distinguished Names syntax.
|
||||
func (n Name) String() string {
|
||||
return n.ToRDNSequence().String()
|
||||
}
|
||||
|
||||
// oidInAttributeTypeAndValue returns whether a type with the given OID exists
|
||||
// in atv.
|
||||
func oidInAttributeTypeAndValue(oid asn1.ObjectIdentifier, atv []AttributeTypeAndValue) bool {
|
||||
for _, a := range atv {
|
||||
if a.Type.Equal(oid) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CertificateList represents the ASN.1 structure of the same name. See RFC
|
||||
// 5280, section 5.1. Use Certificate.CheckCRLSignature to verify the
|
||||
// signature.
|
||||
type CertificateList struct {
|
||||
TBSCertList TBSCertificateList
|
||||
SignatureAlgorithm AlgorithmIdentifier
|
||||
SignatureValue asn1.BitString
|
||||
}
|
||||
|
||||
// HasExpired reports whether certList should have been updated by now.
|
||||
func (certList *CertificateList) HasExpired(now time.Time) bool {
|
||||
return !now.Before(certList.TBSCertList.NextUpdate)
|
||||
}
|
||||
|
||||
// TBSCertificateList represents the ASN.1 structure TBSCertList. See RFC
|
||||
// 5280, section 5.1.
|
||||
type TBSCertificateList struct {
|
||||
Raw asn1.RawContent
|
||||
Version int `asn1:"optional,default:0"`
|
||||
Signature AlgorithmIdentifier
|
||||
Issuer RDNSequence
|
||||
ThisUpdate time.Time
|
||||
NextUpdate time.Time `asn1:"optional"`
|
||||
RevokedCertificates []RevokedCertificate `asn1:"optional"`
|
||||
Extensions []Extension `asn1:"tag:0,optional,explicit"`
|
||||
}
|
||||
|
||||
// RevokedCertificate represents the unnamed ASN.1 structure that makes up the
|
||||
// revokedCertificates member of the TBSCertList structure. See RFC
|
||||
// 5280, section 5.1.
|
||||
type RevokedCertificate struct {
|
||||
SerialNumber *big.Int
|
||||
RevocationTime time.Time
|
||||
Extensions []Extension `asn1:"optional"`
|
||||
}
|
362
vendor/github.com/google/certificate-transparency-go/x509/revoked.go
generated
vendored
Normal file
362
vendor/github.com/google/certificate-transparency-go/x509/revoked.go
generated
vendored
Normal file
@ -0,0 +1,362 @@
|
||||
// Copyright 2017 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/pem"
|
||||
"time"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
"github.com/google/certificate-transparency-go/x509/pkix"
|
||||
)
|
||||
|
||||
var (
|
||||
// OID values for CRL extensions (TBSCertList.Extensions), RFC 5280 s5.2.
|
||||
OIDExtensionCRLNumber = asn1.ObjectIdentifier{2, 5, 29, 20}
|
||||
OIDExtensionDeltaCRLIndicator = asn1.ObjectIdentifier{2, 5, 29, 27}
|
||||
OIDExtensionIssuingDistributionPoint = asn1.ObjectIdentifier{2, 5, 29, 28}
|
||||
// OID values for CRL entry extensions (RevokedCertificate.Extensions), RFC 5280 s5.3
|
||||
OIDExtensionCRLReasons = asn1.ObjectIdentifier{2, 5, 29, 21}
|
||||
OIDExtensionInvalidityDate = asn1.ObjectIdentifier{2, 5, 29, 24}
|
||||
OIDExtensionCertificateIssuer = asn1.ObjectIdentifier{2, 5, 29, 29}
|
||||
)
|
||||
|
||||
// RevocationReasonCode represents the reason for a certificate revocation; see RFC 5280 s5.3.1.
|
||||
type RevocationReasonCode asn1.Enumerated
|
||||
|
||||
// RevocationReasonCode values.
|
||||
var (
|
||||
Unspecified = RevocationReasonCode(0)
|
||||
KeyCompromise = RevocationReasonCode(1)
|
||||
CACompromise = RevocationReasonCode(2)
|
||||
AffiliationChanged = RevocationReasonCode(3)
|
||||
Superseded = RevocationReasonCode(4)
|
||||
CessationOfOperation = RevocationReasonCode(5)
|
||||
CertificateHold = RevocationReasonCode(6)
|
||||
RemoveFromCRL = RevocationReasonCode(8)
|
||||
PrivilegeWithdrawn = RevocationReasonCode(9)
|
||||
AACompromise = RevocationReasonCode(10)
|
||||
)
|
||||
|
||||
// ReasonFlag holds a bitmask of applicable revocation reasons, from RFC 5280 s4.2.1.13
|
||||
type ReasonFlag int
|
||||
|
||||
// ReasonFlag values.
|
||||
const (
|
||||
UnusedFlag ReasonFlag = 1 << iota
|
||||
KeyCompromiseFlag
|
||||
CACompromiseFlag
|
||||
AffiliationChangedFlag
|
||||
SupersededFlag
|
||||
CessationOfOperationFlag
|
||||
CertificateHoldFlag
|
||||
PrivilegeWithdrawnFlag
|
||||
AACompromiseFlag
|
||||
)
|
||||
|
||||
// CertificateList represents the ASN.1 structure of the same name from RFC 5280, s5.1.
|
||||
// It has the same content as pkix.CertificateList, but the contents include parsed versions
|
||||
// of any extensions.
|
||||
type CertificateList struct {
|
||||
Raw asn1.RawContent
|
||||
TBSCertList TBSCertList
|
||||
SignatureAlgorithm pkix.AlgorithmIdentifier
|
||||
SignatureValue asn1.BitString
|
||||
}
|
||||
|
||||
// ExpiredAt reports whether now is past the expiry time of certList.
|
||||
func (certList *CertificateList) ExpiredAt(now time.Time) bool {
|
||||
return now.After(certList.TBSCertList.NextUpdate)
|
||||
}
|
||||
|
||||
// Indication of whether extensions need to be critical or non-critical. Extensions that
|
||||
// can be either are omitted from the map.
|
||||
var listExtCritical = map[string]bool{
|
||||
// From RFC 5280...
|
||||
OIDExtensionAuthorityKeyId.String(): false, // s5.2.1
|
||||
OIDExtensionIssuerAltName.String(): false, // s5.2.2
|
||||
OIDExtensionCRLNumber.String(): false, // s5.2.3
|
||||
OIDExtensionDeltaCRLIndicator.String(): true, // s5.2.4
|
||||
OIDExtensionIssuingDistributionPoint.String(): true, // s5.2.5
|
||||
OIDExtensionFreshestCRL.String(): false, // s5.2.6
|
||||
OIDExtensionAuthorityInfoAccess.String(): false, // s5.2.7
|
||||
}
|
||||
|
||||
var certExtCritical = map[string]bool{
|
||||
// From RFC 5280...
|
||||
OIDExtensionCRLReasons.String(): false, // s5.3.1
|
||||
OIDExtensionInvalidityDate.String(): false, // s5.3.2
|
||||
OIDExtensionCertificateIssuer.String(): true, // s5.3.3
|
||||
}
|
||||
|
||||
// IssuingDistributionPoint represents the ASN.1 structure of the same
|
||||
// name
|
||||
type IssuingDistributionPoint struct {
|
||||
DistributionPoint distributionPointName `asn1:"optional,tag:0"`
|
||||
OnlyContainsUserCerts bool `asn1:"optional,tag:1"`
|
||||
OnlyContainsCACerts bool `asn1:"optional,tag:2"`
|
||||
OnlySomeReasons asn1.BitString `asn1:"optional,tag:3"`
|
||||
IndirectCRL bool `asn1:"optional,tag:4"`
|
||||
OnlyContainsAttributeCerts bool `asn1:"optional,tag:5"`
|
||||
}
|
||||
|
||||
// TBSCertList represents the ASN.1 structure of the same name from RFC
|
||||
// 5280, section 5.1. It has the same content as pkix.TBSCertificateList
|
||||
// but the extensions are included in a parsed format.
|
||||
type TBSCertList struct {
|
||||
Raw asn1.RawContent
|
||||
Version int
|
||||
Signature pkix.AlgorithmIdentifier
|
||||
Issuer pkix.RDNSequence
|
||||
ThisUpdate time.Time
|
||||
NextUpdate time.Time
|
||||
RevokedCertificates []*RevokedCertificate
|
||||
Extensions []pkix.Extension
|
||||
// Cracked out extensions:
|
||||
AuthorityKeyID []byte
|
||||
IssuerAltNames GeneralNames
|
||||
CRLNumber int
|
||||
BaseCRLNumber int // -1 if no delta CRL present
|
||||
IssuingDistributionPoint IssuingDistributionPoint
|
||||
IssuingDPFullNames GeneralNames
|
||||
FreshestCRLDistributionPoint []string
|
||||
OCSPServer []string
|
||||
IssuingCertificateURL []string
|
||||
}
|
||||
|
||||
// ParseCertificateList parses a CertificateList (e.g. a CRL) from the given
|
||||
// bytes. It's often the case that PEM encoded CRLs will appear where they
|
||||
// should be DER encoded, so this function will transparently handle PEM
|
||||
// encoding as long as there isn't any leading garbage.
|
||||
func ParseCertificateList(clBytes []byte) (*CertificateList, error) {
|
||||
if bytes.HasPrefix(clBytes, pemCRLPrefix) {
|
||||
block, _ := pem.Decode(clBytes)
|
||||
if block != nil && block.Type == pemType {
|
||||
clBytes = block.Bytes
|
||||
}
|
||||
}
|
||||
return ParseCertificateListDER(clBytes)
|
||||
}
|
||||
|
||||
// ParseCertificateListDER parses a DER encoded CertificateList from the given bytes.
|
||||
// For non-fatal errors, this function returns both an error and a CertificateList
|
||||
// object.
|
||||
func ParseCertificateListDER(derBytes []byte) (*CertificateList, error) {
|
||||
var errs Errors
|
||||
// First parse the DER into the pkix structures.
|
||||
pkixList := new(pkix.CertificateList)
|
||||
if rest, err := asn1.Unmarshal(derBytes, pkixList); err != nil {
|
||||
errs.AddID(ErrInvalidCertList, err)
|
||||
return nil, &errs
|
||||
} else if len(rest) != 0 {
|
||||
errs.AddID(ErrTrailingCertList)
|
||||
return nil, &errs
|
||||
}
|
||||
|
||||
// Transcribe the revoked certs but crack out extensions.
|
||||
revokedCerts := make([]*RevokedCertificate, len(pkixList.TBSCertList.RevokedCertificates))
|
||||
for i, pkixRevoked := range pkixList.TBSCertList.RevokedCertificates {
|
||||
revokedCerts[i] = parseRevokedCertificate(pkixRevoked, &errs)
|
||||
if revokedCerts[i] == nil {
|
||||
return nil, &errs
|
||||
}
|
||||
}
|
||||
|
||||
certList := CertificateList{
|
||||
Raw: derBytes,
|
||||
TBSCertList: TBSCertList{
|
||||
Raw: pkixList.TBSCertList.Raw,
|
||||
Version: pkixList.TBSCertList.Version,
|
||||
Signature: pkixList.TBSCertList.Signature,
|
||||
Issuer: pkixList.TBSCertList.Issuer,
|
||||
ThisUpdate: pkixList.TBSCertList.ThisUpdate,
|
||||
NextUpdate: pkixList.TBSCertList.NextUpdate,
|
||||
RevokedCertificates: revokedCerts,
|
||||
Extensions: pkixList.TBSCertList.Extensions,
|
||||
CRLNumber: -1,
|
||||
BaseCRLNumber: -1,
|
||||
},
|
||||
SignatureAlgorithm: pkixList.SignatureAlgorithm,
|
||||
SignatureValue: pkixList.SignatureValue,
|
||||
}
|
||||
|
||||
// Now crack out extensions.
|
||||
for _, e := range certList.TBSCertList.Extensions {
|
||||
if expectCritical, present := listExtCritical[e.Id.String()]; present {
|
||||
if e.Critical && !expectCritical {
|
||||
errs.AddID(ErrUnexpectedlyCriticalCertListExtension, e.Id)
|
||||
} else if !e.Critical && expectCritical {
|
||||
errs.AddID(ErrUnexpectedlyNonCriticalCertListExtension, e.Id)
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case e.Id.Equal(OIDExtensionAuthorityKeyId):
|
||||
// RFC 5280 s5.2.1
|
||||
var a authKeyId
|
||||
if rest, err := asn1.Unmarshal(e.Value, &a); err != nil {
|
||||
errs.AddID(ErrInvalidCertListAuthKeyID, err)
|
||||
} else if len(rest) != 0 {
|
||||
errs.AddID(ErrTrailingCertListAuthKeyID)
|
||||
}
|
||||
certList.TBSCertList.AuthorityKeyID = a.Id
|
||||
case e.Id.Equal(OIDExtensionIssuerAltName):
|
||||
// RFC 5280 s5.2.2
|
||||
if err := parseGeneralNames(e.Value, &certList.TBSCertList.IssuerAltNames); err != nil {
|
||||
errs.AddID(ErrInvalidCertListIssuerAltName, err)
|
||||
}
|
||||
case e.Id.Equal(OIDExtensionCRLNumber):
|
||||
// RFC 5280 s5.2.3
|
||||
if rest, err := asn1.Unmarshal(e.Value, &certList.TBSCertList.CRLNumber); err != nil {
|
||||
errs.AddID(ErrInvalidCertListCRLNumber, err)
|
||||
} else if len(rest) != 0 {
|
||||
errs.AddID(ErrTrailingCertListCRLNumber)
|
||||
}
|
||||
if certList.TBSCertList.CRLNumber < 0 {
|
||||
errs.AddID(ErrNegativeCertListCRLNumber, certList.TBSCertList.CRLNumber)
|
||||
}
|
||||
case e.Id.Equal(OIDExtensionDeltaCRLIndicator):
|
||||
// RFC 5280 s5.2.4
|
||||
if rest, err := asn1.Unmarshal(e.Value, &certList.TBSCertList.BaseCRLNumber); err != nil {
|
||||
errs.AddID(ErrInvalidCertListDeltaCRL, err)
|
||||
} else if len(rest) != 0 {
|
||||
errs.AddID(ErrTrailingCertListDeltaCRL)
|
||||
}
|
||||
if certList.TBSCertList.BaseCRLNumber < 0 {
|
||||
errs.AddID(ErrNegativeCertListDeltaCRL, certList.TBSCertList.BaseCRLNumber)
|
||||
}
|
||||
case e.Id.Equal(OIDExtensionIssuingDistributionPoint):
|
||||
parseIssuingDistributionPoint(e.Value, &certList.TBSCertList.IssuingDistributionPoint, &certList.TBSCertList.IssuingDPFullNames, &errs)
|
||||
case e.Id.Equal(OIDExtensionFreshestCRL):
|
||||
// RFC 5280 s5.2.6
|
||||
if err := parseDistributionPoints(e.Value, &certList.TBSCertList.FreshestCRLDistributionPoint); err != nil {
|
||||
errs.AddID(ErrInvalidCertListFreshestCRL, err)
|
||||
return nil, err
|
||||
}
|
||||
case e.Id.Equal(OIDExtensionAuthorityInfoAccess):
|
||||
// RFC 5280 s5.2.7
|
||||
var aia []authorityInfoAccess
|
||||
if rest, err := asn1.Unmarshal(e.Value, &aia); err != nil {
|
||||
errs.AddID(ErrInvalidCertListAuthInfoAccess, err)
|
||||
} else if len(rest) != 0 {
|
||||
errs.AddID(ErrTrailingCertListAuthInfoAccess)
|
||||
}
|
||||
|
||||
for _, v := range aia {
|
||||
// GeneralName: uniformResourceIdentifier [6] IA5String
|
||||
if v.Location.Tag != tagURI {
|
||||
continue
|
||||
}
|
||||
switch {
|
||||
case v.Method.Equal(OIDAuthorityInfoAccessOCSP):
|
||||
certList.TBSCertList.OCSPServer = append(certList.TBSCertList.OCSPServer, string(v.Location.Bytes))
|
||||
case v.Method.Equal(OIDAuthorityInfoAccessIssuers):
|
||||
certList.TBSCertList.IssuingCertificateURL = append(certList.TBSCertList.IssuingCertificateURL, string(v.Location.Bytes))
|
||||
}
|
||||
// TODO(drysdale): cope with more possibilities
|
||||
}
|
||||
default:
|
||||
if e.Critical {
|
||||
errs.AddID(ErrUnhandledCriticalCertListExtension, e.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errs.Fatal() {
|
||||
return nil, &errs
|
||||
}
|
||||
if errs.Empty() {
|
||||
return &certList, nil
|
||||
}
|
||||
return &certList, &errs
|
||||
}
|
||||
|
||||
func parseIssuingDistributionPoint(data []byte, idp *IssuingDistributionPoint, name *GeneralNames, errs *Errors) {
|
||||
// RFC 5280 s5.2.5
|
||||
if rest, err := asn1.Unmarshal(data, idp); err != nil {
|
||||
errs.AddID(ErrInvalidCertListIssuingDP, err)
|
||||
} else if len(rest) != 0 {
|
||||
errs.AddID(ErrTrailingCertListIssuingDP)
|
||||
}
|
||||
|
||||
typeCount := 0
|
||||
if idp.OnlyContainsUserCerts {
|
||||
typeCount++
|
||||
}
|
||||
if idp.OnlyContainsCACerts {
|
||||
typeCount++
|
||||
}
|
||||
if idp.OnlyContainsAttributeCerts {
|
||||
typeCount++
|
||||
}
|
||||
if typeCount > 1 {
|
||||
errs.AddID(ErrCertListIssuingDPMultipleTypes, idp.OnlyContainsUserCerts, idp.OnlyContainsCACerts, idp.OnlyContainsAttributeCerts)
|
||||
}
|
||||
for _, fn := range idp.DistributionPoint.FullName {
|
||||
if _, err := parseGeneralName(fn.FullBytes, name, false); err != nil {
|
||||
errs.AddID(ErrCertListIssuingDPInvalidFullName, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// RevokedCertificate represents the unnamed ASN.1 structure that makes up the
|
||||
// revokedCertificates member of the TBSCertList structure from RFC 5280, s5.1.
|
||||
// It has the same content as pkix.RevokedCertificate but the extensions are
|
||||
// included in a parsed format.
|
||||
type RevokedCertificate struct {
|
||||
pkix.RevokedCertificate
|
||||
// Cracked out extensions:
|
||||
RevocationReason RevocationReasonCode
|
||||
InvalidityDate time.Time
|
||||
Issuer GeneralNames
|
||||
}
|
||||
|
||||
func parseRevokedCertificate(pkixRevoked pkix.RevokedCertificate, errs *Errors) *RevokedCertificate {
|
||||
result := RevokedCertificate{RevokedCertificate: pkixRevoked}
|
||||
for _, e := range pkixRevoked.Extensions {
|
||||
if expectCritical, present := certExtCritical[e.Id.String()]; present {
|
||||
if e.Critical && !expectCritical {
|
||||
errs.AddID(ErrUnexpectedlyCriticalRevokedCertExtension, e.Id)
|
||||
} else if !e.Critical && expectCritical {
|
||||
errs.AddID(ErrUnexpectedlyNonCriticalRevokedCertExtension, e.Id)
|
||||
}
|
||||
}
|
||||
switch {
|
||||
case e.Id.Equal(OIDExtensionCRLReasons):
|
||||
// RFC 5280, s5.3.1
|
||||
var reason asn1.Enumerated
|
||||
if rest, err := asn1.Unmarshal(e.Value, &reason); err != nil {
|
||||
errs.AddID(ErrInvalidRevocationReason, err)
|
||||
} else if len(rest) != 0 {
|
||||
errs.AddID(ErrTrailingRevocationReason)
|
||||
}
|
||||
result.RevocationReason = RevocationReasonCode(reason)
|
||||
case e.Id.Equal(OIDExtensionInvalidityDate):
|
||||
// RFC 5280, s5.3.2
|
||||
if rest, err := asn1.Unmarshal(e.Value, &result.InvalidityDate); err != nil {
|
||||
errs.AddID(ErrInvalidRevocationInvalidityDate, err)
|
||||
} else if len(rest) != 0 {
|
||||
errs.AddID(ErrTrailingRevocationInvalidityDate)
|
||||
}
|
||||
case e.Id.Equal(OIDExtensionCertificateIssuer):
|
||||
// RFC 5280, s5.3.3
|
||||
if err := parseGeneralNames(e.Value, &result.Issuer); err != nil {
|
||||
errs.AddID(ErrInvalidRevocationIssuer, err)
|
||||
}
|
||||
default:
|
||||
if e.Critical {
|
||||
errs.AddID(ErrUnhandledCriticalRevokedCertExtension, e.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &result
|
||||
}
|
||||
|
||||
// CheckCertificateListSignature checks that the signature in crl is from c.
|
||||
func (c *Certificate) CheckCertificateListSignature(crl *CertificateList) error {
|
||||
algo := SignatureAlgorithmFromAI(crl.SignatureAlgorithm)
|
||||
return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign())
|
||||
}
|
2123
vendor/github.com/google/certificate-transparency-go/x509/revoked_test.go
generated
vendored
Normal file
2123
vendor/github.com/google/certificate-transparency-go/x509/revoked_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
22
vendor/github.com/google/certificate-transparency-go/x509/root.go
generated
vendored
Normal file
22
vendor/github.com/google/certificate-transparency-go/x509/root.go
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import "sync"
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
systemRoots *CertPool
|
||||
systemRootsErr error
|
||||
)
|
||||
|
||||
func systemRootsPool() *CertPool {
|
||||
once.Do(initSystemRoots)
|
||||
return systemRoots
|
||||
}
|
||||
|
||||
func initSystemRoots() {
|
||||
systemRoots, systemRootsErr = loadSystemRoots()
|
||||
}
|
15
vendor/github.com/google/certificate-transparency-go/x509/root_bsd.go
generated
vendored
Normal file
15
vendor/github.com/google/certificate-transparency-go/x509/root_bsd.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly freebsd netbsd openbsd
|
||||
|
||||
package x509
|
||||
|
||||
// Possible certificate files; stop after finding one.
|
||||
var certFiles = []string{
|
||||
"/usr/local/etc/ssl/cert.pem", // FreeBSD
|
||||
"/etc/ssl/cert.pem", // OpenBSD
|
||||
"/usr/local/share/certs/ca-root-nss.crt", // DragonFly
|
||||
"/etc/openssl/certs/ca-certificates.crt", // NetBSD
|
||||
}
|
252
vendor/github.com/google/certificate-transparency-go/x509/root_cgo_darwin.go
generated
vendored
Normal file
252
vendor/github.com/google/certificate-transparency-go/x509/root_cgo_darwin.go
generated
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo,!arm,!arm64,!ios
|
||||
|
||||
package x509
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1080
|
||||
#cgo LDFLAGS: -framework CoreFoundation -framework Security
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <Security/Security.h>
|
||||
|
||||
// FetchPEMRootsCTX509_MountainLion is the version of FetchPEMRoots from Go 1.6
|
||||
// which still works on OS X 10.8 (Mountain Lion).
|
||||
// It lacks support for admin & user cert domains.
|
||||
// See golang.org/issue/16473
|
||||
int FetchPEMRootsCTX509_MountainLion(CFDataRef *pemRoots) {
|
||||
if (pemRoots == NULL) {
|
||||
return -1;
|
||||
}
|
||||
CFArrayRef certs = NULL;
|
||||
OSStatus err = SecTrustCopyAnchorCertificates(&certs);
|
||||
if (err != noErr) {
|
||||
return -1;
|
||||
}
|
||||
CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
int i, ncerts = CFArrayGetCount(certs);
|
||||
for (i = 0; i < ncerts; i++) {
|
||||
CFDataRef data = NULL;
|
||||
SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
|
||||
if (cert == NULL) {
|
||||
continue;
|
||||
}
|
||||
// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
|
||||
// Once we support weak imports via cgo we should prefer that, and fall back to this
|
||||
// for older systems.
|
||||
err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
|
||||
if (err != noErr) {
|
||||
continue;
|
||||
}
|
||||
if (data != NULL) {
|
||||
CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
|
||||
CFRelease(data);
|
||||
}
|
||||
}
|
||||
CFRelease(certs);
|
||||
*pemRoots = combinedData;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// useOldCodeCTX509 reports whether the running machine is OS X 10.8 Mountain Lion
|
||||
// or older. We only support Mountain Lion and higher, but we'll at least try our
|
||||
// best on older machines and continue to use the old code path.
|
||||
//
|
||||
// See golang.org/issue/16473
|
||||
int useOldCodeCTX509() {
|
||||
char str[256];
|
||||
size_t size = sizeof(str);
|
||||
memset(str, 0, size);
|
||||
sysctlbyname("kern.osrelease", str, &size, NULL, 0);
|
||||
// OS X 10.8 is osrelease "12.*", 10.7 is 11.*, 10.6 is 10.*.
|
||||
// We never supported things before that.
|
||||
return memcmp(str, "12.", 3) == 0 || memcmp(str, "11.", 3) == 0 || memcmp(str, "10.", 3) == 0;
|
||||
}
|
||||
|
||||
// FetchPEMRootsCTX509 fetches the system's list of trusted X.509 root certificates.
|
||||
//
|
||||
// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
|
||||
// certificates of the system. On failure, the function returns -1.
|
||||
// Additionally, it fills untrustedPemRoots with certs that must be removed from pemRoots.
|
||||
//
|
||||
// Note: The CFDataRef returned in pemRoots and untrustedPemRoots must
|
||||
// be released (using CFRelease) after we've consumed its content.
|
||||
int FetchPEMRootsCTX509(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
|
||||
if (useOldCodeCTX509()) {
|
||||
return FetchPEMRootsCTX509_MountainLion(pemRoots);
|
||||
}
|
||||
|
||||
// Get certificates from all domains, not just System, this lets
|
||||
// the user add CAs to their "login" keychain, and Admins to add
|
||||
// to the "System" keychain
|
||||
SecTrustSettingsDomain domains[] = { kSecTrustSettingsDomainSystem,
|
||||
kSecTrustSettingsDomainAdmin,
|
||||
kSecTrustSettingsDomainUser };
|
||||
|
||||
int numDomains = sizeof(domains)/sizeof(SecTrustSettingsDomain);
|
||||
if (pemRoots == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// kSecTrustSettingsResult is defined as CFSTR("kSecTrustSettingsResult"),
|
||||
// but the Go linker's internal linking mode can't handle CFSTR relocations.
|
||||
// Create our own dynamic string instead and release it below.
|
||||
CFStringRef policy = CFStringCreateWithCString(NULL, "kSecTrustSettingsResult", kCFStringEncodingUTF8);
|
||||
|
||||
CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
CFMutableDataRef combinedUntrustedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
||||
for (int i = 0; i < numDomains; i++) {
|
||||
CFArrayRef certs = NULL;
|
||||
OSStatus err = SecTrustSettingsCopyCertificates(domains[i], &certs);
|
||||
if (err != noErr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
CFIndex numCerts = CFArrayGetCount(certs);
|
||||
for (int j = 0; j < numCerts; j++) {
|
||||
CFDataRef data = NULL;
|
||||
CFErrorRef errRef = NULL;
|
||||
CFArrayRef trustSettings = NULL;
|
||||
SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, j);
|
||||
if (cert == NULL) {
|
||||
continue;
|
||||
}
|
||||
// We only want trusted certs.
|
||||
int untrusted = 0;
|
||||
int trustAsRoot = 0;
|
||||
int trustRoot = 0;
|
||||
if (i == 0) {
|
||||
trustAsRoot = 1;
|
||||
} else {
|
||||
// Certs found in the system domain are always trusted. If the user
|
||||
// configures "Never Trust" on such a cert, it will also be found in the
|
||||
// admin or user domain, causing it to be added to untrustedPemRoots. The
|
||||
// Go code will then clean this up.
|
||||
|
||||
// Trust may be stored in any of the domains. According to Apple's
|
||||
// SecTrustServer.c, "user trust settings overrule admin trust settings",
|
||||
// so take the last trust settings array we find.
|
||||
// Skip the system domain since it is always trusted.
|
||||
for (int k = i; k < numDomains; k++) {
|
||||
CFArrayRef domainTrustSettings = NULL;
|
||||
err = SecTrustSettingsCopyTrustSettings(cert, domains[k], &domainTrustSettings);
|
||||
if (err == errSecSuccess && domainTrustSettings != NULL) {
|
||||
if (trustSettings) {
|
||||
CFRelease(trustSettings);
|
||||
}
|
||||
trustSettings = domainTrustSettings;
|
||||
}
|
||||
}
|
||||
if (trustSettings == NULL) {
|
||||
// "this certificate must be verified to a known trusted certificate"; aka not a root.
|
||||
continue;
|
||||
}
|
||||
for (CFIndex k = 0; k < CFArrayGetCount(trustSettings); k++) {
|
||||
CFNumberRef cfNum;
|
||||
CFDictionaryRef tSetting = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, k);
|
||||
if (CFDictionaryGetValueIfPresent(tSetting, policy, (const void**)&cfNum)){
|
||||
SInt32 result = 0;
|
||||
CFNumberGetValue(cfNum, kCFNumberSInt32Type, &result);
|
||||
// TODO: The rest of the dictionary specifies conditions for evaluation.
|
||||
if (result == kSecTrustSettingsResultDeny) {
|
||||
untrusted = 1;
|
||||
} else if (result == kSecTrustSettingsResultTrustAsRoot) {
|
||||
trustAsRoot = 1;
|
||||
} else if (result == kSecTrustSettingsResultTrustRoot) {
|
||||
trustRoot = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
CFRelease(trustSettings);
|
||||
}
|
||||
|
||||
if (trustRoot) {
|
||||
// We only want to add Root CAs, so make sure Subject and Issuer Name match
|
||||
CFDataRef subjectName = SecCertificateCopyNormalizedSubjectContent(cert, &errRef);
|
||||
if (errRef != NULL) {
|
||||
CFRelease(errRef);
|
||||
continue;
|
||||
}
|
||||
CFDataRef issuerName = SecCertificateCopyNormalizedIssuerContent(cert, &errRef);
|
||||
if (errRef != NULL) {
|
||||
CFRelease(subjectName);
|
||||
CFRelease(errRef);
|
||||
continue;
|
||||
}
|
||||
Boolean equal = CFEqual(subjectName, issuerName);
|
||||
CFRelease(subjectName);
|
||||
CFRelease(issuerName);
|
||||
if (!equal) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
|
||||
// Once we support weak imports via cgo we should prefer that, and fall back to this
|
||||
// for older systems.
|
||||
err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
|
||||
if (err != noErr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data != NULL) {
|
||||
if (!trustRoot && !trustAsRoot) {
|
||||
untrusted = 1;
|
||||
}
|
||||
CFMutableDataRef appendTo = untrusted ? combinedUntrustedData : combinedData;
|
||||
CFDataAppendBytes(appendTo, CFDataGetBytePtr(data), CFDataGetLength(data));
|
||||
CFRelease(data);
|
||||
}
|
||||
}
|
||||
CFRelease(certs);
|
||||
}
|
||||
CFRelease(policy);
|
||||
*pemRoots = combinedData;
|
||||
*untrustedPemRoots = combinedUntrustedData;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
roots := NewCertPool()
|
||||
|
||||
var data C.CFDataRef
|
||||
setNilCFRef(&data)
|
||||
var untrustedData C.CFDataRef
|
||||
setNilCFRef(&untrustedData)
|
||||
err := C.FetchPEMRootsCTX509(&data, &untrustedData)
|
||||
if err == -1 {
|
||||
// TODO: better error message
|
||||
return nil, errors.New("crypto/x509: failed to load darwin system roots with cgo")
|
||||
}
|
||||
|
||||
defer C.CFRelease(C.CFTypeRef(data))
|
||||
buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
|
||||
roots.AppendCertsFromPEM(buf)
|
||||
if isNilCFRef(untrustedData) {
|
||||
return roots, nil
|
||||
}
|
||||
defer C.CFRelease(C.CFTypeRef(untrustedData))
|
||||
buf = C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(untrustedData)), C.int(C.CFDataGetLength(untrustedData)))
|
||||
untrustedRoots := NewCertPool()
|
||||
untrustedRoots.AppendCertsFromPEM(buf)
|
||||
|
||||
trustedRoots := NewCertPool()
|
||||
for _, c := range roots.certs {
|
||||
if !untrustedRoots.contains(c) {
|
||||
trustedRoots.AddCert(c)
|
||||
}
|
||||
}
|
||||
return trustedRoots, nil
|
||||
}
|
264
vendor/github.com/google/certificate-transparency-go/x509/root_darwin.go
generated
vendored
Normal file
264
vendor/github.com/google/certificate-transparency-go/x509/root_darwin.go
generated
vendored
Normal file
@ -0,0 +1,264 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:generate go run root_darwin_arm_gen.go -output root_darwin_armx.go
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var debugExecDarwinRoots = strings.Contains(os.Getenv("GODEBUG"), "x509roots=1")
|
||||
|
||||
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// This code is only used when compiling without cgo.
|
||||
// It is here, instead of root_nocgo_darwin.go, so that tests can check it
|
||||
// even if the tests are run with cgo enabled.
|
||||
// The linker will not include these unused functions in binaries built with cgo enabled.
|
||||
|
||||
// execSecurityRoots finds the macOS list of trusted root certificates
|
||||
// using only command-line tools. This is our fallback path when cgo isn't available.
|
||||
//
|
||||
// The strategy is as follows:
|
||||
//
|
||||
// 1. Run "security trust-settings-export" and "security
|
||||
// trust-settings-export -d" to discover the set of certs with some
|
||||
// user-tweaked trust policy. We're too lazy to parse the XML (at
|
||||
// least at this stage of Go 1.8) to understand what the trust
|
||||
// policy actually is. We just learn that there is _some_ policy.
|
||||
//
|
||||
// 2. Run "security find-certificate" to dump the list of system root
|
||||
// CAs in PEM format.
|
||||
//
|
||||
// 3. For each dumped cert, conditionally verify it with "security
|
||||
// verify-cert" if that cert was in the set discovered in Step 1.
|
||||
// Without the Step 1 optimization, running "security verify-cert"
|
||||
// 150-200 times takes 3.5 seconds. With the optimization, the
|
||||
// whole process takes about 180 milliseconds with 1 untrusted root
|
||||
// CA. (Compared to 110ms in the cgo path)
|
||||
func execSecurityRoots() (*CertPool, error) {
|
||||
hasPolicy, err := getCertsWithTrustPolicy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if debugExecDarwinRoots {
|
||||
println(fmt.Sprintf("crypto/x509: %d certs have a trust policy", len(hasPolicy)))
|
||||
}
|
||||
|
||||
args := []string{"find-certificate", "-a", "-p",
|
||||
"/System/Library/Keychains/SystemRootCertificates.keychain",
|
||||
"/Library/Keychains/System.keychain",
|
||||
}
|
||||
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
if debugExecDarwinRoots {
|
||||
println(fmt.Sprintf("crypto/x509: get current user: %v", err))
|
||||
}
|
||||
} else {
|
||||
args = append(args,
|
||||
filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain"),
|
||||
|
||||
// Fresh installs of Sierra use a slightly different path for the login keychain
|
||||
filepath.Join(u.HomeDir, "/Library/Keychains/login.keychain-db"),
|
||||
)
|
||||
}
|
||||
|
||||
cmd := exec.Command("/usr/bin/security", args...)
|
||||
data, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var (
|
||||
mu sync.Mutex
|
||||
roots = NewCertPool()
|
||||
numVerified int // number of execs of 'security verify-cert', for debug stats
|
||||
)
|
||||
|
||||
blockCh := make(chan *pem.Block)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Using 4 goroutines to pipe into verify-cert seems to be
|
||||
// about the best we can do. The verify-cert binary seems to
|
||||
// just RPC to another server with coarse locking anyway, so
|
||||
// running 16 at a time for instance doesn't help at all. Due
|
||||
// to the "if hasPolicy" check below, though, we will rarely
|
||||
// (or never) call verify-cert on stock macOS systems, though.
|
||||
// The hope is that we only call verify-cert when the user has
|
||||
// tweaked their trust policy. These 4 goroutines are only
|
||||
// defensive in the pathological case of many trust edits.
|
||||
for i := 0; i < 4; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for block := range blockCh {
|
||||
cert, err := ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
sha1CapHex := fmt.Sprintf("%X", sha1.Sum(block.Bytes))
|
||||
|
||||
valid := true
|
||||
verifyChecks := 0
|
||||
if hasPolicy[sha1CapHex] {
|
||||
verifyChecks++
|
||||
if !verifyCertWithSystem(block, cert) {
|
||||
valid = false
|
||||
}
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
numVerified += verifyChecks
|
||||
if valid {
|
||||
roots.AddCert(cert)
|
||||
}
|
||||
mu.Unlock()
|
||||
}
|
||||
}()
|
||||
}
|
||||
for len(data) > 0 {
|
||||
var block *pem.Block
|
||||
block, data = pem.Decode(data)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
blockCh <- block
|
||||
}
|
||||
close(blockCh)
|
||||
wg.Wait()
|
||||
|
||||
if debugExecDarwinRoots {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
println(fmt.Sprintf("crypto/x509: ran security verify-cert %d times", numVerified))
|
||||
}
|
||||
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
func verifyCertWithSystem(block *pem.Block, cert *Certificate) bool {
|
||||
data := pem.EncodeToMemory(block)
|
||||
|
||||
f, err := ioutil.TempFile("", "cert")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "can't create temporary file for cert: %v", err)
|
||||
return false
|
||||
}
|
||||
defer os.Remove(f.Name())
|
||||
if _, err := f.Write(data); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
|
||||
return false
|
||||
}
|
||||
if err := f.Close(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "can't write temporary file for cert: %v", err)
|
||||
return false
|
||||
}
|
||||
cmd := exec.Command("/usr/bin/security", "verify-cert", "-c", f.Name(), "-l", "-L")
|
||||
var stderr bytes.Buffer
|
||||
if debugExecDarwinRoots {
|
||||
cmd.Stderr = &stderr
|
||||
}
|
||||
if err := cmd.Run(); err != nil {
|
||||
if debugExecDarwinRoots {
|
||||
println(fmt.Sprintf("crypto/x509: verify-cert rejected %s: %q", cert.Subject.CommonName, bytes.TrimSpace(stderr.Bytes())))
|
||||
}
|
||||
return false
|
||||
}
|
||||
if debugExecDarwinRoots {
|
||||
println(fmt.Sprintf("crypto/x509: verify-cert approved %s", cert.Subject.CommonName))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// getCertsWithTrustPolicy returns the set of certs that have a
|
||||
// possibly-altered trust policy. The keys of the map are capitalized
|
||||
// sha1 hex of the raw cert.
|
||||
// They are the certs that should be checked against `security
|
||||
// verify-cert` to see whether the user altered the default trust
|
||||
// settings. This code is only used for cgo-disabled builds.
|
||||
func getCertsWithTrustPolicy() (map[string]bool, error) {
|
||||
set := map[string]bool{}
|
||||
td, err := ioutil.TempDir("", "x509trustpolicy")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer os.RemoveAll(td)
|
||||
run := func(file string, args ...string) error {
|
||||
file = filepath.Join(td, file)
|
||||
args = append(args, file)
|
||||
cmd := exec.Command("/usr/bin/security", args...)
|
||||
var stderr bytes.Buffer
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
// If there are no trust settings, the
|
||||
// `security trust-settings-export` command
|
||||
// fails with:
|
||||
// exit status 1, SecTrustSettingsCreateExternalRepresentation: No Trust Settings were found.
|
||||
// Rather than match on English substrings that are probably
|
||||
// localized on macOS, just interpret any failure to mean that
|
||||
// there are no trust settings.
|
||||
if debugExecDarwinRoots {
|
||||
println(fmt.Sprintf("crypto/x509: exec %q: %v, %s", cmd.Args, err, stderr.Bytes()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
// Gather all the runs of 40 capitalized hex characters.
|
||||
br := bufio.NewReader(f)
|
||||
var hexBuf bytes.Buffer
|
||||
for {
|
||||
b, err := br.ReadByte()
|
||||
isHex := ('A' <= b && b <= 'F') || ('0' <= b && b <= '9')
|
||||
if isHex {
|
||||
hexBuf.WriteByte(b)
|
||||
} else {
|
||||
if hexBuf.Len() == 40 {
|
||||
set[hexBuf.String()] = true
|
||||
}
|
||||
hexBuf.Reset()
|
||||
}
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
if err := run("user", "trust-settings-export"); err != nil {
|
||||
return nil, fmt.Errorf("dump-trust-settings (user): %v", err)
|
||||
}
|
||||
if err := run("admin", "trust-settings-export", "-d"); err != nil {
|
||||
return nil, fmt.Errorf("dump-trust-settings (admin): %v", err)
|
||||
}
|
||||
return set, nil
|
||||
}
|
187
vendor/github.com/google/certificate-transparency-go/x509/root_darwin_arm_gen.go
generated
vendored
Normal file
187
vendor/github.com/google/certificate-transparency-go/x509/root_darwin_arm_gen.go
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// Generates root_darwin_armx.go.
|
||||
//
|
||||
// As of iOS 8, there is no API for querying the system trusted X.509 root
|
||||
// certificates. We could use SecTrustEvaluate to verify that a trust chain
|
||||
// exists for a certificate, but the x509 API requires returning the entire
|
||||
// chain.
|
||||
//
|
||||
// Apple publishes the list of trusted root certificates for iOS on
|
||||
// support.apple.com. So we parse the list and extract the certificates from
|
||||
// an OS X machine and embed them into the x509 package.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/google/certificate-transparency-go/x509"
|
||||
)
|
||||
|
||||
var output = flag.String("output", "root_darwin_armx.go", "file name to write")
|
||||
|
||||
func main() {
|
||||
certs, err := selectCerts()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
fmt.Fprintf(buf, "// Code generated by root_darwin_arm_gen --output %s; DO NOT EDIT.\n", *output)
|
||||
fmt.Fprintf(buf, "%s", header)
|
||||
|
||||
fmt.Fprintf(buf, "const systemRootsPEM = `\n")
|
||||
for _, cert := range certs {
|
||||
b := &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
if err := pem.Encode(buf, b); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(buf, "`")
|
||||
|
||||
source, err := format.Source(buf.Bytes())
|
||||
if err != nil {
|
||||
log.Fatal("source format error:", err)
|
||||
}
|
||||
if err := ioutil.WriteFile(*output, source, 0644); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func selectCerts() ([]*x509.Certificate, error) {
|
||||
ids, err := fetchCertIDs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scerts, err := sysCerts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var certs []*x509.Certificate
|
||||
for _, id := range ids {
|
||||
if c, ok := scerts[id.fingerprint]; ok {
|
||||
certs = append(certs, c)
|
||||
} else {
|
||||
fmt.Printf("WARNING: cannot find certificate: %s (fingerprint: %s)\n", id.name, id.fingerprint)
|
||||
}
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
func sysCerts() (certs map[string]*x509.Certificate, err error) {
|
||||
cmd := exec.Command("/usr/bin/security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain")
|
||||
data, err := cmd.Output()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
certs = make(map[string]*x509.Certificate)
|
||||
for len(data) > 0 {
|
||||
var block *pem.Block
|
||||
block, data = pem.Decode(data)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
fingerprint := sha256.Sum256(cert.Raw)
|
||||
certs[hex.EncodeToString(fingerprint[:])] = cert
|
||||
}
|
||||
return certs, nil
|
||||
}
|
||||
|
||||
type certID struct {
|
||||
name string
|
||||
fingerprint string
|
||||
}
|
||||
|
||||
// fetchCertIDs fetches IDs of iOS X509 certificates from apple.com.
|
||||
func fetchCertIDs() ([]certID, error) {
|
||||
// Download the iOS 11 support page. The index for all iOS versions is here:
|
||||
// https://support.apple.com/en-us/HT204132
|
||||
resp, err := http.Get("https://support.apple.com/en-us/HT208125")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
text := string(body)
|
||||
text = text[strings.Index(text, "<div id=trusted"):]
|
||||
text = text[:strings.Index(text, "</div>")]
|
||||
|
||||
var ids []certID
|
||||
cols := make(map[string]int)
|
||||
for i, rowmatch := range regexp.MustCompile("(?s)<tr>(.*?)</tr>").FindAllStringSubmatch(text, -1) {
|
||||
row := rowmatch[1]
|
||||
if i == 0 {
|
||||
// Parse table header row to extract column names
|
||||
for i, match := range regexp.MustCompile("(?s)<th>(.*?)</th>").FindAllStringSubmatch(row, -1) {
|
||||
cols[match[1]] = i
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
values := regexp.MustCompile("(?s)<td>(.*?)</td>").FindAllStringSubmatch(row, -1)
|
||||
name := values[cols["Certificate name"]][1]
|
||||
fingerprint := values[cols["Fingerprint (SHA-256)"]][1]
|
||||
fingerprint = strings.Replace(fingerprint, "<br>", "", -1)
|
||||
fingerprint = strings.Replace(fingerprint, "\n", "", -1)
|
||||
fingerprint = strings.Replace(fingerprint, " ", "", -1)
|
||||
fingerprint = strings.ToLower(fingerprint)
|
||||
|
||||
ids = append(ids, certID{
|
||||
name: name,
|
||||
fingerprint: fingerprint,
|
||||
})
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
const header = `
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build cgo
|
||||
// +build darwin
|
||||
// +build arm arm64 ios
|
||||
|
||||
package x509
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
p := NewCertPool()
|
||||
p.AppendCertsFromPEM([]byte(systemRootsPEM))
|
||||
return p, nil
|
||||
}
|
||||
`
|
4313
vendor/github.com/google/certificate-transparency-go/x509/root_darwin_armx.go
generated
vendored
Normal file
4313
vendor/github.com/google/certificate-transparency-go/x509/root_darwin_armx.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
80
vendor/github.com/google/certificate-transparency-go/x509/root_darwin_test.go
generated
vendored
Normal file
80
vendor/github.com/google/certificate-transparency-go/x509/root_darwin_test.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSystemRoots(t *testing.T) {
|
||||
switch runtime.GOARCH {
|
||||
case "arm", "arm64":
|
||||
t.Skipf("skipping on %s/%s, no system root", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
t.Skipf("skipping on %s/%s until cgo part of golang.org/issue/16532 has been implemented.", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
|
||||
t0 := time.Now()
|
||||
sysRoots := systemRootsPool() // actual system roots
|
||||
sysRootsDuration := time.Since(t0)
|
||||
|
||||
t1 := time.Now()
|
||||
execRoots, err := execSecurityRoots() // non-cgo roots
|
||||
execSysRootsDuration := time.Since(t1)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read system roots: %v", err)
|
||||
}
|
||||
|
||||
t.Logf(" cgo sys roots: %v", sysRootsDuration)
|
||||
t.Logf("non-cgo sys roots: %v", execSysRootsDuration)
|
||||
|
||||
for _, tt := range []*CertPool{sysRoots, execRoots} {
|
||||
if tt == nil {
|
||||
t.Fatal("no system roots")
|
||||
}
|
||||
// On Mavericks, there are 212 bundled certs, at least
|
||||
// there was at one point in time on one machine.
|
||||
// (Maybe it was a corp laptop with extra certs?)
|
||||
// Other OS X users report
|
||||
// 135, 142, 145... Let's try requiring at least 100,
|
||||
// since this is just a sanity check.
|
||||
t.Logf("got %d roots", len(tt.certs))
|
||||
if want, have := 100, len(tt.certs); have < want {
|
||||
t.Fatalf("want at least %d system roots, have %d", want, have)
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the two cert pools are roughly the same;
|
||||
// |A∩B| > max(|A|, |B|) / 2 should be a reasonably robust check.
|
||||
|
||||
isect := make(map[string]bool, len(sysRoots.certs))
|
||||
for _, c := range sysRoots.certs {
|
||||
isect[string(c.Raw)] = true
|
||||
}
|
||||
|
||||
have := 0
|
||||
for _, c := range execRoots.certs {
|
||||
if isect[string(c.Raw)] {
|
||||
have++
|
||||
}
|
||||
}
|
||||
|
||||
var want int
|
||||
if nsys, nexec := len(sysRoots.certs), len(execRoots.certs); nsys > nexec {
|
||||
want = nsys / 2
|
||||
} else {
|
||||
want = nexec / 2
|
||||
}
|
||||
|
||||
if have < want {
|
||||
t.Errorf("insufficient overlap between cgo and non-cgo roots; want at least %d, have %d", want, have)
|
||||
}
|
||||
}
|
14
vendor/github.com/google/certificate-transparency-go/x509/root_linux.go
generated
vendored
Normal file
14
vendor/github.com/google/certificate-transparency-go/x509/root_linux.go
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
// Possible certificate files; stop after finding one.
|
||||
var certFiles = []string{
|
||||
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
|
||||
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
|
||||
"/etc/ssl/ca-bundle.pem", // OpenSUSE
|
||||
"/etc/pki/tls/cacert.pem", // OpenELEC
|
||||
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
|
||||
}
|
8
vendor/github.com/google/certificate-transparency-go/x509/root_nacl.go
generated
vendored
Normal file
8
vendor/github.com/google/certificate-transparency-go/x509/root_nacl.go
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
// Possible certificate files; stop after finding one.
|
||||
var certFiles = []string{}
|
11
vendor/github.com/google/certificate-transparency-go/x509/root_nocgo_darwin.go
generated
vendored
Normal file
11
vendor/github.com/google/certificate-transparency-go/x509/root_nocgo_darwin.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !cgo
|
||||
|
||||
package x509
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
return execSecurityRoots()
|
||||
}
|
37
vendor/github.com/google/certificate-transparency-go/x509/root_plan9.go
generated
vendored
Normal file
37
vendor/github.com/google/certificate-transparency-go/x509/root_plan9.go
generated
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build plan9
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Possible certificate files; stop after finding one.
|
||||
var certFiles = []string{
|
||||
"/sys/lib/tls/ca.pem",
|
||||
}
|
||||
|
||||
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
roots := NewCertPool()
|
||||
var bestErr error
|
||||
for _, file := range certFiles {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err == nil {
|
||||
roots.AppendCertsFromPEM(data)
|
||||
return roots, nil
|
||||
}
|
||||
if bestErr == nil || (os.IsNotExist(bestErr) && !os.IsNotExist(err)) {
|
||||
bestErr = err
|
||||
}
|
||||
}
|
||||
return nil, bestErr
|
||||
}
|
12
vendor/github.com/google/certificate-transparency-go/x509/root_solaris.go
generated
vendored
Normal file
12
vendor/github.com/google/certificate-transparency-go/x509/root_solaris.go
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
// Possible certificate files; stop after finding one.
|
||||
var certFiles = []string{
|
||||
"/etc/certs/ca-certificates.crt", // Solaris 11.2+
|
||||
"/etc/ssl/certs/ca-certificates.crt", // Joyent SmartOS
|
||||
"/etc/ssl/cacert.pem", // OmniOS
|
||||
}
|
88
vendor/github.com/google/certificate-transparency-go/x509/root_unix.go
generated
vendored
Normal file
88
vendor/github.com/google/certificate-transparency-go/x509/root_unix.go
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright 2011 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly freebsd linux nacl netbsd openbsd solaris
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Possible directories with certificate files; stop after successfully
|
||||
// reading at least one file from a directory.
|
||||
var certDirectories = []string{
|
||||
"/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
|
||||
"/system/etc/security/cacerts", // Android
|
||||
"/usr/local/share/certs", // FreeBSD
|
||||
"/etc/pki/tls/certs", // Fedora/RHEL
|
||||
"/etc/openssl/certs", // NetBSD
|
||||
}
|
||||
|
||||
const (
|
||||
// certFileEnv is the environment variable which identifies where to locate
|
||||
// the SSL certificate file. If set this overrides the system default.
|
||||
certFileEnv = "SSL_CERT_FILE"
|
||||
|
||||
// certDirEnv is the environment variable which identifies which directory
|
||||
// to check for SSL certificate files. If set this overrides the system default.
|
||||
certDirEnv = "SSL_CERT_DIR"
|
||||
)
|
||||
|
||||
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
roots := NewCertPool()
|
||||
|
||||
files := certFiles
|
||||
if f := os.Getenv(certFileEnv); f != "" {
|
||||
files = []string{f}
|
||||
}
|
||||
|
||||
var firstErr error
|
||||
for _, file := range files {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err == nil {
|
||||
roots.AppendCertsFromPEM(data)
|
||||
break
|
||||
}
|
||||
if firstErr == nil && !os.IsNotExist(err) {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
|
||||
dirs := certDirectories
|
||||
if d := os.Getenv(certDirEnv); d != "" {
|
||||
dirs = []string{d}
|
||||
}
|
||||
|
||||
for _, directory := range dirs {
|
||||
fis, err := ioutil.ReadDir(directory)
|
||||
if err != nil {
|
||||
if firstErr == nil && !os.IsNotExist(err) {
|
||||
firstErr = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
rootsAdded := false
|
||||
for _, fi := range fis {
|
||||
data, err := ioutil.ReadFile(directory + "/" + fi.Name())
|
||||
if err == nil && roots.AppendCertsFromPEM(data) {
|
||||
rootsAdded = true
|
||||
}
|
||||
}
|
||||
if rootsAdded {
|
||||
return roots, nil
|
||||
}
|
||||
}
|
||||
|
||||
if len(roots.certs) > 0 {
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
return nil, firstErr
|
||||
}
|
127
vendor/github.com/google/certificate-transparency-go/x509/root_unix_test.go
generated
vendored
Normal file
127
vendor/github.com/google/certificate-transparency-go/x509/root_unix_test.go
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const (
|
||||
testDir = "testdata"
|
||||
testDirCN = "test-dir"
|
||||
testFile = "test-file.crt"
|
||||
testFileCN = "test-file"
|
||||
testMissing = "missing"
|
||||
)
|
||||
|
||||
func TestEnvVars(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
fileEnv string
|
||||
dirEnv string
|
||||
files []string
|
||||
dirs []string
|
||||
cns []string
|
||||
}{
|
||||
{
|
||||
// Environment variables override the default locations preventing fall through.
|
||||
name: "override-defaults",
|
||||
fileEnv: testMissing,
|
||||
dirEnv: testMissing,
|
||||
files: []string{testFile},
|
||||
dirs: []string{testDir},
|
||||
cns: nil,
|
||||
},
|
||||
{
|
||||
// File environment overrides default file locations.
|
||||
name: "file",
|
||||
fileEnv: testFile,
|
||||
dirEnv: "",
|
||||
files: nil,
|
||||
dirs: nil,
|
||||
cns: []string{testFileCN},
|
||||
},
|
||||
{
|
||||
// Directory environment overrides default directory locations.
|
||||
name: "dir",
|
||||
fileEnv: "",
|
||||
dirEnv: testDir,
|
||||
files: nil,
|
||||
dirs: nil,
|
||||
cns: []string{testDirCN},
|
||||
},
|
||||
{
|
||||
// File & directory environment overrides both default locations.
|
||||
name: "file+dir",
|
||||
fileEnv: testFile,
|
||||
dirEnv: testDir,
|
||||
files: nil,
|
||||
dirs: nil,
|
||||
cns: []string{testFileCN, testDirCN},
|
||||
},
|
||||
{
|
||||
// Environment variable empty / unset uses default locations.
|
||||
name: "empty-fall-through",
|
||||
fileEnv: "",
|
||||
dirEnv: "",
|
||||
files: []string{testFile},
|
||||
dirs: []string{testDir},
|
||||
cns: []string{testFileCN, testDirCN},
|
||||
},
|
||||
}
|
||||
|
||||
// Save old settings so we can restore before the test ends.
|
||||
origCertFiles, origCertDirectories := certFiles, certDirectories
|
||||
origFile, origDir := os.Getenv(certFileEnv), os.Getenv(certDirEnv)
|
||||
defer func() {
|
||||
certFiles = origCertFiles
|
||||
certDirectories = origCertDirectories
|
||||
os.Setenv(certFileEnv, origFile)
|
||||
os.Setenv(certDirEnv, origDir)
|
||||
}()
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if err := os.Setenv(certFileEnv, tc.fileEnv); err != nil {
|
||||
t.Fatalf("setenv %q failed: %v", certFileEnv, err)
|
||||
}
|
||||
if err := os.Setenv(certDirEnv, tc.dirEnv); err != nil {
|
||||
t.Fatalf("setenv %q failed: %v", certDirEnv, err)
|
||||
}
|
||||
|
||||
certFiles, certDirectories = tc.files, tc.dirs
|
||||
|
||||
r, err := loadSystemRoots()
|
||||
if err != nil {
|
||||
t.Fatal("unexpected failure:", err)
|
||||
}
|
||||
|
||||
if r == nil {
|
||||
if tc.cns == nil {
|
||||
// Expected nil
|
||||
return
|
||||
}
|
||||
t.Fatal("nil roots")
|
||||
}
|
||||
|
||||
// Verify that the returned certs match, otherwise report where the mismatch is.
|
||||
for i, cn := range tc.cns {
|
||||
if i >= len(r.certs) {
|
||||
t.Errorf("missing cert %v @ %v", cn, i)
|
||||
} else if r.certs[i].Subject.CommonName != cn {
|
||||
fmt.Printf("%#v\n", r.certs[0].Subject)
|
||||
t.Errorf("unexpected cert common name %q, want %q", r.certs[i].Subject.CommonName, cn)
|
||||
}
|
||||
}
|
||||
if len(r.certs) > len(tc.cns) {
|
||||
t.Errorf("got %v certs, which is more than %v wanted", len(r.certs), len(tc.cns))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
266
vendor/github.com/google/certificate-transparency-go/x509/root_windows.go
generated
vendored
Normal file
266
vendor/github.com/google/certificate-transparency-go/x509/root_windows.go
generated
vendored
Normal file
@ -0,0 +1,266 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Creates a new *syscall.CertContext representing the leaf certificate in an in-memory
|
||||
// certificate store containing itself and all of the intermediate certificates specified
|
||||
// in the opts.Intermediates CertPool.
|
||||
//
|
||||
// A pointer to the in-memory store is available in the returned CertContext's Store field.
|
||||
// The store is automatically freed when the CertContext is freed using
|
||||
// syscall.CertFreeCertificateContext.
|
||||
func createStoreContext(leaf *Certificate, opts *VerifyOptions) (*syscall.CertContext, error) {
|
||||
var storeCtx *syscall.CertContext
|
||||
|
||||
leafCtx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &leaf.Raw[0], uint32(len(leaf.Raw)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CertFreeCertificateContext(leafCtx)
|
||||
|
||||
handle, err := syscall.CertOpenStore(syscall.CERT_STORE_PROV_MEMORY, 0, 0, syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CertCloseStore(handle, 0)
|
||||
|
||||
err = syscall.CertAddCertificateContextToStore(handle, leafCtx, syscall.CERT_STORE_ADD_ALWAYS, &storeCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.Intermediates != nil {
|
||||
for _, intermediate := range opts.Intermediates.certs {
|
||||
ctx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &intermediate.Raw[0], uint32(len(intermediate.Raw)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = syscall.CertAddCertificateContextToStore(handle, ctx, syscall.CERT_STORE_ADD_ALWAYS, nil)
|
||||
syscall.CertFreeCertificateContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return storeCtx, nil
|
||||
}
|
||||
|
||||
// extractSimpleChain extracts the final certificate chain from a CertSimpleChain.
|
||||
func extractSimpleChain(simpleChain **syscall.CertSimpleChain, count int) (chain []*Certificate, err error) {
|
||||
if simpleChain == nil || count == 0 {
|
||||
return nil, errors.New("x509: invalid simple chain")
|
||||
}
|
||||
|
||||
simpleChains := (*[1 << 20]*syscall.CertSimpleChain)(unsafe.Pointer(simpleChain))[:]
|
||||
lastChain := simpleChains[count-1]
|
||||
elements := (*[1 << 20]*syscall.CertChainElement)(unsafe.Pointer(lastChain.Elements))[:]
|
||||
for i := 0; i < int(lastChain.NumElements); i++ {
|
||||
// Copy the buf, since ParseCertificate does not create its own copy.
|
||||
cert := elements[i].CertContext
|
||||
encodedCert := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
|
||||
buf := make([]byte, cert.Length)
|
||||
copy(buf, encodedCert[:])
|
||||
parsedCert, err := ParseCertificate(buf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
chain = append(chain, parsedCert)
|
||||
}
|
||||
|
||||
return chain, nil
|
||||
}
|
||||
|
||||
// checkChainTrustStatus checks the trust status of the certificate chain, translating
|
||||
// any errors it finds into Go errors in the process.
|
||||
func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) error {
|
||||
if chainCtx.TrustStatus.ErrorStatus != syscall.CERT_TRUST_NO_ERROR {
|
||||
status := chainCtx.TrustStatus.ErrorStatus
|
||||
switch status {
|
||||
case syscall.CERT_TRUST_IS_NOT_TIME_VALID:
|
||||
return CertificateInvalidError{c, Expired, ""}
|
||||
default:
|
||||
return UnknownAuthorityError{c, nil, nil}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for
|
||||
// use as a certificate chain for a SSL/TLS server.
|
||||
func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error {
|
||||
servernamep, err := syscall.UTF16PtrFromString(opts.DNSName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sslPara := &syscall.SSLExtraCertChainPolicyPara{
|
||||
AuthType: syscall.AUTHTYPE_SERVER,
|
||||
ServerName: servernamep,
|
||||
}
|
||||
sslPara.Size = uint32(unsafe.Sizeof(*sslPara))
|
||||
|
||||
para := &syscall.CertChainPolicyPara{
|
||||
ExtraPolicyPara: uintptr(unsafe.Pointer(sslPara)),
|
||||
}
|
||||
para.Size = uint32(unsafe.Sizeof(*para))
|
||||
|
||||
status := syscall.CertChainPolicyStatus{}
|
||||
err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(mkrautz): use the lChainIndex and lElementIndex fields
|
||||
// of the CertChainPolicyStatus to provide proper context, instead
|
||||
// using c.
|
||||
if status.Error != 0 {
|
||||
switch status.Error {
|
||||
case syscall.CERT_E_EXPIRED:
|
||||
return CertificateInvalidError{c, Expired, ""}
|
||||
case syscall.CERT_E_CN_NO_MATCH:
|
||||
return HostnameError{c, opts.DNSName}
|
||||
case syscall.CERT_E_UNTRUSTEDROOT:
|
||||
return UnknownAuthorityError{c, nil, nil}
|
||||
default:
|
||||
return UnknownAuthorityError{c, nil, nil}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// systemVerify is like Verify, except that it uses CryptoAPI calls
|
||||
// to build certificate chains and verify them.
|
||||
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
hasDNSName := opts != nil && len(opts.DNSName) > 0
|
||||
|
||||
storeCtx, err := createStoreContext(c, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CertFreeCertificateContext(storeCtx)
|
||||
|
||||
para := new(syscall.CertChainPara)
|
||||
para.Size = uint32(unsafe.Sizeof(*para))
|
||||
|
||||
// If there's a DNSName set in opts, assume we're verifying
|
||||
// a certificate from a TLS server.
|
||||
if hasDNSName {
|
||||
oids := []*byte{
|
||||
&syscall.OID_PKIX_KP_SERVER_AUTH[0],
|
||||
// Both IE and Chrome allow certificates with
|
||||
// Server Gated Crypto as well. Some certificates
|
||||
// in the wild require them.
|
||||
&syscall.OID_SERVER_GATED_CRYPTO[0],
|
||||
&syscall.OID_SGC_NETSCAPE[0],
|
||||
}
|
||||
para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_OR
|
||||
para.RequestedUsage.Usage.Length = uint32(len(oids))
|
||||
para.RequestedUsage.Usage.UsageIdentifiers = &oids[0]
|
||||
} else {
|
||||
para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_AND
|
||||
para.RequestedUsage.Usage.Length = 0
|
||||
para.RequestedUsage.Usage.UsageIdentifiers = nil
|
||||
}
|
||||
|
||||
var verifyTime *syscall.Filetime
|
||||
if opts != nil && !opts.CurrentTime.IsZero() {
|
||||
ft := syscall.NsecToFiletime(opts.CurrentTime.UnixNano())
|
||||
verifyTime = &ft
|
||||
}
|
||||
|
||||
// CertGetCertificateChain will traverse Windows's root stores
|
||||
// in an attempt to build a verified certificate chain. Once
|
||||
// it has found a verified chain, it stops. MSDN docs on
|
||||
// CERT_CHAIN_CONTEXT:
|
||||
//
|
||||
// When a CERT_CHAIN_CONTEXT is built, the first simple chain
|
||||
// begins with an end certificate and ends with a self-signed
|
||||
// certificate. If that self-signed certificate is not a root
|
||||
// or otherwise trusted certificate, an attempt is made to
|
||||
// build a new chain. CTLs are used to create the new chain
|
||||
// beginning with the self-signed certificate from the original
|
||||
// chain as the end certificate of the new chain. This process
|
||||
// continues building additional simple chains until the first
|
||||
// self-signed certificate is a trusted certificate or until
|
||||
// an additional simple chain cannot be built.
|
||||
//
|
||||
// The result is that we'll only get a single trusted chain to
|
||||
// return to our caller.
|
||||
var chainCtx *syscall.CertChainContext
|
||||
err = syscall.CertGetCertificateChain(syscall.Handle(0), storeCtx, verifyTime, storeCtx.Store, para, 0, 0, &chainCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CertFreeCertificateChain(chainCtx)
|
||||
|
||||
err = checkChainTrustStatus(c, chainCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if hasDNSName {
|
||||
err = checkChainSSLServerPolicy(c, chainCtx, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
chain, err := extractSimpleChain(chainCtx.Chains, int(chainCtx.ChainCount))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
chains = append(chains, chain)
|
||||
|
||||
return chains, nil
|
||||
}
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
// TODO: restore this functionality on Windows. We tried to do
|
||||
// it in Go 1.8 but had to revert it. See Issue 18609.
|
||||
// Returning (nil, nil) was the old behavior, prior to CL 30578.
|
||||
return nil, nil
|
||||
|
||||
const CRYPT_E_NOT_FOUND = 0x80092004
|
||||
|
||||
store, err := syscall.CertOpenSystemStore(0, syscall.StringToUTF16Ptr("ROOT"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer syscall.CertCloseStore(store, 0)
|
||||
|
||||
roots := NewCertPool()
|
||||
var cert *syscall.CertContext
|
||||
for {
|
||||
cert, err = syscall.CertEnumCertificatesInStore(store, cert)
|
||||
if err != nil {
|
||||
if errno, ok := err.(syscall.Errno); ok {
|
||||
if errno == CRYPT_E_NOT_FOUND {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if cert == nil {
|
||||
break
|
||||
}
|
||||
// Copy the buf, since ParseCertificate does not create its own copy.
|
||||
buf := (*[1 << 20]byte)(unsafe.Pointer(cert.EncodedCert))[:]
|
||||
buf2 := make([]byte, cert.Length)
|
||||
copy(buf2, buf)
|
||||
if c, err := ParseCertificate(buf2); err == nil {
|
||||
roots.AddCert(c)
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
112
vendor/github.com/google/certificate-transparency-go/x509/sec1.go
generated
vendored
Normal file
112
vendor/github.com/google/certificate-transparency-go/x509/sec1.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/google/certificate-transparency-go/asn1"
|
||||
)
|
||||
|
||||
const ecPrivKeyVersion = 1
|
||||
|
||||
// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure.
|
||||
// References:
|
||||
// RFC 5915
|
||||
// SEC1 - http://www.secg.org/sec1-v2.pdf
|
||||
// Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in
|
||||
// most cases it is not.
|
||||
type ecPrivateKey struct {
|
||||
Version int
|
||||
PrivateKey []byte
|
||||
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
|
||||
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
|
||||
}
|
||||
|
||||
// ParseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
|
||||
func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error) {
|
||||
return parseECPrivateKey(nil, der)
|
||||
}
|
||||
|
||||
// MarshalECPrivateKey marshals an EC private key into ASN.1, DER format.
|
||||
func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
|
||||
oid, ok := OIDFromNamedCurve(key.Curve)
|
||||
if !ok {
|
||||
return nil, errors.New("x509: unknown elliptic curve")
|
||||
}
|
||||
|
||||
return marshalECPrivateKeyWithOID(key, oid)
|
||||
}
|
||||
|
||||
// marshalECPrivateKey marshals an EC private key into ASN.1, DER format and
|
||||
// sets the curve ID to the given OID, or omits it if OID is nil.
|
||||
func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) {
|
||||
privateKeyBytes := key.D.Bytes()
|
||||
paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
|
||||
copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
|
||||
|
||||
return asn1.Marshal(ecPrivateKey{
|
||||
Version: 1,
|
||||
PrivateKey: paddedPrivateKey,
|
||||
NamedCurveOID: oid,
|
||||
PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
|
||||
})
|
||||
}
|
||||
|
||||
// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure.
|
||||
// The OID for the named curve may be provided from another source (such as
|
||||
// the PKCS8 container) - if it is provided then use this instead of the OID
|
||||
// that may exist in the EC private key structure.
|
||||
func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
|
||||
var privKey ecPrivateKey
|
||||
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
|
||||
return nil, errors.New("x509: failed to parse EC private key: " + err.Error())
|
||||
}
|
||||
if privKey.Version != ecPrivKeyVersion {
|
||||
return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version)
|
||||
}
|
||||
|
||||
var curve elliptic.Curve
|
||||
if namedCurveOID != nil {
|
||||
curve = namedCurveFromOID(*namedCurveOID)
|
||||
} else {
|
||||
curve = namedCurveFromOID(privKey.NamedCurveOID)
|
||||
}
|
||||
if curve == nil {
|
||||
return nil, errors.New("x509: unknown elliptic curve")
|
||||
}
|
||||
|
||||
k := new(big.Int).SetBytes(privKey.PrivateKey)
|
||||
curveOrder := curve.Params().N
|
||||
if k.Cmp(curveOrder) >= 0 {
|
||||
return nil, errors.New("x509: invalid elliptic curve private key value")
|
||||
}
|
||||
priv := new(ecdsa.PrivateKey)
|
||||
priv.Curve = curve
|
||||
priv.D = k
|
||||
|
||||
privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
|
||||
|
||||
// Some private keys have leading zero padding. This is invalid
|
||||
// according to [SEC1], but this code will ignore it.
|
||||
for len(privKey.PrivateKey) > len(privateKey) {
|
||||
if privKey.PrivateKey[0] != 0 {
|
||||
return nil, errors.New("x509: invalid private key length")
|
||||
}
|
||||
privKey.PrivateKey = privKey.PrivateKey[1:]
|
||||
}
|
||||
|
||||
// Some private keys remove all leading zeros, this is also invalid
|
||||
// according to [SEC1] but since OpenSSL used to do this, we ignore
|
||||
// this too.
|
||||
copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
|
||||
priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
|
||||
|
||||
return priv, nil
|
||||
}
|
44
vendor/github.com/google/certificate-transparency-go/x509/sec1_test.go
generated
vendored
Normal file
44
vendor/github.com/google/certificate-transparency-go/x509/sec1_test.go
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var ecKeyTests = []struct {
|
||||
derHex string
|
||||
shouldReserialize bool
|
||||
}{
|
||||
// Generated using:
|
||||
// openssl ecparam -genkey -name secp384r1 -outform PEM
|
||||
{"3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50", true},
|
||||
// This key was generated by GnuTLS and has illegal zero-padding of the
|
||||
// private key. See https://golang.org/issues/13699.
|
||||
{"3078020101042100f9f43a04b9bdc3ab01f53be6df80e7a7bc3eaf7b87fc24e630a4a0aa97633645a00a06082a8648ce3d030107a1440342000441a51bc318461b4c39a45048a16d4fc2a935b1ea7fe86e8c1fa219d6f2438f7c7fd62957d3442efb94b6a23eb0ea66dda663dc42f379cda6630b21b7888a5d3d", false},
|
||||
// This was generated using an old version of OpenSSL and is missing a
|
||||
// leading zero byte in the private key that should be present.
|
||||
{"3081db0201010441607b4f985774ac21e633999794542e09312073480baa69550914d6d43d8414441e61b36650567901da714f94dffb3ce0e2575c31928a0997d51df5c440e983ca17a00706052b81040023a181890381860004001661557afedd7ac8d6b70e038e576558c626eb62edda36d29c3a1310277c11f67a8c6f949e5430a37dcfb95d902c1b5b5379c389873b9dd17be3bdb088a4774a7401072f830fb9a08d93bfa50a03dd3292ea07928724ddb915d831917a338f6b0aecfbc3cf5352c4a1295d356890c41c34116d29eeb93779aab9d9d78e2613437740f6", false},
|
||||
}
|
||||
|
||||
func TestParseECPrivateKey(t *testing.T) {
|
||||
for i, test := range ecKeyTests {
|
||||
derBytes, _ := hex.DecodeString(test.derHex)
|
||||
key, err := ParseECPrivateKey(derBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("#%d: failed to decode EC private key: %s", i, err)
|
||||
}
|
||||
serialized, err := MarshalECPrivateKey(key)
|
||||
if err != nil {
|
||||
t.Fatalf("#%d: failed to encode EC private key: %s", i, err)
|
||||
}
|
||||
matches := bytes.Equal(serialized, derBytes)
|
||||
if matches != test.shouldReserialize {
|
||||
t.Fatalf("#%d: when serializing key: matches=%t, should match=%t: original %x, reserialized %x", i, matches, test.shouldReserialize, serialized, derBytes)
|
||||
}
|
||||
}
|
||||
}
|
19
vendor/github.com/google/certificate-transparency-go/x509/sha2_windows_test.go
generated
vendored
Normal file
19
vendor/github.com/google/certificate-transparency-go/x509/sha2_windows_test.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package x509
|
||||
|
||||
import "syscall"
|
||||
|
||||
func init() {
|
||||
v, err := syscall.GetVersion()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if major := byte(v); major < 6 {
|
||||
// Windows XP SP2 and Windows 2003 do not support SHA2.
|
||||
// http://blogs.technet.com/b/pki/archive/2010/09/30/sha2-and-windows.aspx
|
||||
supportSHA2 = false
|
||||
}
|
||||
}
|
31
vendor/github.com/google/certificate-transparency-go/x509/test-dir.crt
generated
vendored
Normal file
31
vendor/github.com/google/certificate-transparency-go/x509/test-dir.crt
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFazCCA1OgAwIBAgIJAL8a/lsnspOqMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV
|
||||
BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz
|
||||
dHMxETAPBgNVBAMMCHRlc3QtZGlyMB4XDTE3MDIwMTIzNTAyN1oXDTI3MDEzMDIz
|
||||
NTAyN1owTDELMAkGA1UEBhMCVUsxEzARBgNVBAgMClRlc3QtU3RhdGUxFTATBgNV
|
||||
BAoMDEdvbGFuZyBUZXN0czERMA8GA1UEAwwIdGVzdC1kaXIwggIiMA0GCSqGSIb3
|
||||
DQEBAQUAA4ICDwAwggIKAoICAQDzBoi43Yn30KN13PKFHu8LA4UmgCRToTukLItM
|
||||
WK2Je45grs/axg9n3YJOXC6hmsyrkOnyBcx1xVNgSrOAll7fSjtChRIX72Xrloxu
|
||||
XewtWVIrijqz6oylbvEmbRT3O8uynu5rF82Pmdiy8oiSfdywjKuPnE0hjV1ZSCql
|
||||
MYcXqA+f0JFD8kMv4pbtxjGH8f2DkYQz+hHXLrJH4/MEYdVMQXoz/GDzLyOkrXBN
|
||||
hpMaBBqg1p0P+tRdfLXuliNzA9vbZylzpF1YZ0gvsr0S5Y6LVtv7QIRygRuLY4kF
|
||||
k+UYuFq8NrV8TykS7FVnO3tf4XcYZ7r2KV5FjYSrJtNNo85BV5c3xMD3fJ2XcOWk
|
||||
+oD1ATdgAM3aKmSOxNtNItKKxBe1mkqDH41NbWx7xMad78gDznyeT0tjEOltN2bM
|
||||
uXU1R/jgR/vq5Ec0AhXJyL/ziIcmuV2fSl/ZxT4ARD+16tgPiIx+welTf0v27/JY
|
||||
adlfkkL5XsPRrbSguISrj7JeaO/gjG3KnDVHcZvYBpDfHqRhCgrosfe26TZcTXx2
|
||||
cRxOfvBjMz1zJAg+esuUzSkerreyRhzD7RpeZTwi6sxvx82MhYMbA3w1LtgdABio
|
||||
9JRqZy3xqsIbNv7N46WO/qXL1UMRKb1UyHeW8g8btboz+B4zv1U0Nj+9qxPBbQui
|
||||
dgL9LQIDAQABo1AwTjAdBgNVHQ4EFgQUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwHwYD
|
||||
VR0jBBgwFoAUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwDAYDVR0TBAUwAwEB/zANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEAvEVnUYsIOt87rggmLPqEueynkuQ+562M8EDHSQl82zbe
|
||||
xDCxeg3DvPgKb+RvaUdt1362z/szK10SoeMgx6+EQLoV9LiVqXwNqeYfixrhrdw3
|
||||
ppAhYYhymdkbUQCEMHypmXP1vPhAz4o8Bs+eES1M+zO6ErBiD7SqkmBElT+GixJC
|
||||
6epC9ZQFs+dw3lPlbiZSsGE85sqc3VAs0/JgpL/pb1/Eg4s0FUhZD2C2uWdSyZGc
|
||||
g0/v3aXJCp4j/9VoNhI1WXz3M45nysZIL5OQgXymLqJElQa1pZ3Wa4i/nidvT4AT
|
||||
Xlxc/qijM8set/nOqp7hVd5J0uG6qdwLRILUddZ6OpXd7ZNi1EXg+Bpc7ehzGsDt
|
||||
3UFGzYXDjxYnK2frQfjLS8stOQIqSrGthW6x0fdkVx0y8BByvd5J6+JmZl4UZfzA
|
||||
m99VxXSt4B9x6BvnY7ktzcFDOjtuLc4B/7yg9fv1eQuStA4cHGGAttsCg1X/Kx8W
|
||||
PvkkeH0UWDZ9vhH9K36703z89da6MWF+bz92B0+4HoOmlVaXRkvblsNaynJnL0LC
|
||||
Ayry7QBxuh5cMnDdRwJB3AVJIiJ1GVpb7aGvBOnx+s2lwRv9HWtghb+cbwwktx1M
|
||||
JHyBf3GZNSWTpKY7cD8V+NnBv3UuioOVVo+XAU4LF/bYUjdRpxWADJizNtZrtFo=
|
||||
-----END CERTIFICATE-----
|
32
vendor/github.com/google/certificate-transparency-go/x509/test-file.crt
generated
vendored
Normal file
32
vendor/github.com/google/certificate-transparency-go/x509/test-file.crt
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFbTCCA1WgAwIBAgIJAN338vEmMtLsMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNV
|
||||
BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz
|
||||
dHMxEjAQBgNVBAMMCXRlc3QtZmlsZTAeFw0xNzAyMDEyMzUyMDhaFw0yNzAxMzAy
|
||||
MzUyMDhaME0xCzAJBgNVBAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYD
|
||||
VQQKDAxHb2xhbmcgVGVzdHMxEjAQBgNVBAMMCXRlc3QtZmlsZTCCAiIwDQYJKoZI
|
||||
hvcNAQEBBQADggIPADCCAgoCggIBAPMGiLjdiffQo3Xc8oUe7wsDhSaAJFOhO6Qs
|
||||
i0xYrYl7jmCuz9rGD2fdgk5cLqGazKuQ6fIFzHXFU2BKs4CWXt9KO0KFEhfvZeuW
|
||||
jG5d7C1ZUiuKOrPqjKVu8SZtFPc7y7Ke7msXzY+Z2LLyiJJ93LCMq4+cTSGNXVlI
|
||||
KqUxhxeoD5/QkUPyQy/ilu3GMYfx/YORhDP6Edcuskfj8wRh1UxBejP8YPMvI6St
|
||||
cE2GkxoEGqDWnQ/61F18te6WI3MD29tnKXOkXVhnSC+yvRLljotW2/tAhHKBG4tj
|
||||
iQWT5Ri4Wrw2tXxPKRLsVWc7e1/hdxhnuvYpXkWNhKsm002jzkFXlzfEwPd8nZdw
|
||||
5aT6gPUBN2AAzdoqZI7E200i0orEF7WaSoMfjU1tbHvExp3vyAPOfJ5PS2MQ6W03
|
||||
Zsy5dTVH+OBH++rkRzQCFcnIv/OIhya5XZ9KX9nFPgBEP7Xq2A+IjH7B6VN/S/bv
|
||||
8lhp2V+SQvlew9GttKC4hKuPsl5o7+CMbcqcNUdxm9gGkN8epGEKCuix97bpNlxN
|
||||
fHZxHE5+8GMzPXMkCD56y5TNKR6ut7JGHMPtGl5lPCLqzG/HzYyFgxsDfDUu2B0A
|
||||
GKj0lGpnLfGqwhs2/s3jpY7+pcvVQxEpvVTId5byDxu1ujP4HjO/VTQ2P72rE8Ft
|
||||
C6J2Av0tAgMBAAGjUDBOMB0GA1UdDgQWBBTLT/RbyfBB/Pa07oBnaM+QSJPO9TAf
|
||||
BgNVHSMEGDAWgBTLT/RbyfBB/Pa07oBnaM+QSJPO9TAMBgNVHRMEBTADAQH/MA0G
|
||||
CSqGSIb3DQEBCwUAA4ICAQB3sCntCcQwhMgRPPyvOCMyTcQ/Iv+cpfxz2Ck14nlx
|
||||
AkEAH2CH0ov5GWTt07/ur3aa5x+SAKi0J3wTD1cdiw4U/6Uin6jWGKKxvoo4IaeK
|
||||
SbM8w/6eKx6UbmHx7PA/eRABY9tTlpdPCVgw7/o3WDr03QM+IAtatzvaCPPczake
|
||||
pbdLwmBZB/v8V+6jUajy6jOgdSH0PyffGnt7MWgDETmNC6p/Xigp5eh+C8Fb4NGT
|
||||
xgHES5PBC+sruWp4u22bJGDKTvYNdZHsnw/CaKQWNsQqwisxa3/8N5v+PCff/pxl
|
||||
r05pE3PdHn9JrCl4iWdVlgtiI9BoPtQyDfa/OEFaScE8KYR8LxaAgdgp3zYncWls
|
||||
BpwQ6Y/A2wIkhlD9eEp5Ib2hz7isXOs9UwjdriKqrBXqcIAE5M+YIk3+KAQKxAtd
|
||||
4YsK3CSJ010uphr12YKqlScj4vuKFjuOtd5RyyMIxUG3lrrhAu2AzCeKCLdVgA8+
|
||||
75FrYMApUdvcjp4uzbBoED4XRQlx9kdFHVbYgmE/+yddBYJM8u4YlgAL0hW2/D8p
|
||||
z9JWIfxVmjJnBnXaKGBuiUyZ864A3PJndP6EMMo7TzS2CDnfCYuJjvI0KvDjFNmc
|
||||
rQA04+qfMSEz3nmKhbbZu4eYLzlADhfH8tT4GMtXf71WLA5AUHGf2Y4+HIHTsmHG
|
||||
vQ==
|
||||
-----END CERTIFICATE-----
|
31
vendor/github.com/google/certificate-transparency-go/x509/testdata/test-dir.crt
generated
vendored
Normal file
31
vendor/github.com/google/certificate-transparency-go/x509/testdata/test-dir.crt
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFazCCA1OgAwIBAgIJAL8a/lsnspOqMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNV
|
||||
BAYTAlVLMRMwEQYDVQQIDApUZXN0LVN0YXRlMRUwEwYDVQQKDAxHb2xhbmcgVGVz
|
||||
dHMxETAPBgNVBAMMCHRlc3QtZGlyMB4XDTE3MDIwMTIzNTAyN1oXDTI3MDEzMDIz
|
||||
NTAyN1owTDELMAkGA1UEBhMCVUsxEzARBgNVBAgMClRlc3QtU3RhdGUxFTATBgNV
|
||||
BAoMDEdvbGFuZyBUZXN0czERMA8GA1UEAwwIdGVzdC1kaXIwggIiMA0GCSqGSIb3
|
||||
DQEBAQUAA4ICDwAwggIKAoICAQDzBoi43Yn30KN13PKFHu8LA4UmgCRToTukLItM
|
||||
WK2Je45grs/axg9n3YJOXC6hmsyrkOnyBcx1xVNgSrOAll7fSjtChRIX72Xrloxu
|
||||
XewtWVIrijqz6oylbvEmbRT3O8uynu5rF82Pmdiy8oiSfdywjKuPnE0hjV1ZSCql
|
||||
MYcXqA+f0JFD8kMv4pbtxjGH8f2DkYQz+hHXLrJH4/MEYdVMQXoz/GDzLyOkrXBN
|
||||
hpMaBBqg1p0P+tRdfLXuliNzA9vbZylzpF1YZ0gvsr0S5Y6LVtv7QIRygRuLY4kF
|
||||
k+UYuFq8NrV8TykS7FVnO3tf4XcYZ7r2KV5FjYSrJtNNo85BV5c3xMD3fJ2XcOWk
|
||||
+oD1ATdgAM3aKmSOxNtNItKKxBe1mkqDH41NbWx7xMad78gDznyeT0tjEOltN2bM
|
||||
uXU1R/jgR/vq5Ec0AhXJyL/ziIcmuV2fSl/ZxT4ARD+16tgPiIx+welTf0v27/JY
|
||||
adlfkkL5XsPRrbSguISrj7JeaO/gjG3KnDVHcZvYBpDfHqRhCgrosfe26TZcTXx2
|
||||
cRxOfvBjMz1zJAg+esuUzSkerreyRhzD7RpeZTwi6sxvx82MhYMbA3w1LtgdABio
|
||||
9JRqZy3xqsIbNv7N46WO/qXL1UMRKb1UyHeW8g8btboz+B4zv1U0Nj+9qxPBbQui
|
||||
dgL9LQIDAQABo1AwTjAdBgNVHQ4EFgQUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwHwYD
|
||||
VR0jBBgwFoAUy0/0W8nwQfz2tO6AZ2jPkEiTzvUwDAYDVR0TBAUwAwEB/zANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEAvEVnUYsIOt87rggmLPqEueynkuQ+562M8EDHSQl82zbe
|
||||
xDCxeg3DvPgKb+RvaUdt1362z/szK10SoeMgx6+EQLoV9LiVqXwNqeYfixrhrdw3
|
||||
ppAhYYhymdkbUQCEMHypmXP1vPhAz4o8Bs+eES1M+zO6ErBiD7SqkmBElT+GixJC
|
||||
6epC9ZQFs+dw3lPlbiZSsGE85sqc3VAs0/JgpL/pb1/Eg4s0FUhZD2C2uWdSyZGc
|
||||
g0/v3aXJCp4j/9VoNhI1WXz3M45nysZIL5OQgXymLqJElQa1pZ3Wa4i/nidvT4AT
|
||||
Xlxc/qijM8set/nOqp7hVd5J0uG6qdwLRILUddZ6OpXd7ZNi1EXg+Bpc7ehzGsDt
|
||||
3UFGzYXDjxYnK2frQfjLS8stOQIqSrGthW6x0fdkVx0y8BByvd5J6+JmZl4UZfzA
|
||||
m99VxXSt4B9x6BvnY7ktzcFDOjtuLc4B/7yg9fv1eQuStA4cHGGAttsCg1X/Kx8W
|
||||
PvkkeH0UWDZ9vhH9K36703z89da6MWF+bz92B0+4HoOmlVaXRkvblsNaynJnL0LC
|
||||
Ayry7QBxuh5cMnDdRwJB3AVJIiJ1GVpb7aGvBOnx+s2lwRv9HWtghb+cbwwktx1M
|
||||
JHyBf3GZNSWTpKY7cD8V+NnBv3UuioOVVo+XAU4LF/bYUjdRpxWADJizNtZrtFo=
|
||||
-----END CERTIFICATE-----
|
1035
vendor/github.com/google/certificate-transparency-go/x509/verify.go
generated
vendored
Normal file
1035
vendor/github.com/google/certificate-transparency-go/x509/verify.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1744
vendor/github.com/google/certificate-transparency-go/x509/verify_test.go
generated
vendored
Normal file
1744
vendor/github.com/google/certificate-transparency-go/x509/verify_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2841
vendor/github.com/google/certificate-transparency-go/x509/x509.go
generated
vendored
Normal file
2841
vendor/github.com/google/certificate-transparency-go/x509/x509.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2370
vendor/github.com/google/certificate-transparency-go/x509/x509_test.go
generated
vendored
Normal file
2370
vendor/github.com/google/certificate-transparency-go/x509/x509_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
55
vendor/github.com/google/certificate-transparency-go/x509/x509_test_import.go
generated
vendored
Normal file
55
vendor/github.com/google/certificate-transparency-go/x509/x509_test_import.go
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build ignore
|
||||
|
||||
// This file is run by the x509 tests to ensure that a program with minimal
|
||||
// imports can sign certificates without errors resulting from missing hash
|
||||
// functions.
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
// START CT CHANGES
|
||||
"github.com/google/certificate-transparency-go/x509"
|
||||
"github.com/google/certificate-transparency-go/x509/pkix"
|
||||
// END CT CHANGES
|
||||
"encoding/pem"
|
||||
"math/big"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
block, _ := pem.Decode([]byte(pemPrivateKey))
|
||||
rsaPriv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
panic("Failed to parse private key: " + err.Error())
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: "test",
|
||||
Organization: []string{"Σ Acme Co"},
|
||||
},
|
||||
NotBefore: time.Unix(1000, 0),
|
||||
NotAfter: time.Unix(100000, 0),
|
||||
KeyUsage: x509.KeyUsageCertSign,
|
||||
}
|
||||
|
||||
if _, err = x509.CreateCertificate(rand.Reader, &template, &template, &rsaPriv.PublicKey, rsaPriv); err != nil {
|
||||
panic("failed to create certificate with basic imports: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
var pemPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0
|
||||
fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu
|
||||
/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu
|
||||
RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/
|
||||
EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A
|
||||
IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS
|
||||
tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`
|
Reference in New Issue
Block a user