Switch from globalsign/certlint to zmap/zlint (#3745)

Switch linting library to zmap/zlint.

```
github.com/zmap/zlint$ go test ./...
ok  	github.com/zmap/zlint	0.190s
?   	github.com/zmap/zlint/cmd/zlint	[no test files]
ok  	github.com/zmap/zlint/lints	0.216s
ok  	github.com/zmap/zlint/util	(cached)
```
This commit is contained in:
Roland Bracewell Shoemaker 2018-06-04 17:47:06 -07:00 committed by GitHub
parent b29fe6559d
commit 72949d5915
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
375 changed files with 37191 additions and 13896 deletions

233
Godeps/Godeps.json generated
View File

@ -6,250 +6,95 @@
"./..."
],
"Deps": [
{
"ImportPath": "github.com/asaskevich/govalidator",
"Comment": "v6-25-g73945b6",
"Rev": "73945b6115bfbbcc57d89b7316e28109364124e1"
},
{
"ImportPath": "github.com/beorn7/perks/quantile",
"Rev": "3ac7bf7a47d159a033b107610db8a1b6575507a4"
},
{
"ImportPath": "github.com/cloudflare/cfssl/auth",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb/dbconf",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/certdb/sql",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/config",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/crypto/pkcs7",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/csr",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/errors",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/helpers",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/helpers/derhelpers",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/info",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/log",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ocsp",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/ocsp/config",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/cloudflare/cfssl/signer/local",
"Comment": "1.3.1-12-g8d76cdf",
"Comment": "1.3.1-12-g8d76cdf7",
"Rev": "8d76cdf742f917ba01551bf7ca41f8a7f82da15a"
},
{
"ImportPath": "github.com/globalsign/certlint/asn1",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/certdata",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/aiaissuers",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/all",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/basicconstraints",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/extensions",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/extkeyusage",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/internal",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/issuerdn",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/keyusage",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/publickey",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/publickey/goodkey",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/publicsuffix",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/revocation",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/serialnumber",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/signaturealgorithm",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/subject",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/subjectaltname",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/validity",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/version",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/certificate/wildcard",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/adobetimestamp",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/all",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/authorityinfoaccess",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/authoritykeyid",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/basicconstraints",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/crldistributionpoints",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/ct",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/extkeyusage",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/keyusage",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/nameconstraints",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/ocspmuststaple",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/ocspnocheck",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/pdfrevocation",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/policyidentifiers",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/smimecapabilities",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/subjectaltname",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/checks/extensions/subjectkeyid",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/globalsign/certlint/errors",
"Rev": "d4a45be06892f3e664f69892aca79a48df510be0"
},
{
"ImportPath": "github.com/go-sql-driver/mysql",
"Comment": "v1.3.0-28-g3955978",
@ -342,7 +187,7 @@
},
{
"ImportPath": "github.com/jmhodges/clock",
"Comment": "v1.1",
"Comment": "v1.0-4-g880ee4c",
"Rev": "880ee4c335489bc78d01e4d0a254ae880734bc15"
},
{
@ -366,7 +211,7 @@
},
{
"ImportPath": "github.com/matttproud/golang_protobuf_extensions/pbutil",
"Comment": "v1.0.1",
"Comment": "v1.0.0-2-gc12348c",
"Rev": "c12348ce28de40eed0136aa2b644d0ee0650e56c"
},
{
@ -417,6 +262,34 @@
"Comment": "v0.4.0-13-g67ec7c1",
"Rev": "67ec7c1b9678b719e579f2118c36fca4e11a0fb1"
},
{
"ImportPath": "github.com/zmap/zcrypto/json",
"Rev": "cf96f6a8516687d345fe4ba98b5defa4e823f736"
},
{
"ImportPath": "github.com/zmap/zcrypto/x509",
"Rev": "cf96f6a8516687d345fe4ba98b5defa4e823f736"
},
{
"ImportPath": "github.com/zmap/zcrypto/x509/ct",
"Rev": "cf96f6a8516687d345fe4ba98b5defa4e823f736"
},
{
"ImportPath": "github.com/zmap/zcrypto/x509/pkix",
"Rev": "cf96f6a8516687d345fe4ba98b5defa4e823f736"
},
{
"ImportPath": "github.com/zmap/zlint",
"Rev": "9bebe5e32c2c4b27892021e8e2f0459ef3b075ab"
},
{
"ImportPath": "github.com/zmap/zlint/lints",
"Rev": "9bebe5e32c2c4b27892021e8e2f0459ef3b075ab"
},
{
"ImportPath": "github.com/zmap/zlint/util",
"Rev": "9bebe5e32c2c4b27892021e8e2f0459ef3b075ab"
},
{
"ImportPath": "golang.org/x/crypto/cryptobyte",
"Rev": "650f4a345ab4e5b245a3034b110ebc7299e68186"
@ -473,10 +346,6 @@
"ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "d11bb6cd8e3c4e60239c9cb20ef68586d74500d0"
},
{
"ImportPath": "golang.org/x/net/publicsuffix",
"Rev": "d11bb6cd8e3c4e60239c9cb20ef68586d74500d0"
},
{
"ImportPath": "golang.org/x/net/trace",
"Rev": "d11bb6cd8e3c4e60239c9cb20ef68586d74500d0"

View File

@ -1,7 +1,7 @@
package main
import (
"crypto/x509"
"bytes"
"encoding/json"
"flag"
"fmt"
@ -16,6 +16,9 @@ import (
"github.com/jmhodges/clock"
"github.com/prometheus/client_golang/prometheus"
"github.com/zmap/zcrypto/x509"
"github.com/zmap/zlint"
"github.com/zmap/zlint/lints"
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
@ -24,31 +27,17 @@ import (
"github.com/letsencrypt/boulder/metrics"
"github.com/letsencrypt/boulder/policy"
"github.com/letsencrypt/boulder/sa"
lintasn1 "github.com/globalsign/certlint/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
_ "github.com/globalsign/certlint/checks/certificate/all"
_ "github.com/globalsign/certlint/checks/extensions/all"
)
const (
good = "valid"
bad = "invalid"
certlintCNError = "commonName field is deprecated"
filenameLayout = "20060102"
expectedValidityPeriod = time.Hour * 24 * 90
)
// certlintPSLErrPattern is a regex for matching Certlint error strings
// complaining about a CN or SAN matching a public suffix list entry.
var certlintPSLErrPattern = regexp.MustCompile(
`^Certificate (?:CommonName|subjectAltName) "[a-z0-9*][a-z0-9-.]+" ` +
`equals "[a-z0-9][a-z0-9-.]+" from the public suffix list$`)
// For defense-in-depth in addition to using the PA & its hostnamePolicy to
// check domain names we also perform a check against the regex's from the
// forbiddenDomains array
@ -196,54 +185,49 @@ func (c *certChecker) processCerts(wg *sync.WaitGroup, badResultsOnly bool) {
wg.Done()
}
// Extensions that we allow in certificates
var allowedExtensions = map[string]bool{
"1.3.6.1.5.5.7.1.1": true, // Authority info access
"2.5.29.35": true, // Authority key identifier
"2.5.29.19": true, // Basic constraints
"2.5.29.32": true, // Certificate policies
"2.5.29.31": true, // CRL distribution points
"2.5.29.37": true, // Extended key usage
"2.5.29.15": true, // Key usage
"2.5.29.17": true, // Subject alternative name
"2.5.29.14": true, // Subject key identifier
"1.3.6.1.4.1.11129.2.4.2": true, // SCT list
"1.3.6.1.5.5.7.1.24": true, // TLS feature
}
// For extensions that have a fixed value we check that it contains that value
var expectedExtensionContent = map[string][]byte{
"1.3.6.1.5.5.7.1.24": []byte{0x30, 0x03, 0x02, 0x01, 0x05}, // Must staple feature
}
func (c *certChecker) checkCert(cert core.Certificate) (problems []string) {
// Check digests match
if cert.Digest != core.Fingerprint256(cert.DER) {
problems = append(problems, "Stored digest doesn't match certificate digest")
}
// Run linter
linter := new(lintasn1.Linter)
errs := linter.CheckStruct(cert.DER)
if errs != nil {
for _, err := range errs.List() {
problems = append(problems, err.Error())
}
}
d, err := certdata.Load(cert.DER)
if err != nil {
problems = append(problems, err.Error())
}
errs = checks.Certificate.Check(d)
if errs != nil {
for _, err := range errs.List() {
// commonName has been deprecated for years, but common practice is still
// to include it for compatibility reasons. For instance, Chrome on macOS
// until very recently would error on an empty Subject (which is what we
// would have if we omitted CommonName). There have been proposals at
// CA/Browser Forum for an alternate contentless field whose purpose would
// just be to make Subject non-empty, but so far they have not been
// successful. If the check error is `certlintCNError`, ignore it.
if err.Error() == certlintCNError {
continue
}
// certlint incorrectly flags certificates that have a subj. CN or SAN
// exactly equal to a *private* entry on the public suffix list. Since
// this is allowed and LE issues certificates for such names we ignore
// errors of this form until the upstream bug can be addressed. See
// https://github.com/globalsign/certlint/issues/17
if certlintPSLErrPattern.MatchString(err.Error()) {
continue
}
problems = append(problems, err.Error())
}
}
// Parse certificate
parsedCert, err := x509.ParseCertificate(cert.DER)
if err != nil {
problems = append(problems, fmt.Sprintf("Couldn't parse stored certificate: %s", err))
} else {
// Run zlint checks
results := zlint.LintCertificate(parsedCert)
for name, res := range results.Results {
// ignore notices and warnings
if res.Status >= lints.Error {
prob := fmt.Sprintf("zlint %s: %s", res.Status, name)
if res.Details != "" {
prob = fmt.Sprintf("%s %s", prob, res.Details)
}
problems = append(problems, prob)
}
}
// Check stored serial is correct
storedSerial, err := core.StringToSerial(cert.Serial)
if err != nil {
@ -308,6 +292,17 @@ func (c *certChecker) checkCert(cert core.Certificate) (problems []string) {
if !reflect.DeepEqual(parsedCert.ExtKeyUsage, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}) {
problems = append(problems, "Certificate has incorrect key usage extensions")
}
for _, ext := range parsedCert.Extensions {
if _, ok := allowedExtensions[ext.Id.String()]; !ok {
problems = append(problems, fmt.Sprintf("Certificate contains an unexpected extension: %s", ext.Id))
}
if expectedContent, ok := expectedExtensionContent[ext.Id.String()]; ok {
if !bytes.Equal(ext.Value, expectedContent) {
problems = append(problems, fmt.Sprintf("Certificate extension %s contains unexpected content: has %x, expected %x", ext.Id, ext.Value, expectedContent))
}
}
}
}
return problems
}

View File

@ -176,7 +176,8 @@ func TestCheckCert(t *testing.T) {
"*.foodnotbombs.mil",
// `dev-myqnapcloud.com` is included because it is an exact private
// entry on the public suffix list
"dev-myqnapcloud.com"},
"dev-myqnapcloud.com",
},
SerialNumber: serial,
BasicConstraintsValid: false,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
@ -211,8 +212,7 @@ func TestCheckCert(t *testing.T) {
"Certificate has incorrect key usage extensions": 1,
"Certificate has common name >64 characters long (65)": 1,
"Policy Authority isn't willing to issue for '*.foodnotbombs.mil': Wildcard names not supported": 1,
"commonName exceeding max length of 64": 1,
"Certificate contains unknown extension (1.3.3.7)": 1,
"Certificate contains an unexpected extension: 1.3.3.7": 1,
}
for _, p := range problems {
_, ok := problemsMap[p]

14
vendor/github.com/asaskevich/govalidator/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,14 @@
language: go
go:
- 1.1
- 1.2
- 1.3
- 1.4
- 1.5
- 1.6
- tip
notifications:
email:
- bwatas@gmail.com

21
vendor/github.com/asaskevich/govalidator/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Alex Saskevich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

423
vendor/github.com/asaskevich/govalidator/README.md generated vendored Normal file
View File

@ -0,0 +1,423 @@
govalidator
===========
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/asaskevich/govalidator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![GoDoc](https://godoc.org/github.com/asaskevich/govalidator?status.png)](https://godoc.org/github.com/asaskevich/govalidator) [![Coverage Status](https://img.shields.io/coveralls/asaskevich/govalidator.svg)](https://coveralls.io/r/asaskevich/govalidator?branch=master) [![wercker status](https://app.wercker.com/status/1ec990b09ea86c910d5f08b0e02c6043/s "wercker status")](https://app.wercker.com/project/bykey/1ec990b09ea86c910d5f08b0e02c6043)
[![Build Status](https://travis-ci.org/asaskevich/govalidator.svg?branch=master)](https://travis-ci.org/asaskevich/govalidator) [![Go Report Card](https://goreportcard.com/badge/github.com/asaskevich/govalidator)](https://goreportcard.com/report/github.com/asaskevich/govalidator) [![GoSearch](http://go-search.org/badge?id=github.com%2Fasaskevich%2Fgovalidator)](http://go-search.org/view?id=github.com%2Fasaskevich%2Fgovalidator)
A package of validators and sanitizers for strings, structs and collections. Based on [validator.js](https://github.com/chriso/validator.js).
#### Installation
Make sure that Go is installed on your computer.
Type the following command in your terminal:
go get github.com/asaskevich/govalidator
or you can get specified release of the package with `gopkg.in`:
go get gopkg.in/asaskevich/govalidator.v4
After it the package is ready to use.
#### Import package in your project
Add following line in your `*.go` file:
```go
import "github.com/asaskevich/govalidator"
```
If you are unhappy to use long `govalidator`, you can do something like this:
```go
import (
valid "github.com/asaskevich/govalidator"
)
```
#### Activate behavior to require all fields have a validation tag by default
`SetFieldsRequiredByDefault` causes validation to fail when struct fields do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`). A good place to activate this is a package init function or the main() function.
```go
import "github.com/asaskevich/govalidator"
func init() {
govalidator.SetFieldsRequiredByDefault(true)
}
```
Here's some code to explain it:
```go
// this struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
type exampleStruct struct {
Name string ``
Email string `valid:"email"`
}
// this, however, will only fail when Email is empty or an invalid email address:
type exampleStruct2 struct {
Name string `valid:"-"`
Email string `valid:"email"`
}
// lastly, this will only fail when Email is an invalid email address but not when it's empty:
type exampleStruct2 struct {
Name string `valid:"-"`
Email string `valid:"email,optional"`
}
```
#### Recent breaking changes (see [#123](https://github.com/asaskevich/govalidator/pull/123))
##### Custom validator function signature
A context was added as the second parameter, for structs this is the object being validated this makes dependent validation possible.
```go
import "github.com/asaskevich/govalidator"
// old signature
func(i interface{}) bool
// new signature
func(i interface{}, o interface{}) bool
```
##### Adding a custom validator
This was changed to prevent data races when accessing custom validators.
```go
import "github.com/asaskevich/govalidator"
// before
govalidator.CustomTypeTagMap["customByteArrayValidator"] = CustomTypeValidator(func(i interface{}, o interface{}) bool {
// ...
})
// after
govalidator.CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, o interface{}) bool {
// ...
}))
```
#### List of functions:
```go
func Abs(value float64) float64
func BlackList(str, chars string) string
func ByteLength(str string, params ...string) bool
func CamelCaseToUnderscore(str string) string
func Contains(str, substring string) bool
func Count(array []interface{}, iterator ConditionIterator) int
func Each(array []interface{}, iterator Iterator)
func ErrorByField(e error, field string) string
func ErrorsByField(e error) map[string]string
func Filter(array []interface{}, iterator ConditionIterator) []interface{}
func Find(array []interface{}, iterator ConditionIterator) interface{}
func GetLine(s string, index int) (string, error)
func GetLines(s string) []string
func InRange(value, left, right float64) bool
func IsASCII(str string) bool
func IsAlpha(str string) bool
func IsAlphanumeric(str string) bool
func IsBase64(str string) bool
func IsByteLength(str string, min, max int) bool
func IsCIDR(str string) bool
func IsCreditCard(str string) bool
func IsDNSName(str string) bool
func IsDataURI(str string) bool
func IsDialString(str string) bool
func IsDivisibleBy(str, num string) bool
func IsEmail(str string) bool
func IsFilePath(str string) (bool, int)
func IsFloat(str string) bool
func IsFullWidth(str string) bool
func IsHalfWidth(str string) bool
func IsHexadecimal(str string) bool
func IsHexcolor(str string) bool
func IsHost(str string) bool
func IsIP(str string) bool
func IsIPv4(str string) bool
func IsIPv6(str string) bool
func IsISBN(str string, version int) bool
func IsISBN10(str string) bool
func IsISBN13(str string) bool
func IsISO3166Alpha2(str string) bool
func IsISO3166Alpha3(str string) bool
func IsISO693Alpha2(str string) bool
func IsISO693Alpha3b(str string) bool
func IsISO4217(str string) bool
func IsIn(str string, params ...string) bool
func IsInt(str string) bool
func IsJSON(str string) bool
func IsLatitude(str string) bool
func IsLongitude(str string) bool
func IsLowerCase(str string) bool
func IsMAC(str string) bool
func IsMongoID(str string) bool
func IsMultibyte(str string) bool
func IsNatural(value float64) bool
func IsNegative(value float64) bool
func IsNonNegative(value float64) bool
func IsNonPositive(value float64) bool
func IsNull(str string) bool
func IsNumeric(str string) bool
func IsPort(str string) bool
func IsPositive(value float64) bool
func IsPrintableASCII(str string) bool
func IsRFC3339(str string) bool
func IsRGBcolor(str string) bool
func IsRequestURI(rawurl string) bool
func IsRequestURL(rawurl string) bool
func IsSSN(str string) bool
func IsSemver(str string) bool
func IsTime(str string, format string) bool
func IsURL(str string) bool
func IsUTFDigit(str string) bool
func IsUTFLetter(str string) bool
func IsUTFLetterNumeric(str string) bool
func IsUTFNumeric(str string) bool
func IsUUID(str string) bool
func IsUUIDv3(str string) bool
func IsUUIDv4(str string) bool
func IsUUIDv5(str string) bool
func IsUpperCase(str string) bool
func IsVariableWidth(str string) bool
func IsWhole(value float64) bool
func LeftTrim(str, chars string) string
func Map(array []interface{}, iterator ResultIterator) []interface{}
func Matches(str, pattern string) bool
func NormalizeEmail(str string) (string, error)
func PadBoth(str string, padStr string, padLen int) string
func PadLeft(str string, padStr string, padLen int) string
func PadRight(str string, padStr string, padLen int) string
func Range(str string, params ...string) bool
func RemoveTags(s string) string
func ReplacePattern(str, pattern, replace string) string
func Reverse(s string) string
func RightTrim(str, chars string) string
func RuneLength(str string, params ...string) bool
func SafeFileName(str string) string
func SetFieldsRequiredByDefault(value bool)
func Sign(value float64) float64
func StringLength(str string, params ...string) bool
func StringMatches(s string, params ...string) bool
func StripLow(str string, keepNewLines bool) string
func ToBoolean(str string) (bool, error)
func ToFloat(str string) (float64, error)
func ToInt(str string) (int64, error)
func ToJSON(obj interface{}) (string, error)
func ToString(obj interface{}) string
func Trim(str, chars string) string
func Truncate(str string, length int, ending string) string
func UnderscoreToCamelCase(s string) string
func ValidateStruct(s interface{}) (bool, error)
func WhiteList(str, chars string) string
type ConditionIterator
type CustomTypeValidator
type Error
func (e Error) Error() string
type Errors
func (es Errors) Error() string
func (es Errors) Errors() []error
type ISO3166Entry
type Iterator
type ParamValidator
type ResultIterator
type UnsupportedTypeError
func (e *UnsupportedTypeError) Error() string
type Validator
```
#### Examples
###### IsURL
```go
println(govalidator.IsURL(`http://user@pass:domain.com/path/page`))
```
###### ToString
```go
type User struct {
FirstName string
LastName string
}
str := govalidator.ToString(&User{"John", "Juan"})
println(str)
```
###### Each, Map, Filter, Count for slices
Each iterates over the slice/array and calls Iterator for every item
```go
data := []interface{}{1, 2, 3, 4, 5}
var fn govalidator.Iterator = func(value interface{}, index int) {
println(value.(int))
}
govalidator.Each(data, fn)
```
```go
data := []interface{}{1, 2, 3, 4, 5}
var fn govalidator.ResultIterator = func(value interface{}, index int) interface{} {
return value.(int) * 3
}
_ = govalidator.Map(data, fn) // result = []interface{}{1, 6, 9, 12, 15}
```
```go
data := []interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
var fn govalidator.ConditionIterator = func(value interface{}, index int) bool {
return value.(int)%2 == 0
}
_ = govalidator.Filter(data, fn) // result = []interface{}{2, 4, 6, 8, 10}
_ = govalidator.Count(data, fn) // result = 5
```
###### ValidateStruct [#2](https://github.com/asaskevich/govalidator/pull/2)
If you want to validate structs, you can use tag `valid` for any field in your structure. All validators used with this field in one tag are separated by comma. If you want to skip validation, place `-` in your tag. If you need a validator that is not on the list below, you can add it like this:
```go
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
return str == "duck"
})
```
For completely custom validators (interface-based), see below.
Here is a list of available validators for struct fields (validator - used function):
```go
"email": IsEmail,
"url": IsURL,
"dialstring": IsDialString,
"requrl": IsRequestURL,
"requri": IsRequestURI,
"alpha": IsAlpha,
"utfletter": IsUTFLetter,
"alphanum": IsAlphanumeric,
"utfletternum": IsUTFLetterNumeric,
"numeric": IsNumeric,
"utfnumeric": IsUTFNumeric,
"utfdigit": IsUTFDigit,
"hexadecimal": IsHexadecimal,
"hexcolor": IsHexcolor,
"rgbcolor": IsRGBcolor,
"lowercase": IsLowerCase,
"uppercase": IsUpperCase,
"int": IsInt,
"float": IsFloat,
"null": IsNull,
"uuid": IsUUID,
"uuidv3": IsUUIDv3,
"uuidv4": IsUUIDv4,
"uuidv5": IsUUIDv5,
"creditcard": IsCreditCard,
"isbn10": IsISBN10,
"isbn13": IsISBN13,
"json": IsJSON,
"multibyte": IsMultibyte,
"ascii": IsASCII,
"printableascii": IsPrintableASCII,
"fullwidth": IsFullWidth,
"halfwidth": IsHalfWidth,
"variablewidth": IsVariableWidth,
"base64": IsBase64,
"datauri": IsDataURI,
"ip": IsIP,
"port": IsPort,
"ipv4": IsIPv4,
"ipv6": IsIPv6,
"dns": IsDNSName,
"host": IsHost,
"mac": IsMAC,
"latitude": IsLatitude,
"longitude": IsLongitude,
"ssn": IsSSN,
"semver": IsSemver,
"rfc3339": IsRFC3339,
"ISO3166Alpha2": IsISO3166Alpha2,
"ISO3166Alpha3": IsISO3166Alpha3,
```
Validators with parameters
```go
"range(min|max)": Range,
"length(min|max)": ByteLength,
"runelength(min|max)": RuneLength,
"matches(pattern)": StringMatches,
"in(string1|string2|...|stringN)": IsIn,
```
And here is small example of usage:
```go
type Post struct {
Title string `valid:"alphanum,required"`
Message string `valid:"duck,ascii"`
AuthorIP string `valid:"ipv4"`
Date string `valid:"-"`
}
post := &Post{
Title: "My Example Post",
Message: "duck",
AuthorIP: "123.234.54.3",
}
// Add your own struct validation tags
govalidator.TagMap["duck"] = govalidator.Validator(func(str string) bool {
return str == "duck"
})
result, err := govalidator.ValidateStruct(post)
if err != nil {
println("error: " + err.Error())
}
println(result)
```
###### WhiteList
```go
// Remove all characters from string ignoring characters between "a" and "z"
println(govalidator.WhiteList("a3a43a5a4a3a2a23a4a5a4a3a4", "a-z") == "aaaaaaaaaaaa")
```
###### Custom validation functions
Custom validation using your own domain specific validators is also available - here's an example of how to use it:
```go
import "github.com/asaskevich/govalidator"
type CustomByteArray [6]byte // custom types are supported and can be validated
type StructWithCustomByteArray struct {
ID CustomByteArray `valid:"customByteArrayValidator,customMinLengthValidator"` // multiple custom validators are possible as well and will be evaluated in sequence
Email string `valid:"email"`
CustomMinLength int `valid:"-"`
}
govalidator.CustomTypeTagMap.Set("customByteArrayValidator", CustomTypeValidator(func(i interface{}, context interface{}) bool {
switch v := context.(type) { // you can type switch on the context interface being validated
case StructWithCustomByteArray:
// you can check and validate against some other field in the context,
// return early or not validate against the context at all your choice
case SomeOtherType:
// ...
default:
// expecting some other type? Throw/panic here or continue
}
switch v := i.(type) { // type switch on the struct field being validated
case CustomByteArray:
for _, e := range v { // this validator checks that the byte array is not empty, i.e. not all zeroes
if e != 0 {
return true
}
}
}
return false
}))
govalidator.CustomTypeTagMap.Set("customMinLengthValidator", CustomTypeValidator(func(i interface{}, context interface{}) bool {
switch v := context.(type) { // this validates a field against the value in another field, i.e. dependent validation
case StructWithCustomByteArray:
return len(v.ID) >= v.CustomMinLength
}
return false
}))
```
#### Notes
Documentation is available here: [godoc.org](https://godoc.org/github.com/asaskevich/govalidator).
Full information about code coverage is also available here: [govalidator on gocover.io](http://gocover.io/github.com/asaskevich/govalidator).
#### Support
If you do have a contribution for the package feel free to put up a Pull Request or open Issue.
#### Special thanks to [contributors](https://github.com/asaskevich/govalidator/graphs/contributors)
* [Daniel Lohse](https://github.com/annismckenzie)
* [Attila Oláh](https://github.com/attilaolah)
* [Daniel Korner](https://github.com/Dadie)
* [Steven Wilkin](https://github.com/stevenwilkin)
* [Deiwin Sarjas](https://github.com/deiwin)
* [Noah Shibley](https://github.com/slugmobile)
* [Nathan Davies](https://github.com/nathj07)
* [Matt Sanford](https://github.com/mzsanford)
* [Simon ccl1115](https://github.com/ccl1115)

58
vendor/github.com/asaskevich/govalidator/arrays.go generated vendored Normal file
View File

@ -0,0 +1,58 @@
package govalidator
// Iterator is the function that accepts element of slice/array and its index
type Iterator func(interface{}, int)
// ResultIterator is the function that accepts element of slice/array and its index and returns any result
type ResultIterator func(interface{}, int) interface{}
// ConditionIterator is the function that accepts element of slice/array and its index and returns boolean
type ConditionIterator func(interface{}, int) bool
// Each iterates over the slice and apply Iterator to every item
func Each(array []interface{}, iterator Iterator) {
for index, data := range array {
iterator(data, index)
}
}
// Map iterates over the slice and apply ResultIterator to every item. Returns new slice as a result.
func Map(array []interface{}, iterator ResultIterator) []interface{} {
var result = make([]interface{}, len(array))
for index, data := range array {
result[index] = iterator(data, index)
}
return result
}
// Find iterates over the slice and apply ConditionIterator to every item. Returns first item that meet ConditionIterator or nil otherwise.
func Find(array []interface{}, iterator ConditionIterator) interface{} {
for index, data := range array {
if iterator(data, index) {
return data
}
}
return nil
}
// Filter iterates over the slice and apply ConditionIterator to every item. Returns new slice.
func Filter(array []interface{}, iterator ConditionIterator) []interface{} {
var result = make([]interface{}, 0)
for index, data := range array {
if iterator(data, index) {
result = append(result, data)
}
}
return result
}
// Count iterates over the slice and apply ConditionIterator to every item. Returns count of items that meets ConditionIterator.
func Count(array []interface{}, iterator ConditionIterator) int {
count := 0
for index, data := range array {
if iterator(data, index) {
count = count + 1
}
}
return count
}

45
vendor/github.com/asaskevich/govalidator/converter.go generated vendored Normal file
View File

@ -0,0 +1,45 @@
package govalidator
import (
"encoding/json"
"fmt"
"strconv"
)
// ToString convert the input to a string.
func ToString(obj interface{}) string {
res := fmt.Sprintf("%v", obj)
return string(res)
}
// ToJSON convert the input to a valid JSON string
func ToJSON(obj interface{}) (string, error) {
res, err := json.Marshal(obj)
if err != nil {
res = []byte("")
}
return string(res), err
}
// ToFloat convert the input string to a float, or 0.0 if the input is not a float.
func ToFloat(str string) (float64, error) {
res, err := strconv.ParseFloat(str, 64)
if err != nil {
res = 0.0
}
return res, err
}
// ToInt convert the input string to an integer, or 0 if the input is not an integer.
func ToInt(str string) (int64, error) {
res, err := strconv.ParseInt(str, 0, 64)
if err != nil {
res = 0
}
return res, err
}
// ToBoolean convert the input string to a boolean.
func ToBoolean(str string) (bool, error) {
return strconv.ParseBool(str)
}

31
vendor/github.com/asaskevich/govalidator/error.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
package govalidator
// Errors is an array of multiple errors and conforms to the error interface.
type Errors []error
// Errors returns itself.
func (es Errors) Errors() []error {
return es
}
func (es Errors) Error() string {
var err string
for _, e := range es {
err += e.Error() + ";"
}
return err
}
// Error encapsulates a name, an error and whether there's a custom error message or not.
type Error struct {
Name string
Err error
CustomErrorMessageExists bool
}
func (e Error) Error() string {
if e.CustomErrorMessageExists {
return e.Err.Error()
}
return e.Name + ": " + e.Err.Error()
}

57
vendor/github.com/asaskevich/govalidator/numerics.go generated vendored Normal file
View File

@ -0,0 +1,57 @@
package govalidator
import "math"
// Abs returns absolute value of number
func Abs(value float64) float64 {
return math.Abs(value)
}
// Sign returns signum of number: 1 in case of value > 0, -1 in case of value < 0, 0 otherwise
func Sign(value float64) float64 {
if value > 0 {
return 1
} else if value < 0 {
return -1
} else {
return 0
}
}
// IsNegative returns true if value < 0
func IsNegative(value float64) bool {
return value < 0
}
// IsPositive returns true if value > 0
func IsPositive(value float64) bool {
return value > 0
}
// IsNonNegative returns true if value >= 0
func IsNonNegative(value float64) bool {
return value >= 0
}
// IsNonPositive returns true if value <= 0
func IsNonPositive(value float64) bool {
return value <= 0
}
// InRange returns true if value lies between left and right border
func InRange(value, left, right float64) bool {
if left > right {
left, right = right, left
}
return value >= left && value <= right
}
// IsWhole returns true if value is whole number
func IsWhole(value float64) bool {
return math.Remainder(value, 1) == 0
}
// IsNatural returns true if value is natural number (positive and whole)
func IsNatural(value float64) bool {
return IsWhole(value) && IsPositive(value)
}

91
vendor/github.com/asaskevich/govalidator/patterns.go generated vendored Normal file
View File

@ -0,0 +1,91 @@
package govalidator
import "regexp"
// Basic regular expressions for validating strings
const (
Email string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
CreditCard string = "^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11})$"
ISBN10 string = "^(?:[0-9]{9}X|[0-9]{10})$"
ISBN13 string = "^(?:[0-9]{13})$"
UUID3 string = "^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$"
UUID4 string = "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
UUID5 string = "^[0-9a-f]{8}-[0-9a-f]{4}-5[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
UUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
Alpha string = "^[a-zA-Z]+$"
Alphanumeric string = "^[a-zA-Z0-9]+$"
Numeric string = "^[0-9]+$"
Int string = "^(?:[-+]?(?:0|[1-9][0-9]*))$"
Float string = "^(?:[-+]?(?:[0-9]+))?(?:\\.[0-9]*)?(?:[eE][\\+\\-]?(?:[0-9]+))?$"
Hexadecimal string = "^[0-9a-fA-F]+$"
Hexcolor string = "^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$"
RGBcolor string = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\)$"
ASCII string = "^[\x00-\x7F]+$"
Multibyte string = "[^\x00-\x7F]"
FullWidth string = "[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]"
HalfWidth string = "[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]"
Base64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
PrintableASCII string = "^[\x20-\x7E]+$"
DataURI string = "^data:.+\\/(.+);base64$"
Latitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
Longitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
DNSName string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`
IP string = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
URLSchema string = `((ftp|tcp|udp|wss?|https?):\/\/)`
URLUsername string = `(\S+(:\S*)?@)`
Hostname string = ``
URLPath string = `((\/|\?|#)[^\s]*)`
URLPort string = `(:(\d{1,5}))`
URLIP string = `([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))`
URLSubdomain string = `((www\.)|([a-zA-Z0-9]([-\.][-\._a-zA-Z0-9]+)*))`
URL string = `^` + URLSchema + `?` + URLUsername + `?` + `((` + URLIP + `|(\[` + IP + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + URLSubdomain + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + URLPort + `?` + URLPath + `?$`
SSN string = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
WinPath string = `^[a-zA-Z]:\\(?:[^\\/:*?"<>|\r\n]+\\)*[^\\/:*?"<>|\r\n]*$`
UnixPath string = `^(/[^/\x00]*)+/?$`
Semver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$"
tagName string = "valid"
)
// Used by IsFilePath func
const (
// Unknown is unresolved OS type
Unknown = iota
// Win is Windows type
Win
// Unix is *nix OS types
Unix
)
var (
rxEmail = regexp.MustCompile(Email)
rxCreditCard = regexp.MustCompile(CreditCard)
rxISBN10 = regexp.MustCompile(ISBN10)
rxISBN13 = regexp.MustCompile(ISBN13)
rxUUID3 = regexp.MustCompile(UUID3)
rxUUID4 = regexp.MustCompile(UUID4)
rxUUID5 = regexp.MustCompile(UUID5)
rxUUID = regexp.MustCompile(UUID)
rxAlpha = regexp.MustCompile(Alpha)
rxAlphanumeric = regexp.MustCompile(Alphanumeric)
rxNumeric = regexp.MustCompile(Numeric)
rxInt = regexp.MustCompile(Int)
rxFloat = regexp.MustCompile(Float)
rxHexadecimal = regexp.MustCompile(Hexadecimal)
rxHexcolor = regexp.MustCompile(Hexcolor)
rxRGBcolor = regexp.MustCompile(RGBcolor)
rxASCII = regexp.MustCompile(ASCII)
rxPrintableASCII = regexp.MustCompile(PrintableASCII)
rxMultibyte = regexp.MustCompile(Multibyte)
rxFullWidth = regexp.MustCompile(FullWidth)
rxHalfWidth = regexp.MustCompile(HalfWidth)
rxBase64 = regexp.MustCompile(Base64)
rxDataURI = regexp.MustCompile(DataURI)
rxLatitude = regexp.MustCompile(Latitude)
rxLongitude = regexp.MustCompile(Longitude)
rxDNSName = regexp.MustCompile(DNSName)
rxURL = regexp.MustCompile(URL)
rxSSN = regexp.MustCompile(SSN)
rxWinPath = regexp.MustCompile(WinPath)
rxUnixPath = regexp.MustCompile(UnixPath)
rxSemver = regexp.MustCompile(Semver)
)

613
vendor/github.com/asaskevich/govalidator/types.go generated vendored Normal file
View File

@ -0,0 +1,613 @@
package govalidator
import (
"reflect"
"regexp"
"sync"
)
// Validator is a wrapper for a validator function that returns bool and accepts string.
type Validator func(str string) bool
// CustomTypeValidator is a wrapper for validator functions that returns bool and accepts any type.
// The second parameter should be the context (in the case of validating a struct: the whole object being validated).
type CustomTypeValidator func(i interface{}, o interface{}) bool
// ParamValidator is a wrapper for validator functions that accepts additional parameters.
type ParamValidator func(str string, params ...string) bool
type tagOptionsMap map[string]string
// UnsupportedTypeError is a wrapper for reflect.Type
type UnsupportedTypeError struct {
Type reflect.Type
}
// stringValues is a slice of reflect.Value holding *reflect.StringValue.
// It implements the methods to sort by string.
type stringValues []reflect.Value
// ParamTagMap is a map of functions accept variants parameters
var ParamTagMap = map[string]ParamValidator{
"length": ByteLength,
"range": Range,
"runelength": RuneLength,
"stringlength": StringLength,
"matches": StringMatches,
"in": isInRaw,
}
// ParamTagRegexMap maps param tags to their respective regexes.
var ParamTagRegexMap = map[string]*regexp.Regexp{
"range": regexp.MustCompile("^range\\((\\d+)\\|(\\d+)\\)$"),
"length": regexp.MustCompile("^length\\((\\d+)\\|(\\d+)\\)$"),
"runelength": regexp.MustCompile("^runelength\\((\\d+)\\|(\\d+)\\)$"),
"stringlength": regexp.MustCompile("^stringlength\\((\\d+)\\|(\\d+)\\)$"),
"in": regexp.MustCompile(`^in\((.*)\)`),
"matches": regexp.MustCompile(`^matches\((.+)\)$`),
}
type customTypeTagMap struct {
validators map[string]CustomTypeValidator
sync.RWMutex
}
func (tm *customTypeTagMap) Get(name string) (CustomTypeValidator, bool) {
tm.RLock()
defer tm.RUnlock()
v, ok := tm.validators[name]
return v, ok
}
func (tm *customTypeTagMap) Set(name string, ctv CustomTypeValidator) {
tm.Lock()
defer tm.Unlock()
tm.validators[name] = ctv
}
// CustomTypeTagMap is a map of functions that can be used as tags for ValidateStruct function.
// Use this to validate compound or custom types that need to be handled as a whole, e.g.
// `type UUID [16]byte` (this would be handled as an array of bytes).
var CustomTypeTagMap = &customTypeTagMap{validators: make(map[string]CustomTypeValidator)}
// TagMap is a map of functions, that can be used as tags for ValidateStruct function.
var TagMap = map[string]Validator{
"email": IsEmail,
"url": IsURL,
"dialstring": IsDialString,
"requrl": IsRequestURL,
"requri": IsRequestURI,
"alpha": IsAlpha,
"utfletter": IsUTFLetter,
"alphanum": IsAlphanumeric,
"utfletternum": IsUTFLetterNumeric,
"numeric": IsNumeric,
"utfnumeric": IsUTFNumeric,
"utfdigit": IsUTFDigit,
"hexadecimal": IsHexadecimal,
"hexcolor": IsHexcolor,
"rgbcolor": IsRGBcolor,
"lowercase": IsLowerCase,
"uppercase": IsUpperCase,
"int": IsInt,
"float": IsFloat,
"null": IsNull,
"uuid": IsUUID,
"uuidv3": IsUUIDv3,
"uuidv4": IsUUIDv4,
"uuidv5": IsUUIDv5,
"creditcard": IsCreditCard,
"isbn10": IsISBN10,
"isbn13": IsISBN13,
"json": IsJSON,
"multibyte": IsMultibyte,
"ascii": IsASCII,
"printableascii": IsPrintableASCII,
"fullwidth": IsFullWidth,
"halfwidth": IsHalfWidth,
"variablewidth": IsVariableWidth,
"base64": IsBase64,
"datauri": IsDataURI,
"ip": IsIP,
"port": IsPort,
"ipv4": IsIPv4,
"ipv6": IsIPv6,
"dns": IsDNSName,
"host": IsHost,
"mac": IsMAC,
"latitude": IsLatitude,
"longitude": IsLongitude,
"ssn": IsSSN,
"semver": IsSemver,
"rfc3339": IsRFC3339,
"ISO3166Alpha2": IsISO3166Alpha2,
"ISO3166Alpha3": IsISO3166Alpha3,
"ISO4217": IsISO4217,
}
// ISO3166Entry stores country codes
type ISO3166Entry struct {
EnglishShortName string
FrenchShortName string
Alpha2Code string
Alpha3Code string
Numeric string
}
//ISO3166List based on https://www.iso.org/obp/ui/#search/code/ Code Type "Officially Assigned Codes"
var ISO3166List = []ISO3166Entry{
{"Afghanistan", "Afghanistan (l')", "AF", "AFG", "004"},
{"Albania", "Albanie (l')", "AL", "ALB", "008"},
{"Antarctica", "Antarctique (l')", "AQ", "ATA", "010"},
{"Algeria", "Algérie (l')", "DZ", "DZA", "012"},
{"American Samoa", "Samoa américaines (les)", "AS", "ASM", "016"},
{"Andorra", "Andorre (l')", "AD", "AND", "020"},
{"Angola", "Angola (l')", "AO", "AGO", "024"},
{"Antigua and Barbuda", "Antigua-et-Barbuda", "AG", "ATG", "028"},
{"Azerbaijan", "Azerbaïdjan (l')", "AZ", "AZE", "031"},
{"Argentina", "Argentine (l')", "AR", "ARG", "032"},
{"Australia", "Australie (l')", "AU", "AUS", "036"},
{"Austria", "Autriche (l')", "AT", "AUT", "040"},
{"Bahamas (the)", "Bahamas (les)", "BS", "BHS", "044"},
{"Bahrain", "Bahreïn", "BH", "BHR", "048"},
{"Bangladesh", "Bangladesh (le)", "BD", "BGD", "050"},
{"Armenia", "Arménie (l')", "AM", "ARM", "051"},
{"Barbados", "Barbade (la)", "BB", "BRB", "052"},
{"Belgium", "Belgique (la)", "BE", "BEL", "056"},
{"Bermuda", "Bermudes (les)", "BM", "BMU", "060"},
{"Bhutan", "Bhoutan (le)", "BT", "BTN", "064"},
{"Bolivia (Plurinational State of)", "Bolivie (État plurinational de)", "BO", "BOL", "068"},
{"Bosnia and Herzegovina", "Bosnie-Herzégovine (la)", "BA", "BIH", "070"},
{"Botswana", "Botswana (le)", "BW", "BWA", "072"},
{"Bouvet Island", "Bouvet (l'Île)", "BV", "BVT", "074"},
{"Brazil", "Brésil (le)", "BR", "BRA", "076"},
{"Belize", "Belize (le)", "BZ", "BLZ", "084"},
{"British Indian Ocean Territory (the)", "Indien (le Territoire britannique de l'océan)", "IO", "IOT", "086"},
{"Solomon Islands", "Salomon (Îles)", "SB", "SLB", "090"},
{"Virgin Islands (British)", "Vierges britanniques (les Îles)", "VG", "VGB", "092"},
{"Brunei Darussalam", "Brunéi Darussalam (le)", "BN", "BRN", "096"},
{"Bulgaria", "Bulgarie (la)", "BG", "BGR", "100"},
{"Myanmar", "Myanmar (le)", "MM", "MMR", "104"},
{"Burundi", "Burundi (le)", "BI", "BDI", "108"},
{"Belarus", "Bélarus (le)", "BY", "BLR", "112"},
{"Cambodia", "Cambodge (le)", "KH", "KHM", "116"},
{"Cameroon", "Cameroun (le)", "CM", "CMR", "120"},
{"Canada", "Canada (le)", "CA", "CAN", "124"},
{"Cabo Verde", "Cabo Verde", "CV", "CPV", "132"},
{"Cayman Islands (the)", "Caïmans (les Îles)", "KY", "CYM", "136"},
{"Central African Republic (the)", "République centrafricaine (la)", "CF", "CAF", "140"},
{"Sri Lanka", "Sri Lanka", "LK", "LKA", "144"},
{"Chad", "Tchad (le)", "TD", "TCD", "148"},
{"Chile", "Chili (le)", "CL", "CHL", "152"},
{"China", "Chine (la)", "CN", "CHN", "156"},
{"Taiwan (Province of China)", "Taïwan (Province de Chine)", "TW", "TWN", "158"},
{"Christmas Island", "Christmas (l'Île)", "CX", "CXR", "162"},
{"Cocos (Keeling) Islands (the)", "Cocos (les Îles)/ Keeling (les Îles)", "CC", "CCK", "166"},
{"Colombia", "Colombie (la)", "CO", "COL", "170"},
{"Comoros (the)", "Comores (les)", "KM", "COM", "174"},
{"Mayotte", "Mayotte", "YT", "MYT", "175"},
{"Congo (the)", "Congo (le)", "CG", "COG", "178"},
{"Congo (the Democratic Republic of the)", "Congo (la République démocratique du)", "CD", "COD", "180"},
{"Cook Islands (the)", "Cook (les Îles)", "CK", "COK", "184"},
{"Costa Rica", "Costa Rica (le)", "CR", "CRI", "188"},
{"Croatia", "Croatie (la)", "HR", "HRV", "191"},
{"Cuba", "Cuba", "CU", "CUB", "192"},
{"Cyprus", "Chypre", "CY", "CYP", "196"},
{"Czech Republic (the)", "tchèque (la République)", "CZ", "CZE", "203"},
{"Benin", "Bénin (le)", "BJ", "BEN", "204"},
{"Denmark", "Danemark (le)", "DK", "DNK", "208"},
{"Dominica", "Dominique (la)", "DM", "DMA", "212"},
{"Dominican Republic (the)", "dominicaine (la République)", "DO", "DOM", "214"},
{"Ecuador", "Équateur (l')", "EC", "ECU", "218"},
{"El Salvador", "El Salvador", "SV", "SLV", "222"},
{"Equatorial Guinea", "Guinée équatoriale (la)", "GQ", "GNQ", "226"},
{"Ethiopia", "Éthiopie (l')", "ET", "ETH", "231"},
{"Eritrea", "Érythrée (l')", "ER", "ERI", "232"},
{"Estonia", "Estonie (l')", "EE", "EST", "233"},
{"Faroe Islands (the)", "Féroé (les Îles)", "FO", "FRO", "234"},
{"Falkland Islands (the) [Malvinas]", "Falkland (les Îles)/Malouines (les Îles)", "FK", "FLK", "238"},
{"South Georgia and the South Sandwich Islands", "Géorgie du Sud-et-les Îles Sandwich du Sud (la)", "GS", "SGS", "239"},
{"Fiji", "Fidji (les)", "FJ", "FJI", "242"},
{"Finland", "Finlande (la)", "FI", "FIN", "246"},
{"Åland Islands", "Åland(les Îles)", "AX", "ALA", "248"},
{"France", "France (la)", "FR", "FRA", "250"},
{"French Guiana", "Guyane française (la )", "GF", "GUF", "254"},
{"French Polynesia", "Polynésie française (la)", "PF", "PYF", "258"},
{"French Southern Territories (the)", "Terres australes françaises (les)", "TF", "ATF", "260"},
{"Djibouti", "Djibouti", "DJ", "DJI", "262"},
{"Gabon", "Gabon (le)", "GA", "GAB", "266"},
{"Georgia", "Géorgie (la)", "GE", "GEO", "268"},
{"Gambia (the)", "Gambie (la)", "GM", "GMB", "270"},
{"Palestine, State of", "Palestine, État de", "PS", "PSE", "275"},
{"Germany", "Allemagne (l')", "DE", "DEU", "276"},
{"Ghana", "Ghana (le)", "GH", "GHA", "288"},
{"Gibraltar", "Gibraltar", "GI", "GIB", "292"},
{"Kiribati", "Kiribati", "KI", "KIR", "296"},
{"Greece", "Grèce (la)", "GR", "GRC", "300"},
{"Greenland", "Groenland (le)", "GL", "GRL", "304"},
{"Grenada", "Grenade (la)", "GD", "GRD", "308"},
{"Guadeloupe", "Guadeloupe (la)", "GP", "GLP", "312"},
{"Guam", "Guam", "GU", "GUM", "316"},
{"Guatemala", "Guatemala (le)", "GT", "GTM", "320"},
{"Guinea", "Guinée (la)", "GN", "GIN", "324"},
{"Guyana", "Guyana (le)", "GY", "GUY", "328"},
{"Haiti", "Haïti", "HT", "HTI", "332"},
{"Heard Island and McDonald Islands", "Heard-et-Îles MacDonald (l'Île)", "HM", "HMD", "334"},
{"Holy See (the)", "Saint-Siège (le)", "VA", "VAT", "336"},
{"Honduras", "Honduras (le)", "HN", "HND", "340"},
{"Hong Kong", "Hong Kong", "HK", "HKG", "344"},
{"Hungary", "Hongrie (la)", "HU", "HUN", "348"},
{"Iceland", "Islande (l')", "IS", "ISL", "352"},
{"India", "Inde (l')", "IN", "IND", "356"},
{"Indonesia", "Indonésie (l')", "ID", "IDN", "360"},
{"Iran (Islamic Republic of)", "Iran (République Islamique d')", "IR", "IRN", "364"},
{"Iraq", "Iraq (l')", "IQ", "IRQ", "368"},
{"Ireland", "Irlande (l')", "IE", "IRL", "372"},
{"Israel", "Israël", "IL", "ISR", "376"},
{"Italy", "Italie (l')", "IT", "ITA", "380"},
{"Côte d'Ivoire", "Côte d'Ivoire (la)", "CI", "CIV", "384"},
{"Jamaica", "Jamaïque (la)", "JM", "JAM", "388"},
{"Japan", "Japon (le)", "JP", "JPN", "392"},
{"Kazakhstan", "Kazakhstan (le)", "KZ", "KAZ", "398"},
{"Jordan", "Jordanie (la)", "JO", "JOR", "400"},
{"Kenya", "Kenya (le)", "KE", "KEN", "404"},
{"Korea (the Democratic People's Republic of)", "Corée (la République populaire démocratique de)", "KP", "PRK", "408"},
{"Korea (the Republic of)", "Corée (la République de)", "KR", "KOR", "410"},
{"Kuwait", "Koweït (le)", "KW", "KWT", "414"},
{"Kyrgyzstan", "Kirghizistan (le)", "KG", "KGZ", "417"},
{"Lao People's Democratic Republic (the)", "Lao, République démocratique populaire", "LA", "LAO", "418"},
{"Lebanon", "Liban (le)", "LB", "LBN", "422"},
{"Lesotho", "Lesotho (le)", "LS", "LSO", "426"},
{"Latvia", "Lettonie (la)", "LV", "LVA", "428"},
{"Liberia", "Libéria (le)", "LR", "LBR", "430"},
{"Libya", "Libye (la)", "LY", "LBY", "434"},
{"Liechtenstein", "Liechtenstein (le)", "LI", "LIE", "438"},
{"Lithuania", "Lituanie (la)", "LT", "LTU", "440"},
{"Luxembourg", "Luxembourg (le)", "LU", "LUX", "442"},
{"Macao", "Macao", "MO", "MAC", "446"},
{"Madagascar", "Madagascar", "MG", "MDG", "450"},
{"Malawi", "Malawi (le)", "MW", "MWI", "454"},
{"Malaysia", "Malaisie (la)", "MY", "MYS", "458"},
{"Maldives", "Maldives (les)", "MV", "MDV", "462"},
{"Mali", "Mali (le)", "ML", "MLI", "466"},
{"Malta", "Malte", "MT", "MLT", "470"},
{"Martinique", "Martinique (la)", "MQ", "MTQ", "474"},
{"Mauritania", "Mauritanie (la)", "MR", "MRT", "478"},
{"Mauritius", "Maurice", "MU", "MUS", "480"},
{"Mexico", "Mexique (le)", "MX", "MEX", "484"},
{"Monaco", "Monaco", "MC", "MCO", "492"},
{"Mongolia", "Mongolie (la)", "MN", "MNG", "496"},
{"Moldova (the Republic of)", "Moldova , République de", "MD", "MDA", "498"},
{"Montenegro", "Monténégro (le)", "ME", "MNE", "499"},
{"Montserrat", "Montserrat", "MS", "MSR", "500"},
{"Morocco", "Maroc (le)", "MA", "MAR", "504"},
{"Mozambique", "Mozambique (le)", "MZ", "MOZ", "508"},
{"Oman", "Oman", "OM", "OMN", "512"},
{"Namibia", "Namibie (la)", "NA", "NAM", "516"},
{"Nauru", "Nauru", "NR", "NRU", "520"},
{"Nepal", "Népal (le)", "NP", "NPL", "524"},
{"Netherlands (the)", "Pays-Bas (les)", "NL", "NLD", "528"},
{"Curaçao", "Curaçao", "CW", "CUW", "531"},
{"Aruba", "Aruba", "AW", "ABW", "533"},
{"Sint Maarten (Dutch part)", "Saint-Martin (partie néerlandaise)", "SX", "SXM", "534"},
{"Bonaire, Sint Eustatius and Saba", "Bonaire, Saint-Eustache et Saba", "BQ", "BES", "535"},
{"New Caledonia", "Nouvelle-Calédonie (la)", "NC", "NCL", "540"},
{"Vanuatu", "Vanuatu (le)", "VU", "VUT", "548"},
{"New Zealand", "Nouvelle-Zélande (la)", "NZ", "NZL", "554"},
{"Nicaragua", "Nicaragua (le)", "NI", "NIC", "558"},
{"Niger (the)", "Niger (le)", "NE", "NER", "562"},
{"Nigeria", "Nigéria (le)", "NG", "NGA", "566"},
{"Niue", "Niue", "NU", "NIU", "570"},
{"Norfolk Island", "Norfolk (l'Île)", "NF", "NFK", "574"},
{"Norway", "Norvège (la)", "NO", "NOR", "578"},
{"Northern Mariana Islands (the)", "Mariannes du Nord (les Îles)", "MP", "MNP", "580"},
{"United States Minor Outlying Islands (the)", "Îles mineures éloignées des États-Unis (les)", "UM", "UMI", "581"},
{"Micronesia (Federated States of)", "Micronésie (États fédérés de)", "FM", "FSM", "583"},
{"Marshall Islands (the)", "Marshall (Îles)", "MH", "MHL", "584"},
{"Palau", "Palaos (les)", "PW", "PLW", "585"},
{"Pakistan", "Pakistan (le)", "PK", "PAK", "586"},
{"Panama", "Panama (le)", "PA", "PAN", "591"},
{"Papua New Guinea", "Papouasie-Nouvelle-Guinée (la)", "PG", "PNG", "598"},
{"Paraguay", "Paraguay (le)", "PY", "PRY", "600"},
{"Peru", "Pérou (le)", "PE", "PER", "604"},
{"Philippines (the)", "Philippines (les)", "PH", "PHL", "608"},
{"Pitcairn", "Pitcairn", "PN", "PCN", "612"},
{"Poland", "Pologne (la)", "PL", "POL", "616"},
{"Portugal", "Portugal (le)", "PT", "PRT", "620"},
{"Guinea-Bissau", "Guinée-Bissau (la)", "GW", "GNB", "624"},
{"Timor-Leste", "Timor-Leste (le)", "TL", "TLS", "626"},
{"Puerto Rico", "Porto Rico", "PR", "PRI", "630"},
{"Qatar", "Qatar (le)", "QA", "QAT", "634"},
{"Réunion", "Réunion (La)", "RE", "REU", "638"},
{"Romania", "Roumanie (la)", "RO", "ROU", "642"},
{"Russian Federation (the)", "Russie (la Fédération de)", "RU", "RUS", "643"},
{"Rwanda", "Rwanda (le)", "RW", "RWA", "646"},
{"Saint Barthélemy", "Saint-Barthélemy", "BL", "BLM", "652"},
{"Saint Helena, Ascension and Tristan da Cunha", "Sainte-Hélène, Ascension et Tristan da Cunha", "SH", "SHN", "654"},
{"Saint Kitts and Nevis", "Saint-Kitts-et-Nevis", "KN", "KNA", "659"},
{"Anguilla", "Anguilla", "AI", "AIA", "660"},
{"Saint Lucia", "Sainte-Lucie", "LC", "LCA", "662"},
{"Saint Martin (French part)", "Saint-Martin (partie française)", "MF", "MAF", "663"},
{"Saint Pierre and Miquelon", "Saint-Pierre-et-Miquelon", "PM", "SPM", "666"},
{"Saint Vincent and the Grenadines", "Saint-Vincent-et-les Grenadines", "VC", "VCT", "670"},
{"San Marino", "Saint-Marin", "SM", "SMR", "674"},
{"Sao Tome and Principe", "Sao Tomé-et-Principe", "ST", "STP", "678"},
{"Saudi Arabia", "Arabie saoudite (l')", "SA", "SAU", "682"},
{"Senegal", "Sénégal (le)", "SN", "SEN", "686"},
{"Serbia", "Serbie (la)", "RS", "SRB", "688"},
{"Seychelles", "Seychelles (les)", "SC", "SYC", "690"},
{"Sierra Leone", "Sierra Leone (la)", "SL", "SLE", "694"},
{"Singapore", "Singapour", "SG", "SGP", "702"},
{"Slovakia", "Slovaquie (la)", "SK", "SVK", "703"},
{"Viet Nam", "Viet Nam (le)", "VN", "VNM", "704"},
{"Slovenia", "Slovénie (la)", "SI", "SVN", "705"},
{"Somalia", "Somalie (la)", "SO", "SOM", "706"},
{"South Africa", "Afrique du Sud (l')", "ZA", "ZAF", "710"},
{"Zimbabwe", "Zimbabwe (le)", "ZW", "ZWE", "716"},
{"Spain", "Espagne (l')", "ES", "ESP", "724"},
{"South Sudan", "Soudan du Sud (le)", "SS", "SSD", "728"},
{"Sudan (the)", "Soudan (le)", "SD", "SDN", "729"},
{"Western Sahara*", "Sahara occidental (le)*", "EH", "ESH", "732"},
{"Suriname", "Suriname (le)", "SR", "SUR", "740"},
{"Svalbard and Jan Mayen", "Svalbard et l'Île Jan Mayen (le)", "SJ", "SJM", "744"},
{"Swaziland", "Swaziland (le)", "SZ", "SWZ", "748"},
{"Sweden", "Suède (la)", "SE", "SWE", "752"},
{"Switzerland", "Suisse (la)", "CH", "CHE", "756"},
{"Syrian Arab Republic", "République arabe syrienne (la)", "SY", "SYR", "760"},
{"Tajikistan", "Tadjikistan (le)", "TJ", "TJK", "762"},
{"Thailand", "Thaïlande (la)", "TH", "THA", "764"},
{"Togo", "Togo (le)", "TG", "TGO", "768"},
{"Tokelau", "Tokelau (les)", "TK", "TKL", "772"},
{"Tonga", "Tonga (les)", "TO", "TON", "776"},
{"Trinidad and Tobago", "Trinité-et-Tobago (la)", "TT", "TTO", "780"},
{"United Arab Emirates (the)", "Émirats arabes unis (les)", "AE", "ARE", "784"},
{"Tunisia", "Tunisie (la)", "TN", "TUN", "788"},
{"Turkey", "Turquie (la)", "TR", "TUR", "792"},
{"Turkmenistan", "Turkménistan (le)", "TM", "TKM", "795"},
{"Turks and Caicos Islands (the)", "Turks-et-Caïcos (les Îles)", "TC", "TCA", "796"},
{"Tuvalu", "Tuvalu (les)", "TV", "TUV", "798"},
{"Uganda", "Ouganda (l')", "UG", "UGA", "800"},
{"Ukraine", "Ukraine (l')", "UA", "UKR", "804"},
{"Macedonia (the former Yugoslav Republic of)", "Macédoine (l'exRépublique yougoslave de)", "MK", "MKD", "807"},
{"Egypt", "Égypte (l')", "EG", "EGY", "818"},
{"United Kingdom of Great Britain and Northern Ireland (the)", "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)", "GB", "GBR", "826"},
{"Guernsey", "Guernesey", "GG", "GGY", "831"},
{"Jersey", "Jersey", "JE", "JEY", "832"},
{"Isle of Man", "Île de Man", "IM", "IMN", "833"},
{"Tanzania, United Republic of", "Tanzanie, République-Unie de", "TZ", "TZA", "834"},
{"United States of America (the)", "États-Unis d'Amérique (les)", "US", "USA", "840"},
{"Virgin Islands (U.S.)", "Vierges des États-Unis (les Îles)", "VI", "VIR", "850"},
{"Burkina Faso", "Burkina Faso (le)", "BF", "BFA", "854"},
{"Uruguay", "Uruguay (l')", "UY", "URY", "858"},
{"Uzbekistan", "Ouzbékistan (l')", "UZ", "UZB", "860"},
{"Venezuela (Bolivarian Republic of)", "Venezuela (République bolivarienne du)", "VE", "VEN", "862"},
{"Wallis and Futuna", "Wallis-et-Futuna", "WF", "WLF", "876"},
{"Samoa", "Samoa (le)", "WS", "WSM", "882"},
{"Yemen", "Yémen (le)", "YE", "YEM", "887"},
{"Zambia", "Zambie (la)", "ZM", "ZMB", "894"},
}
// ISO4217List is the list of ISO currency codes
var ISO4217List = []string{
"AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN",
"BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BOV", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD",
"CAD", "CDF", "CHE", "CHF", "CHW", "CLF", "CLP", "CNY", "COP", "COU", "CRC", "CUC", "CUP", "CVE", "CZK",
"DJF", "DKK", "DOP", "DZD",
"EGP", "ERN", "ETB", "EUR",
"FJD", "FKP",
"GBP", "GEL", "GHS", "GIP", "GMD", "GNF", "GTQ", "GYD",
"HKD", "HNL", "HRK", "HTG", "HUF",
"IDR", "ILS", "INR", "IQD", "IRR", "ISK",
"JMD", "JOD", "JPY",
"KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT",
"LAK", "LBP", "LKR", "LRD", "LSL", "LYD",
"MAD", "MDL", "MGA", "MKD", "MMK", "MNT", "MOP", "MRO", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZN",
"NAD", "NGN", "NIO", "NOK", "NPR", "NZD",
"OMR",
"PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PYG",
"QAR",
"RON", "RSD", "RUB", "RWF",
"SAR", "SBD", "SCR", "SDG", "SEK", "SGD", "SHP", "SLL", "SOS", "SRD", "SSP", "STD", "SVC", "SYP", "SZL",
"THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TWD", "TZS",
"UAH", "UGX", "USD", "USN", "UYI", "UYU", "UZS",
"VEF", "VND", "VUV",
"WST",
"XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XOF", "XPD", "XPF", "XPT", "XSU", "XTS", "XUA", "XXX",
"YER",
"ZAR", "ZMW", "ZWL",
}
// ISO693Entry stores ISO language codes
type ISO693Entry struct {
Alpha3bCode string
Alpha2Code string
English string
}
//ISO693List based on http://data.okfn.org/data/core/language-codes/r/language-codes-3b2.json
var ISO693List = []ISO693Entry{
{Alpha3bCode: "aar", Alpha2Code: "aa", English: "Afar"},
{Alpha3bCode: "abk", Alpha2Code: "ab", English: "Abkhazian"},
{Alpha3bCode: "afr", Alpha2Code: "af", English: "Afrikaans"},
{Alpha3bCode: "aka", Alpha2Code: "ak", English: "Akan"},
{Alpha3bCode: "alb", Alpha2Code: "sq", English: "Albanian"},
{Alpha3bCode: "amh", Alpha2Code: "am", English: "Amharic"},
{Alpha3bCode: "ara", Alpha2Code: "ar", English: "Arabic"},
{Alpha3bCode: "arg", Alpha2Code: "an", English: "Aragonese"},
{Alpha3bCode: "arm", Alpha2Code: "hy", English: "Armenian"},
{Alpha3bCode: "asm", Alpha2Code: "as", English: "Assamese"},
{Alpha3bCode: "ava", Alpha2Code: "av", English: "Avaric"},
{Alpha3bCode: "ave", Alpha2Code: "ae", English: "Avestan"},
{Alpha3bCode: "aym", Alpha2Code: "ay", English: "Aymara"},
{Alpha3bCode: "aze", Alpha2Code: "az", English: "Azerbaijani"},
{Alpha3bCode: "bak", Alpha2Code: "ba", English: "Bashkir"},
{Alpha3bCode: "bam", Alpha2Code: "bm", English: "Bambara"},
{Alpha3bCode: "baq", Alpha2Code: "eu", English: "Basque"},
{Alpha3bCode: "bel", Alpha2Code: "be", English: "Belarusian"},
{Alpha3bCode: "ben", Alpha2Code: "bn", English: "Bengali"},
{Alpha3bCode: "bih", Alpha2Code: "bh", English: "Bihari languages"},
{Alpha3bCode: "bis", Alpha2Code: "bi", English: "Bislama"},
{Alpha3bCode: "bos", Alpha2Code: "bs", English: "Bosnian"},
{Alpha3bCode: "bre", Alpha2Code: "br", English: "Breton"},
{Alpha3bCode: "bul", Alpha2Code: "bg", English: "Bulgarian"},
{Alpha3bCode: "bur", Alpha2Code: "my", English: "Burmese"},
{Alpha3bCode: "cat", Alpha2Code: "ca", English: "Catalan; Valencian"},
{Alpha3bCode: "cha", Alpha2Code: "ch", English: "Chamorro"},
{Alpha3bCode: "che", Alpha2Code: "ce", English: "Chechen"},
{Alpha3bCode: "chi", Alpha2Code: "zh", English: "Chinese"},
{Alpha3bCode: "chu", Alpha2Code: "cu", English: "Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic"},
{Alpha3bCode: "chv", Alpha2Code: "cv", English: "Chuvash"},
{Alpha3bCode: "cor", Alpha2Code: "kw", English: "Cornish"},
{Alpha3bCode: "cos", Alpha2Code: "co", English: "Corsican"},
{Alpha3bCode: "cre", Alpha2Code: "cr", English: "Cree"},
{Alpha3bCode: "cze", Alpha2Code: "cs", English: "Czech"},
{Alpha3bCode: "dan", Alpha2Code: "da", English: "Danish"},
{Alpha3bCode: "div", Alpha2Code: "dv", English: "Divehi; Dhivehi; Maldivian"},
{Alpha3bCode: "dut", Alpha2Code: "nl", English: "Dutch; Flemish"},
{Alpha3bCode: "dzo", Alpha2Code: "dz", English: "Dzongkha"},
{Alpha3bCode: "eng", Alpha2Code: "en", English: "English"},
{Alpha3bCode: "epo", Alpha2Code: "eo", English: "Esperanto"},
{Alpha3bCode: "est", Alpha2Code: "et", English: "Estonian"},
{Alpha3bCode: "ewe", Alpha2Code: "ee", English: "Ewe"},
{Alpha3bCode: "fao", Alpha2Code: "fo", English: "Faroese"},
{Alpha3bCode: "fij", Alpha2Code: "fj", English: "Fijian"},
{Alpha3bCode: "fin", Alpha2Code: "fi", English: "Finnish"},
{Alpha3bCode: "fre", Alpha2Code: "fr", English: "French"},
{Alpha3bCode: "fry", Alpha2Code: "fy", English: "Western Frisian"},
{Alpha3bCode: "ful", Alpha2Code: "ff", English: "Fulah"},
{Alpha3bCode: "geo", Alpha2Code: "ka", English: "Georgian"},
{Alpha3bCode: "ger", Alpha2Code: "de", English: "German"},
{Alpha3bCode: "gla", Alpha2Code: "gd", English: "Gaelic; Scottish Gaelic"},
{Alpha3bCode: "gle", Alpha2Code: "ga", English: "Irish"},
{Alpha3bCode: "glg", Alpha2Code: "gl", English: "Galician"},
{Alpha3bCode: "glv", Alpha2Code: "gv", English: "Manx"},
{Alpha3bCode: "gre", Alpha2Code: "el", English: "Greek, Modern (1453-)"},
{Alpha3bCode: "grn", Alpha2Code: "gn", English: "Guarani"},
{Alpha3bCode: "guj", Alpha2Code: "gu", English: "Gujarati"},
{Alpha3bCode: "hat", Alpha2Code: "ht", English: "Haitian; Haitian Creole"},
{Alpha3bCode: "hau", Alpha2Code: "ha", English: "Hausa"},
{Alpha3bCode: "heb", Alpha2Code: "he", English: "Hebrew"},
{Alpha3bCode: "her", Alpha2Code: "hz", English: "Herero"},
{Alpha3bCode: "hin", Alpha2Code: "hi", English: "Hindi"},
{Alpha3bCode: "hmo", Alpha2Code: "ho", English: "Hiri Motu"},
{Alpha3bCode: "hrv", Alpha2Code: "hr", English: "Croatian"},
{Alpha3bCode: "hun", Alpha2Code: "hu", English: "Hungarian"},
{Alpha3bCode: "ibo", Alpha2Code: "ig", English: "Igbo"},
{Alpha3bCode: "ice", Alpha2Code: "is", English: "Icelandic"},
{Alpha3bCode: "ido", Alpha2Code: "io", English: "Ido"},
{Alpha3bCode: "iii", Alpha2Code: "ii", English: "Sichuan Yi; Nuosu"},
{Alpha3bCode: "iku", Alpha2Code: "iu", English: "Inuktitut"},
{Alpha3bCode: "ile", Alpha2Code: "ie", English: "Interlingue; Occidental"},
{Alpha3bCode: "ina", Alpha2Code: "ia", English: "Interlingua (International Auxiliary Language Association)"},
{Alpha3bCode: "ind", Alpha2Code: "id", English: "Indonesian"},
{Alpha3bCode: "ipk", Alpha2Code: "ik", English: "Inupiaq"},
{Alpha3bCode: "ita", Alpha2Code: "it", English: "Italian"},
{Alpha3bCode: "jav", Alpha2Code: "jv", English: "Javanese"},
{Alpha3bCode: "jpn", Alpha2Code: "ja", English: "Japanese"},
{Alpha3bCode: "kal", Alpha2Code: "kl", English: "Kalaallisut; Greenlandic"},
{Alpha3bCode: "kan", Alpha2Code: "kn", English: "Kannada"},
{Alpha3bCode: "kas", Alpha2Code: "ks", English: "Kashmiri"},
{Alpha3bCode: "kau", Alpha2Code: "kr", English: "Kanuri"},
{Alpha3bCode: "kaz", Alpha2Code: "kk", English: "Kazakh"},
{Alpha3bCode: "khm", Alpha2Code: "km", English: "Central Khmer"},
{Alpha3bCode: "kik", Alpha2Code: "ki", English: "Kikuyu; Gikuyu"},
{Alpha3bCode: "kin", Alpha2Code: "rw", English: "Kinyarwanda"},
{Alpha3bCode: "kir", Alpha2Code: "ky", English: "Kirghiz; Kyrgyz"},
{Alpha3bCode: "kom", Alpha2Code: "kv", English: "Komi"},
{Alpha3bCode: "kon", Alpha2Code: "kg", English: "Kongo"},
{Alpha3bCode: "kor", Alpha2Code: "ko", English: "Korean"},
{Alpha3bCode: "kua", Alpha2Code: "kj", English: "Kuanyama; Kwanyama"},
{Alpha3bCode: "kur", Alpha2Code: "ku", English: "Kurdish"},
{Alpha3bCode: "lao", Alpha2Code: "lo", English: "Lao"},
{Alpha3bCode: "lat", Alpha2Code: "la", English: "Latin"},
{Alpha3bCode: "lav", Alpha2Code: "lv", English: "Latvian"},
{Alpha3bCode: "lim", Alpha2Code: "li", English: "Limburgan; Limburger; Limburgish"},
{Alpha3bCode: "lin", Alpha2Code: "ln", English: "Lingala"},
{Alpha3bCode: "lit", Alpha2Code: "lt", English: "Lithuanian"},
{Alpha3bCode: "ltz", Alpha2Code: "lb", English: "Luxembourgish; Letzeburgesch"},
{Alpha3bCode: "lub", Alpha2Code: "lu", English: "Luba-Katanga"},
{Alpha3bCode: "lug", Alpha2Code: "lg", English: "Ganda"},
{Alpha3bCode: "mac", Alpha2Code: "mk", English: "Macedonian"},
{Alpha3bCode: "mah", Alpha2Code: "mh", English: "Marshallese"},
{Alpha3bCode: "mal", Alpha2Code: "ml", English: "Malayalam"},
{Alpha3bCode: "mao", Alpha2Code: "mi", English: "Maori"},
{Alpha3bCode: "mar", Alpha2Code: "mr", English: "Marathi"},
{Alpha3bCode: "may", Alpha2Code: "ms", English: "Malay"},
{Alpha3bCode: "mlg", Alpha2Code: "mg", English: "Malagasy"},
{Alpha3bCode: "mlt", Alpha2Code: "mt", English: "Maltese"},
{Alpha3bCode: "mon", Alpha2Code: "mn", English: "Mongolian"},
{Alpha3bCode: "nau", Alpha2Code: "na", English: "Nauru"},
{Alpha3bCode: "nav", Alpha2Code: "nv", English: "Navajo; Navaho"},
{Alpha3bCode: "nbl", Alpha2Code: "nr", English: "Ndebele, South; South Ndebele"},
{Alpha3bCode: "nde", Alpha2Code: "nd", English: "Ndebele, North; North Ndebele"},
{Alpha3bCode: "ndo", Alpha2Code: "ng", English: "Ndonga"},
{Alpha3bCode: "nep", Alpha2Code: "ne", English: "Nepali"},
{Alpha3bCode: "nno", Alpha2Code: "nn", English: "Norwegian Nynorsk; Nynorsk, Norwegian"},
{Alpha3bCode: "nob", Alpha2Code: "nb", English: "Bokmål, Norwegian; Norwegian Bokmål"},
{Alpha3bCode: "nor", Alpha2Code: "no", English: "Norwegian"},
{Alpha3bCode: "nya", Alpha2Code: "ny", English: "Chichewa; Chewa; Nyanja"},
{Alpha3bCode: "oci", Alpha2Code: "oc", English: "Occitan (post 1500); Provençal"},
{Alpha3bCode: "oji", Alpha2Code: "oj", English: "Ojibwa"},
{Alpha3bCode: "ori", Alpha2Code: "or", English: "Oriya"},
{Alpha3bCode: "orm", Alpha2Code: "om", English: "Oromo"},
{Alpha3bCode: "oss", Alpha2Code: "os", English: "Ossetian; Ossetic"},
{Alpha3bCode: "pan", Alpha2Code: "pa", English: "Panjabi; Punjabi"},
{Alpha3bCode: "per", Alpha2Code: "fa", English: "Persian"},
{Alpha3bCode: "pli", Alpha2Code: "pi", English: "Pali"},
{Alpha3bCode: "pol", Alpha2Code: "pl", English: "Polish"},
{Alpha3bCode: "por", Alpha2Code: "pt", English: "Portuguese"},
{Alpha3bCode: "pus", Alpha2Code: "ps", English: "Pushto; Pashto"},
{Alpha3bCode: "que", Alpha2Code: "qu", English: "Quechua"},
{Alpha3bCode: "roh", Alpha2Code: "rm", English: "Romansh"},
{Alpha3bCode: "rum", Alpha2Code: "ro", English: "Romanian; Moldavian; Moldovan"},
{Alpha3bCode: "run", Alpha2Code: "rn", English: "Rundi"},
{Alpha3bCode: "rus", Alpha2Code: "ru", English: "Russian"},
{Alpha3bCode: "sag", Alpha2Code: "sg", English: "Sango"},
{Alpha3bCode: "san", Alpha2Code: "sa", English: "Sanskrit"},
{Alpha3bCode: "sin", Alpha2Code: "si", English: "Sinhala; Sinhalese"},
{Alpha3bCode: "slo", Alpha2Code: "sk", English: "Slovak"},
{Alpha3bCode: "slv", Alpha2Code: "sl", English: "Slovenian"},
{Alpha3bCode: "sme", Alpha2Code: "se", English: "Northern Sami"},
{Alpha3bCode: "smo", Alpha2Code: "sm", English: "Samoan"},
{Alpha3bCode: "sna", Alpha2Code: "sn", English: "Shona"},
{Alpha3bCode: "snd", Alpha2Code: "sd", English: "Sindhi"},
{Alpha3bCode: "som", Alpha2Code: "so", English: "Somali"},
{Alpha3bCode: "sot", Alpha2Code: "st", English: "Sotho, Southern"},
{Alpha3bCode: "spa", Alpha2Code: "es", English: "Spanish; Castilian"},
{Alpha3bCode: "srd", Alpha2Code: "sc", English: "Sardinian"},
{Alpha3bCode: "srp", Alpha2Code: "sr", English: "Serbian"},
{Alpha3bCode: "ssw", Alpha2Code: "ss", English: "Swati"},
{Alpha3bCode: "sun", Alpha2Code: "su", English: "Sundanese"},
{Alpha3bCode: "swa", Alpha2Code: "sw", English: "Swahili"},
{Alpha3bCode: "swe", Alpha2Code: "sv", English: "Swedish"},
{Alpha3bCode: "tah", Alpha2Code: "ty", English: "Tahitian"},
{Alpha3bCode: "tam", Alpha2Code: "ta", English: "Tamil"},
{Alpha3bCode: "tat", Alpha2Code: "tt", English: "Tatar"},
{Alpha3bCode: "tel", Alpha2Code: "te", English: "Telugu"},
{Alpha3bCode: "tgk", Alpha2Code: "tg", English: "Tajik"},
{Alpha3bCode: "tgl", Alpha2Code: "tl", English: "Tagalog"},
{Alpha3bCode: "tha", Alpha2Code: "th", English: "Thai"},
{Alpha3bCode: "tib", Alpha2Code: "bo", English: "Tibetan"},
{Alpha3bCode: "tir", Alpha2Code: "ti", English: "Tigrinya"},
{Alpha3bCode: "ton", Alpha2Code: "to", English: "Tonga (Tonga Islands)"},
{Alpha3bCode: "tsn", Alpha2Code: "tn", English: "Tswana"},
{Alpha3bCode: "tso", Alpha2Code: "ts", English: "Tsonga"},
{Alpha3bCode: "tuk", Alpha2Code: "tk", English: "Turkmen"},
{Alpha3bCode: "tur", Alpha2Code: "tr", English: "Turkish"},
{Alpha3bCode: "twi", Alpha2Code: "tw", English: "Twi"},
{Alpha3bCode: "uig", Alpha2Code: "ug", English: "Uighur; Uyghur"},
{Alpha3bCode: "ukr", Alpha2Code: "uk", English: "Ukrainian"},
{Alpha3bCode: "urd", Alpha2Code: "ur", English: "Urdu"},
{Alpha3bCode: "uzb", Alpha2Code: "uz", English: "Uzbek"},
{Alpha3bCode: "ven", Alpha2Code: "ve", English: "Venda"},
{Alpha3bCode: "vie", Alpha2Code: "vi", English: "Vietnamese"},
{Alpha3bCode: "vol", Alpha2Code: "vo", English: "Volapük"},
{Alpha3bCode: "wel", Alpha2Code: "cy", English: "Welsh"},
{Alpha3bCode: "wln", Alpha2Code: "wa", English: "Walloon"},
{Alpha3bCode: "wol", Alpha2Code: "wo", English: "Wolof"},
{Alpha3bCode: "xho", Alpha2Code: "xh", English: "Xhosa"},
{Alpha3bCode: "yid", Alpha2Code: "yi", English: "Yiddish"},
{Alpha3bCode: "yor", Alpha2Code: "yo", English: "Yoruba"},
{Alpha3bCode: "zha", Alpha2Code: "za", English: "Zhuang; Chuang"},
{Alpha3bCode: "zul", Alpha2Code: "zu", English: "Zulu"},
}

262
vendor/github.com/asaskevich/govalidator/utils.go generated vendored Normal file
View File

@ -0,0 +1,262 @@
package govalidator
import (
"errors"
"fmt"
"html"
"math"
"path"
"regexp"
"strings"
"unicode"
"unicode/utf8"
)
// Contains check if the string contains the substring.
func Contains(str, substring string) bool {
return strings.Contains(str, substring)
}
// Matches check if string matches the pattern (pattern is regular expression)
// In case of error return false
func Matches(str, pattern string) bool {
match, _ := regexp.MatchString(pattern, str)
return match
}
// LeftTrim trim characters from the left-side of the input.
// If second argument is empty, it's will be remove leading spaces.
func LeftTrim(str, chars string) string {
if chars == "" {
return strings.TrimLeftFunc(str, unicode.IsSpace)
}
r, _ := regexp.Compile("^[" + chars + "]+")
return r.ReplaceAllString(str, "")
}
// RightTrim trim characters from the right-side of the input.
// If second argument is empty, it's will be remove spaces.
func RightTrim(str, chars string) string {
if chars == "" {
return strings.TrimRightFunc(str, unicode.IsSpace)
}
r, _ := regexp.Compile("[" + chars + "]+$")
return r.ReplaceAllString(str, "")
}
// Trim trim characters from both sides of the input.
// If second argument is empty, it's will be remove spaces.
func Trim(str, chars string) string {
return LeftTrim(RightTrim(str, chars), chars)
}
// WhiteList remove characters that do not appear in the whitelist.
func WhiteList(str, chars string) string {
pattern := "[^" + chars + "]+"
r, _ := regexp.Compile(pattern)
return r.ReplaceAllString(str, "")
}
// BlackList remove characters that appear in the blacklist.
func BlackList(str, chars string) string {
pattern := "[" + chars + "]+"
r, _ := regexp.Compile(pattern)
return r.ReplaceAllString(str, "")
}
// StripLow remove characters with a numerical value < 32 and 127, mostly control characters.
// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD).
func StripLow(str string, keepNewLines bool) string {
chars := ""
if keepNewLines {
chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F"
} else {
chars = "\x00-\x1F\x7F"
}
return BlackList(str, chars)
}
// ReplacePattern replace regular expression pattern in string
func ReplacePattern(str, pattern, replace string) string {
r, _ := regexp.Compile(pattern)
return r.ReplaceAllString(str, replace)
}
// Escape replace <, >, & and " with HTML entities.
var Escape = html.EscapeString
func addSegment(inrune, segment []rune) []rune {
if len(segment) == 0 {
return inrune
}
if len(inrune) != 0 {
inrune = append(inrune, '_')
}
inrune = append(inrune, segment...)
return inrune
}
// UnderscoreToCamelCase converts from underscore separated form to camel case form.
// Ex.: my_func => MyFunc
func UnderscoreToCamelCase(s string) string {
return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1)
}
// CamelCaseToUnderscore converts from camel case form to underscore separated form.
// Ex.: MyFunc => my_func
func CamelCaseToUnderscore(str string) string {
var output []rune
var segment []rune
for _, r := range str {
if !unicode.IsLower(r) {
output = addSegment(output, segment)
segment = nil
}
segment = append(segment, unicode.ToLower(r))
}
output = addSegment(output, segment)
return string(output)
}
// Reverse return reversed string
func Reverse(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
// GetLines split string by "\n" and return array of lines
func GetLines(s string) []string {
return strings.Split(s, "\n")
}
// GetLine return specified line of multiline string
func GetLine(s string, index int) (string, error) {
lines := GetLines(s)
if index < 0 || index >= len(lines) {
return "", errors.New("line index out of bounds")
}
return lines[index], nil
}
// RemoveTags remove all tags from HTML string
func RemoveTags(s string) string {
return ReplacePattern(s, "<[^>]*>", "")
}
// SafeFileName return safe string that can be used in file names
func SafeFileName(str string) string {
name := strings.ToLower(str)
name = path.Clean(path.Base(name))
name = strings.Trim(name, " ")
separators, err := regexp.Compile(`[ &_=+:]`)
if err == nil {
name = separators.ReplaceAllString(name, "-")
}
legal, err := regexp.Compile(`[^[:alnum:]-.]`)
if err == nil {
name = legal.ReplaceAllString(name, "")
}
for strings.Contains(name, "--") {
name = strings.Replace(name, "--", "-", -1)
}
return name
}
// NormalizeEmail canonicalize an email address.
// The local part of the email address is lowercased for all domains; the hostname is always lowercased and
// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail).
// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and
// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are
// normalized to @gmail.com.
func NormalizeEmail(str string) (string, error) {
if !IsEmail(str) {
return "", fmt.Errorf("%s is not an email", str)
}
parts := strings.Split(str, "@")
parts[0] = strings.ToLower(parts[0])
parts[1] = strings.ToLower(parts[1])
if parts[1] == "gmail.com" || parts[1] == "googlemail.com" {
parts[1] = "gmail.com"
parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0]
}
return strings.Join(parts, "@"), nil
}
// Truncate a string to the closest length without breaking words.
func Truncate(str string, length int, ending string) string {
var aftstr, befstr string
if len(str) > length {
words := strings.Fields(str)
before, present := 0, 0
for i := range words {
befstr = aftstr
before = present
aftstr = aftstr + words[i] + " "
present = len(aftstr)
if present > length && i != 0 {
if (length - before) < (present - length) {
return Trim(befstr, " /\\.,\"'#!?&@+-") + ending
}
return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending
}
}
}
return str
}
// PadLeft pad left side of string if size of string is less then indicated pad length
func PadLeft(str string, padStr string, padLen int) string {
return buildPadStr(str, padStr, padLen, true, false)
}
// PadRight pad right side of string if size of string is less then indicated pad length
func PadRight(str string, padStr string, padLen int) string {
return buildPadStr(str, padStr, padLen, false, true)
}
// PadBoth pad sides of string if size of string is less then indicated pad length
func PadBoth(str string, padStr string, padLen int) string {
return buildPadStr(str, padStr, padLen, true, true)
}
// PadString either left, right or both sides, not the padding string can be unicode and more then one
// character
func buildPadStr(str string, padStr string, padLen int, padLeft bool, padRight bool) string {
// When padded length is less then the current string size
if padLen < utf8.RuneCountInString(str) {
return str
}
padLen -= utf8.RuneCountInString(str)
targetLen := padLen
targetLenLeft := targetLen
targetLenRight := targetLen
if padLeft && padRight {
targetLenLeft = padLen / 2
targetLenRight = padLen - targetLenLeft
}
strToRepeatLen := utf8.RuneCountInString(padStr)
repeatTimes := int(math.Ceil(float64(targetLen) / float64(strToRepeatLen)))
repeatedString := strings.Repeat(padStr, repeatTimes)
leftSide := ""
if padLeft {
leftSide = repeatedString[0:targetLenLeft]
}
rightSide := ""
if padRight {
rightSide = repeatedString[0:targetLenRight]
}
return leftSide + str + rightSide
}

1044
vendor/github.com/asaskevich/govalidator/validator.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

15
vendor/github.com/asaskevich/govalidator/wercker.yml generated vendored Normal file
View File

@ -0,0 +1,15 @@
box: golang
build:
steps:
- setup-go-workspace
- script:
name: go get
code: |
go version
go get -t ./...
- script:
name: go test
code: |
go test -race ./...

View File

@ -1,48 +0,0 @@
package asn1
import (
"encoding/asn1"
"github.com/globalsign/certlint/errors"
)
type Linter struct {
e errors.Errors
}
// CheckStruct returns a list of errors based on strict checks on the raw ASN1
// encoding of the input der.
func (l *Linter) CheckStruct(der []byte) *errors.Errors {
l.walk(der)
if l.e.IsError() {
return &l.e
}
return nil
}
// walk is a recursive call that walks over the ASN1 structured data until no
// remaining bytes are left. For each non compound is will call the ASN1 format
// checker.
func (l *Linter) walk(der []byte) {
var err error
var d asn1.RawValue
for len(der) > 0 {
der, err = asn1.Unmarshal(der, &d)
if err != nil {
// Errors should be included in the report, but allow format checking when
// data has been decoded.
l.e.Err(err.Error())
if len(d.Bytes) == 0 {
return
}
}
// A compound is an ASN.1 container that contains other structs.
if d.IsCompound {
l.walk(d.Bytes)
} else {
l.CheckFormat(d)
}
}
}

View File

@ -1,233 +0,0 @@
package asn1
import (
"bytes"
"encoding/asn1"
"regexp"
"strings"
"time"
"unicode"
"unicode/utf8"
)
// RFC 5280 4.1.2.5.1: UTCTime MUST include seconds, even when 00
var formatUTCTime = regexp.MustCompile("^([0-9]{2})([01][0-9])([0-3][0-9])([012][0-9])([0-5][0-9]){2}Z$")
var formatGeneralizedTime = regexp.MustCompile("^([0-9]{4})([01][0-9])([0-3][0-9])([012][0-9])([0-5][0-9]){2}Z$")
// CheckFormat returns a list of formatting errors based on the expected ASN1
// encoding according to the class and tag of the raw value.
// TODO: Create checks for remaining class 0 tags
// TODO: Should we create extensions for other classes, even include class 0?
func (l *Linter) CheckFormat(d asn1.RawValue) {
if d.Class == 0 {
switch d.Tag {
case 0: // "reserved for BER"
case 1: // "BOOLEAN"
case 2: // "INTEGER"
case 3: // "BIT STRING"
case 4: // "OCTET STRING"
case 5: // "NULL"
case 6: // "OBJECT IDENTIFIER"
case 7: // "ObjectDescriptor"
case 8: // "INSTANCE OF, EXTERNAL"
case 9: // "REAL"
case 10: // "ENUMERATED"
case 11: // "EMBEDDED PDV"
case 12: // "UTF8String"
if !utf8.Valid(d.Bytes) {
l.e.Err("Invalid UTF8 encoding in UTF8String")
}
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in UTF8String '%s'", string(d.Bytes))
}
if isControlCharacter(d.Bytes) {
l.e.Err("Control character in UTF8String '%s'", string(d.Bytes))
}
case 13: // "RELATIVE-OID"
case 16: // "SEQUENCE, SEQUENCE OF"
case 17: // "SET, SET OF"
case 18: // "NumericString"
if !isNumericString(d.Bytes) {
l.e.Err("Invalid character in NumericString '%s'", string(d.Bytes))
}
case 19: // "PrintableString"
for _, b := range d.Bytes {
if !isPrintable(b) {
l.e.Err("Invalid character in PrintableString '%s'", string(d.Bytes))
}
}
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in PrintableString '%s'", string(d.Bytes))
}
case 20: // "TeletexString, T61String"
l.e.Warning("Using deprecated TeletexString for '%s'", string(d.Bytes))
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in TeletexString '%s'", string(d.Bytes))
}
if isControlCharacter(d.Bytes) {
l.e.Err("Control character in TeletexString '%s'", string(d.Bytes))
}
case 21: // "VideotexString"
l.e.Warning("Using deprecated VideotexString for '%s'", string(d.Bytes))
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in VideotexString '%s'", string(d.Bytes))
}
if isControlCharacter(d.Bytes) {
l.e.Err("Control character in VideotexString '%s'", string(d.Bytes))
}
case 22: // "IA5String"
if !isIA5String(d.Bytes) {
l.e.Err("Invalid character in IA5String '%s'", string(d.Bytes))
}
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in IA5String '%s'", string(d.Bytes))
}
case 23: // "UTCTime"
// RFC 5280 4.1.2.5: times must be in Z (GMT)
if !bytes.HasSuffix(d.Bytes, []byte{90}) {
l.e.Err("UTCTime not in Zulu/GMT")
}
if !formatUTCTime.Match(d.Bytes) {
l.e.Err("Invalid UTCTime")
}
case 24: // "GeneralizedTime"
var v time.Time
_, err := asn1.Unmarshal(d.FullBytes, &v)
if err != nil {
l.e.Err("Failed to parse Generalized Time: %s", err.Error())
}
// RFC 5280 4.1.2.5: times must be in Z (GMT)
if !bytes.HasSuffix(d.Bytes, []byte{90}) {
l.e.Err("Generalized Time not in Zulu/GMT")
}
// TODO: Can we use binary.BigEndian.Varint(d.Bytes[0:3]), for better performance?
if v.Year() < 2050 {
l.e.Err("Generalized Time before 2050")
}
if !formatGeneralizedTime.Match(d.Bytes) {
l.e.Err("Invalid Generalized Time")
}
case 25: // "GraphicString"
l.e.Warning("Using deprecated GraphicString for '%s'", string(d.Bytes))
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in GraphicString '%s'", string(d.Bytes))
}
if isControlCharacter(d.Bytes) {
l.e.Err("Control character in GraphicString '%s'", string(d.Bytes))
}
case 26: // "VisibleString, ISO646String"
case 27: // "GeneralString"
l.e.Warning("Using deprecated GeneralString for '%s'", string(d.Bytes))
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in GeneralString '%s'", string(d.Bytes))
}
if isControlCharacter(d.Bytes) {
l.e.Err("Control character in GeneralString '%s'", string(d.Bytes))
}
case 28: // "UniversalString"
l.e.Warning("Using deprecated UniversalString for '%s'", string(d.Bytes))
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in UniversalString '%s'", string(d.Bytes))
}
if isControlCharacter(d.Bytes) {
l.e.Err("Control character in UniversalString '%s'", string(d.Bytes))
}
case 29: // "CHARACTER STRING"
case 30: // "BMPString"
l.e.Warning("Using deprecated BMPString for '%s'", string(d.Bytes))
if isForbiddenString(d.Bytes) {
l.e.Err("Forbidden value in BMPString '%s'", string(d.Bytes))
}
if isControlCharacter(d.Bytes) {
l.e.Err("Control character in BMPString '%s'", string(d.Bytes))
}
}
}
}
// Version of isPrintable without allowing a *
// Source: https://golang.org/src/encoding/asn1/asn1.go
func isPrintable(b byte) bool {
return 'a' <= b && b <= 'z' ||
'A' <= b && b <= 'Z' ||
'0' <= b && b <= '9' ||
'\'' <= b && b <= ')' ||
'+' <= b && b <= '/' ||
b == ' ' ||
b == ':' ||
b == '=' ||
b == '?'
}
// Range from: http://www.zytrax.com/tech/ia5.html
func isIA5String(b []byte) bool {
for len(b) > 0 {
r, size := utf8.DecodeRune(b)
if r < 0 || r > 127 {
return false
}
b = b[size:]
}
return true
}
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, and SPACE
func isNumericString(b []byte) bool {
for len(b) > 0 {
r, size := utf8.DecodeRune(b)
if !unicode.IsNumber(r) && !unicode.IsSpace(r) {
return false
}
b = b[size:]
}
return true
}
// The BR state that attributes MUST NOT contain metadata such as '.', '-', ' ',
// this check implements a structure wide validation for values that indication
// that the field is absent, incomplete, or not applicable.
//
// ASCII range of forbidden metadata characters are 32 - 47, 58 -64, 91 - 96,
// 123 - 126, if the value does only contain metadata this value is forbidden.
// This check does also detect double characters or any combination of metadata
// characters.
func isForbiddenString(b []byte) bool {
for len(b) == 0 {
return false
}
switch strings.ToLower(string(b)) {
case "n/a":
return true
}
for len(b) > 0 {
r, size := utf8.DecodeRune(b)
if !((r >= 32 && r <= 47) ||
(r >= 58 && r <= 64) ||
(r >= 91 && r <= 96) ||
(r >= 123 && r <= 126)) {
// non metadata character included in value
return false
}
b = b[size:]
}
return true
}
// isControlCharacter checks if Control characters are included in the given bytes
func isControlCharacter(b []byte) bool {
for len(b) > 0 {
r, size := utf8.DecodeRune(b)
if unicode.IsControl(r) || unicode.Is(unicode.C, r) {
return true
}
b = b[size:]
}
return false
}

View File

@ -1,42 +0,0 @@
package certdata
import (
"crypto/x509"
"fmt"
)
// Data holds the certificate and relevant information
// Type can be DV, OV, EV, PS, CS, EVCS, TS, OCSP, CA
type Data struct {
Cert *x509.Certificate
Issuer *x509.Certificate
Type string
}
// Load raw certificate bytes into a Data struct
func Load(der []byte) (*Data, error) {
var err error
d := new(Data)
d.Cert, err = x509.ParseCertificate(der)
if err != nil {
return nil, err
}
if err = d.setCertificateType(); err != nil {
fmt.Println(err)
}
return d, nil
}
// SetIssuer sets the issuer of a certificate
// TODO: Validate if the correct issuer is given
func (d *Data) SetIssuer(der []byte) error {
var err error
d.Issuer, err = x509.ParseCertificate(der)
if err != nil {
return err
}
return nil
}

View File

@ -1,91 +0,0 @@
package certdata
import "encoding/asn1"
// Source GlobalSign CP and Cabforum BR
// https://www.globalsign.com/en/repository/GlobalSign_CP_v5.3.pdf
var polOidType []oidType
type oidType struct {
ObjectIdentifier asn1.ObjectIdentifier
Type string
}
func getType(oid []asn1.ObjectIdentifier) string {
for _, poid := range oid {
for _, oidt := range polOidType {
if poid.Equal(oidt.ObjectIdentifier) {
return oidt.Type
}
}
}
return ""
}
// TODO: Can we handle this differently, we might want to use a constant here?
func init() {
// Extended Validation
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 1}, "EV"}) // Extended Validation Certificates Policy SSL
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 2}, "CS"}) // Extended Validation Certificates Policy Code Signing
// Domain Validation
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 10}, "DV"}) // Domain Validation Certificates Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 10, 10}, "DV"}) // Domain Validation Certificates Policy AlphaSSL
// Organization Validation
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 20}, "OV"}) // Organization Validation Certificates Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 21}, "-"}) // Untrusted OneClickSSL Test Certificate (not in cp)
// Intranet Validation
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 25}, "IN"}) // IntranetSSL Validation Certificates Policy
// Time Stamping
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 30}, "TS"}) // Time Stamping Certificates Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 31}, "TS"}) // Time Stamping Certificates Policy AATL
// Client Certificates
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 40}, "PS"}) // Client Certificates Policy (Generic)
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 40, 10}, "PS"}) // Client Certificates Policy (ePKI Enterprise PKI)
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 40, 20}, "PS"}) // Client Certificates Policy (JCAN Japan CA Network)
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 40, 30}, "PS"}) // Client Certificates Policy (AATL)
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 40, 40}, "PS"}) // Client Certificates Policy (ePKI for private CAs)
// Code Signing
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 50}, "CS"}) // Code Signing Certificates Policy
// CA Chaining and Cross Signing
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 60}, "CA"}) // CA Chaining Policy Trusted Root and Hosted Root
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 60, 1}, "CA"}) // CA Chaining Policy Trusted Root (Baseline Requirements Compatible)
// Others
/*polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1,3,6,1,4,1,4146,1,80}, "XX"}) // Retail Industry Electronic Data Interchange Client Certificate Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1,3,6,1,4,1,4146,1,81}, "XX"}) // Retail Industry Electronic Data Interchange Server Certificate Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1,3,6,1,4,1,4146,1,90}, "XX"}) // Trusted Root TPM Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1,3,6,1,4,1,4146,1,95}, "XX"}) // Online Certificate Status Protocol Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1,3,6,1,4,1,4146,1,70}, "XX"}) // High Volume CA Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1,3,6,1,4,1,4146,1,26}, "XX"}) // Test Certificate Policy (Should not be trusted)
// In addition to these identifiers, all Certificates that comply with the NAESB Business
// Practice Standards will include one of the following additional identifiers:-
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2,16,840,1,114505,1,12,1,2}, "XX"}) // NAESB Rudimentary Assurance
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2,16,840,1,114505,1,12,2,2}, "XX"}) // NAESB Basic Assurance
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2,16,840,1,114505,1,12,3,2}, "XX"}) // NAESB Medium Assurance
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2,16,840,1,114505,1,12,4,2}, "XX"}) // NAESB High Assurance
*/
// In addition to these identifiers, all Certificates that comply with the Baseline
// Requirements will include the following additional identifiers:-
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2, 23, 140, 1, 1}, "EV"}) // Extended Validation Certificate Policy
//polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2,23,140,1,2}, ""}) // BR Compliance Certificate Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2, 23, 140, 1, 3}, "EVCS"}) // Extended Validation Code Signing Certificates Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2, 23, 140, 1, 4}, "CS"}) // BR Compliance Code Signing Certificates Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1}, "DV"}) // Domain Validation Certificates Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2, 23, 140, 1, 2, 2}, "OV"}) // Organization Validation Certificates Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{2, 23, 140, 1, 2, 3}, "IV"}) // Individual Validation Certificates Policy
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 2, 1}, "PS"}) // Adobe Certificate Policy Attribute Object Identifier (PDF)
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 2, 2}, "PS"}) // Test Adobe Certificate Policy Attribute Object Identifier
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 4146, 1, 40, 30, 2}, "PS"}) // AATL Adobe Certificate Policy Attribute Object Identifier
polOidType = append(polOidType, oidType{asn1.ObjectIdentifier{1, 2, 392, 200063, 30, 5300}, "PS"}) // JCAN
}

View File

@ -1,115 +0,0 @@
package certdata
import (
"crypto/x509"
"encoding/asn1"
"fmt"
"strings"
psl "golang.org/x/net/publicsuffix"
)
// setCertificateType set the base on how we check for other requirements of the
// certificate. It's important that we reliably identify the purpose to apply
// the right checks for that certificate type.
func (d *Data) setCertificateType() error {
// We want to be able to detect 'false' CA certificates, classify as CA
// certificate is basic contains and key usage certsign are set.
if d.Cert.IsCA && d.Cert.KeyUsage&x509.KeyUsageCertSign != 0 {
d.Type = "CA"
return nil
}
// The fallback type is used when a certificate could be any of a range
// but further checks need to define the exact type. When these checks fail
// the fallback type is used.
var fallbackType string
// Based on ExtKeyUsage
for _, ku := range d.Cert.ExtKeyUsage {
switch ku {
case x509.ExtKeyUsageServerAuth:
// Try to determine certificate type via policy oid
d.Type = getType(d.Cert.PolicyIdentifiers)
fallbackType = "DV"
case x509.ExtKeyUsageClientAuth:
fallbackType = "PS"
case x509.ExtKeyUsageEmailProtection:
d.Type = "PS"
case x509.ExtKeyUsageCodeSigning:
d.Type = "CS"
case x509.ExtKeyUsageTimeStamping:
d.Type = "TS"
case x509.ExtKeyUsageOCSPSigning:
d.Type = "OCSP"
}
}
// If we have no kown key usage, try the policy list again
if d.Type == "" {
d.Type = getType(d.Cert.PolicyIdentifiers)
}
// When determined by Policy Identifier we can stop
if d.Type != "" {
return nil
}
// Based on UnknownExtKeyUsage
for _, ku := range d.Cert.UnknownExtKeyUsage {
switch {
case ku.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 21, 19}):
// dsEmailReplication
d.Type = "PS"
return nil
case ku.Equal(asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 8, 2, 2}):
// IPSEC Protection
d.Type = "IPSEC"
return nil
}
}
// Check if the e-mailAddress is set in the DN
for _, n := range d.Cert.Subject.Names {
switch {
case n.Type.Equal(asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}): // e-mailAddress
d.Type = "PS"
return nil
}
}
// An @ sing in the common name is often used in PS.
if strings.Contains(d.Cert.Subject.CommonName, "@") {
d.Type = "PS"
return nil
} else if strings.Contains(d.Cert.Subject.CommonName, " ") {
d.Type = "PS"
return nil
}
// If it's a fqdn, it's a EV, OV or DV
if suffix, _ := psl.PublicSuffix(strings.ToLower(d.Cert.Subject.CommonName)); len(suffix) > 0 {
if len(d.Cert.Subject.Organization) > 0 {
if len(d.Cert.Subject.SerialNumber) > 0 {
d.Type = "EV"
return nil
}
d.Type = "OV"
return nil
}
d.Type = "DV"
return nil
}
if len(fallbackType) > 0 {
d.Type = fallbackType
return nil
}
if d.Type == "" {
return fmt.Errorf("Could not determine certificate type")
}
return nil
}

View File

@ -1,42 +0,0 @@
package checks
import (
"sync"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/errors"
)
var certMutex = &sync.Mutex{}
type certificate []certificateCheck
type certificateCheck struct {
name string
filter *Filter
f func(*certdata.Data) *errors.Errors
}
// Certificate contains all imported certificate checks
var Certificate certificate
// RegisterCertificateCheck adds a new check to Cerificates
func RegisterCertificateCheck(name string, filter *Filter, f func(*certdata.Data) *errors.Errors) {
certMutex.Lock()
Certificate = append(Certificate, certificateCheck{name, filter, f})
certMutex.Unlock()
}
// Check runs all the registered certificate checks
func (c certificate) Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
for _, cc := range c {
if cc.filter != nil && !cc.filter.Check(d) {
continue
}
e.Append(cc.f(d))
}
return e
}

View File

@ -1,56 +0,0 @@
package aiaissuers
import (
"net/url"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Authority Info Access Issuers Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// OCSP signing certificates should not any Authority Info Access Issuers
if d.Type == "OCSP" {
if len(d.Cert.IssuingCertificateURL) > 0 {
e.Warning("OCSP signing certificate contains any Authority Info Access Issuers")
}
// no extra checks needed
return e
}
// Self signed CA certificates should not contain any AIA Issuers
if d.Type == "CA" && d.Cert.CheckSignatureFrom(d.Cert) == nil {
if len(d.Cert.IssuingCertificateURL) != 0 {
e.Warning("Self signed CA certificates should not contain any Authority Info Access Issuers")
}
return e
}
// Other certificates should contain at least one Authority Info Access Issuer
if len(d.Cert.IssuingCertificateURL) == 0 {
e.Err("Certificate contains no Authority Info Access Issuers")
return e
}
for _, icu := range d.Cert.IssuingCertificateURL {
l, err := url.Parse(icu)
if err != nil {
e.Err("Certificate contains an invalid Authority Info Access Issuer URL (%s)", icu)
}
if l.Scheme != "http" {
e.Warning("Certificate contains a Authority Info Access Issuer with an non-preferred scheme (%s)", l.Scheme)
}
}
return e
}

View File

@ -1,22 +0,0 @@
package all
import (
// Import all default checks
_ "github.com/globalsign/certlint/checks/certificate/aiaissuers"
_ "github.com/globalsign/certlint/checks/certificate/basicconstraints"
_ "github.com/globalsign/certlint/checks/certificate/extensions"
_ "github.com/globalsign/certlint/checks/certificate/extkeyusage"
_ "github.com/globalsign/certlint/checks/certificate/internal"
_ "github.com/globalsign/certlint/checks/certificate/issuerdn"
_ "github.com/globalsign/certlint/checks/certificate/keyusage"
_ "github.com/globalsign/certlint/checks/certificate/publickey"
_ "github.com/globalsign/certlint/checks/certificate/publicsuffix"
_ "github.com/globalsign/certlint/checks/certificate/revocation"
_ "github.com/globalsign/certlint/checks/certificate/serialnumber"
_ "github.com/globalsign/certlint/checks/certificate/signaturealgorithm"
_ "github.com/globalsign/certlint/checks/certificate/subject"
_ "github.com/globalsign/certlint/checks/certificate/subjectaltname"
_ "github.com/globalsign/certlint/checks/certificate/validity"
_ "github.com/globalsign/certlint/checks/certificate/version"
_ "github.com/globalsign/certlint/checks/certificate/wildcard"
)

View File

@ -1,33 +0,0 @@
package basicconstraints
import (
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Basic Constraints Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
switch d.Type {
case "DV", "OV", "EV":
if d.Cert.IsCA {
e.Err("Certificate has set CA true")
}
if d.Cert.MaxPathLen == 0 && d.Cert.MaxPathLenZero {
//e.Err("Certificate has set CA true")
}
if d.Cert.BasicConstraintsValid {
//e.Err("Certificate has set CA true")
}
}
return e
}

View File

@ -1,23 +0,0 @@
package extensions
import (
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Extensions Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
for _, ext := range d.Cert.Extensions {
// Check for any imported extensions and run all matching
e.Append(checks.Extensions.Check(ext, d))
}
return e
}

View File

@ -1,56 +0,0 @@
package extkeyusage
import (
"crypto/x509"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Extended Key Usage Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check verifies if the the required/allowed extended keyusages
// are set in relation to the certificate type.
//
// https://tools.ietf.org/html/rfc5280#section-4.2.1.12
//
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if len(d.Cert.ExtKeyUsage) == 0 && len(d.Cert.UnknownExtKeyUsage) == 0 {
e.Err("Certificate contains no extended key usage")
return e
}
for _, ku := range d.Cert.ExtKeyUsage {
switch d.Type {
case "DV", "OV", "EV":
if ku != x509.ExtKeyUsageServerAuth && ku != x509.ExtKeyUsageClientAuth && ku != x509.ExtKeyUsageMicrosoftServerGatedCrypto {
e.Err("Certificate contains an extended key usage different from ServerAuth, ClientAuth or ServerGatedCrypto")
return e
}
case "PS":
if ku != x509.ExtKeyUsageClientAuth && ku != x509.ExtKeyUsageEmailProtection {
e.Err("Certificate contains an extended key usage different from ClientAuth or EmailProtection")
return e
}
case "CS":
if ku != x509.ExtKeyUsageCodeSigning {
e.Err("Certificate contains an extended key usage different from ClientAuth or EmailProtection")
return e
}
}
}
if len(d.Cert.UnknownExtKeyUsage) > 0 {
// encryptedFileSystem 1.3.6.1.4.1.311.10.3.4
//return fmt.Errorf("%s Certificate contains an unknown extented key usage", d.Type)
}
return e
}

View File

@ -1,23 +0,0 @@
package internal
import (
"net"
"strings"
psl "golang.org/x/net/publicsuffix"
)
// All official domain suffixes are registered by icann, but because some
// subdomains are not only check against the last part of the fqdn.
func checkInternalName(fqdn string) bool {
if ip := net.ParseIP(fqdn); ip != nil {
return checkInternalIP(ip)
}
suffix := strings.Split(strings.ToLower(fqdn), ".")
_, icann := psl.PublicSuffix(suffix[len(suffix)-1])
if icann {
return false
}
return true
}

View File

@ -1,43 +0,0 @@
package internal
import (
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Internal Names and IP addresses Check"
func init() {
filter := &checks.Filter{
Type: []string{"DV", "OV", "IV", "EV"},
}
checks.RegisterCertificateCheck(checkName, filter, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
// TODO: Add more checks https://golang.org/src/crypto/x509/x509.go?s=15439:18344#L1157
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if checkInternalName(d.Cert.Subject.CommonName) {
e.Err("Certificate contains an internal server name in the common name '%s'", d.Cert.Subject.CommonName)
}
for _, n := range d.Cert.DNSNames {
if checkInternalName(n) {
e.Err("Certificate subjectAltName '%s' contains an internal server name", n)
}
}
// Check for internal IP addresses
for _, ip := range d.Cert.IPAddresses {
if !ip.IsGlobalUnicast() {
e.Err("Certificate subjectAltName '%v' contains a non global unicast IP address", ip)
}
if checkInternalIP(ip) {
e.Err("Certificate subjectAltName '%v' contains a private or local IP address", ip)
}
}
return e
}

View File

@ -1,32 +0,0 @@
package internal
import "net"
// checkInternalIP verifies is an IP address in a registered internal range.
// TODO: Check if we need to verify any IPv6 ranges
// TODO: We should also check for special purpose IP ranges, we might want to do that in a specific function
func checkInternalIP(ip net.IP) bool {
var privIPSpace []net.IPNet
// 10.0.0.0/8
privIPSpace = append(privIPSpace, net.IPNet{
IP: net.IP{0xa, 0x0, 0x0, 0x0},
Mask: net.IPMask{0xff, 0x0, 0x0, 0x0},
})
// 172.16.0.0/12"
privIPSpace = append(privIPSpace, net.IPNet{
IP: net.IP{0xac, 0x10, 0x0, 0x0},
Mask: net.IPMask{0xff, 0xf0, 0x0, 0x0},
})
// 192.168.0.0/16
privIPSpace = append(privIPSpace, net.IPNet{
IP: net.IP{0xc0, 0xa8, 0x0, 0x0},
Mask: net.IPMask{0xff, 0xff, 0x0, 0x0},
})
for _, ipSpace := range privIPSpace {
if ipSpace.Contains(ip) {
return true
}
}
return false
}

View File

@ -1,27 +0,0 @@
package version
import (
"bytes"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Issuer DN Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if d.Issuer != nil && !bytes.Equal(d.Cert.RawIssuer, d.Issuer.RawSubject) {
e.Err("Certificate Issuer Distinguished Name field MUST match the Subject DN of the Issuing CA")
return e
}
return e
}

View File

@ -1,83 +0,0 @@
package keyusage
import (
"crypto/dsa"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Key Usage Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
// checkKeyUsageExtension verifies if the the required/allowed keyusages are set
//
// https://tools.ietf.org/html/rfc5280#section-4.2.1.3
//
// TODO: Check if we can or need to do something with dh.PublicKey
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
var forbidden []x509.KeyUsage
// Source
// https://github.com/awslabs/certlint/blob/master/lib/certlint/extensions/keyusage.rb
switch d.Cert.PublicKey.(type) {
case *rsa.PublicKey:
forbidden = []x509.KeyUsage{
x509.KeyUsageKeyAgreement,
x509.KeyUsageEncipherOnly,
x509.KeyUsageDecipherOnly,
}
case *ecdsa.PublicKey:
forbidden = []x509.KeyUsage{
x509.KeyUsageKeyEncipherment,
x509.KeyUsageDataEncipherment,
}
case *dsa.PublicKey:
forbidden = []x509.KeyUsage{
x509.KeyUsageKeyEncipherment,
x509.KeyUsageDataEncipherment,
x509.KeyUsageKeyAgreement,
x509.KeyUsageEncipherOnly,
x509.KeyUsageDecipherOnly,
}
// case *dh.PublicKey:
// forbidden = []x509.KeyUsage{
// x509.KeyUsageDigitalSignature,
// x509.KeyUsageContentCommitment,
// x509.KeyUsageKeyEncipherment,
// x509.KeyUsageDataEncipherment,
// x509.KeyUsageCertSign,
// x509.KeyUsageCRLSign,
// }
}
// If we have not defined this certificate as a CA certificate, the following
// key ussages would not be allowed
if d.Type != "CA" {
if d.Cert.KeyUsage == 0 {
e.Err("Certificate has no key usage set")
return e
}
forbidden = append(forbidden, x509.KeyUsageCertSign)
forbidden = append(forbidden, x509.KeyUsageCRLSign)
}
// Check if there are any forbidden key usages set
for _, fku := range forbidden {
if d.Cert.KeyUsage&fku != 0 {
e.Err("Certificate has key usage %s set", keyUsageString(fku))
}
}
return e
}

View File

@ -1,28 +0,0 @@
package keyusage
import "crypto/x509"
// keyUsageString returns the name of the keyusage as string
func keyUsageString(ku x509.KeyUsage) string {
switch ku {
case x509.KeyUsageDigitalSignature:
return "DigitalSignature"
case x509.KeyUsageContentCommitment:
return "ContentCommitment"
case x509.KeyUsageKeyEncipherment:
return "KeyEncipherment"
case x509.KeyUsageDataEncipherment:
return "DataEncipherment"
case x509.KeyUsageKeyAgreement:
return "KeyAgreement"
case x509.KeyUsageCertSign:
return "CertSign"
case x509.KeyUsageCRLSign:
return "CRLSign"
case x509.KeyUsageEncipherOnly:
return "EncipherOnly"
case x509.KeyUsageDecipherOnly:
return "DecipherOnly"
}
return "Unknown"
}

View File

@ -1,375 +0,0 @@
Copyright 2016 ISRG. All rights reserved.
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

View File

@ -1,246 +0,0 @@
// Package goodkey copied from "github.com/letsencrypt/boulder/goodkey"
//
// This package is vovered under the Mozilla Public License Version 2.0
//
// Removed depency on letsencrypt core and allow key size above 4096
package goodkey
import (
"crypto"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
"fmt"
"math/big"
"reflect"
"sync"
)
// To generate, run: primes 2 752 | tr '\n' ,
var smallPrimeInts = []int64{
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47,
53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167,
173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359,
367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491,
499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571,
577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641,
643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709,
719, 727, 733, 739, 743, 751,
}
// singleton defines the object of a Singleton pattern
var (
smallPrimesSingleton sync.Once
smallPrimes []*big.Int
)
// KeyPolicy determines which types of key may be used with various boulder
// operations.
type KeyPolicy struct {
AllowRSA bool // Whether RSA keys should be allowed.
AllowECDSANISTP256 bool // Whether ECDSA NISTP256 keys should be allowed.
AllowECDSANISTP384 bool // Whether ECDSA NISTP384 keys should be allowed.
}
// NewKeyPolicy returns a KeyPolicy that allows RSA, ECDSA256 and ECDSA384.
func NewKeyPolicy() KeyPolicy {
return KeyPolicy{
AllowRSA: true,
AllowECDSANISTP256: true,
AllowECDSANISTP384: true,
}
}
// GoodKey returns true if the key is acceptable for both TLS use and account
// key use (our requirements are the same for either one), according to basic
// strength and algorithm checking.
// TODO: Support JsonWebKeys once go-jose migration is done.
func (policy *KeyPolicy) GoodKey(key crypto.PublicKey) error {
switch t := key.(type) {
case rsa.PublicKey:
return policy.goodKeyRSA(t)
case *rsa.PublicKey:
return policy.goodKeyRSA(*t)
case ecdsa.PublicKey:
return policy.goodKeyECDSA(t)
case *ecdsa.PublicKey:
return policy.goodKeyECDSA(*t)
default:
return fmt.Errorf("Unknown key type %s", reflect.TypeOf(key))
}
}
// GoodKeyECDSA determines if an ECDSA pubkey meets our requirements
func (policy *KeyPolicy) goodKeyECDSA(key ecdsa.PublicKey) (err error) {
// Check the curve.
//
// The validity of the curve is an assumption for all following tests.
err = policy.goodCurve(key.Curve)
if err != nil {
return err
}
// Key validation routine adapted from NIST SP800-56A § 5.6.2.3.2.
// <http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf>
//
// Assuming a prime field since a) we are only allowing such curves and b)
// crypto/elliptic only supports prime curves. Where this assumption
// simplifies the code below, it is explicitly stated and explained. If ever
// adapting this code to support non-prime curves, refer to NIST SP800-56A §
// 5.6.2.3.2 and adapt this code appropriately.
params := key.Params()
// SP800-56A § 5.6.2.3.2 Step 1.
// Partial check of the public key for an invalid range in the EC group:
// Verify that key is not the point at infinity O.
// This code assumes that the point at infinity is (0,0), which is the
// case for all supported curves.
if isPointAtInfinityNISTP(key.X, key.Y) {
return fmt.Errorf("Key x, y must not be the point at infinity")
}
// SP800-56A § 5.6.2.3.2 Step 2.
// "Verify that x_Q and y_Q are integers in the interval [0,p-1] in the
// case that q is an odd prime p, or that x_Q and y_Q are bit strings
// of length m bits in the case that q = 2**m."
//
// Prove prime field: ASSUMED.
// Prove q != 2: ASSUMED. (Curve parameter. No supported curve has q == 2.)
// Prime field && q != 2 => q is an odd prime p
// Therefore "verify that x, y are in [0, p-1]" satisfies step 2.
//
// Therefore verify that both x and y of the public key point have the unique
// correct representation of an element in the underlying field by verifying
// that x and y are integers in [0, p-1].
if key.X.Sign() < 0 || key.Y.Sign() < 0 {
return fmt.Errorf("Key x, y must not be negative")
}
if key.X.Cmp(params.P) >= 0 || key.Y.Cmp(params.P) >= 0 {
return fmt.Errorf("Key x, y must not exceed P-1")
}
// SP800-56A § 5.6.2.3.2 Step 3.
// "If q is an odd prime p, verify that (y_Q)**2 === (x_Q)***3 + a*x_Q + b (mod p).
// If q = 2**m, verify that (y_Q)**2 + (x_Q)*(y_Q) == (x_Q)**3 + a*(x_Q)*2 + b in
// the finite field of size 2**m.
// (Ensures that the public key is on the correct elliptic curve.)"
//
// q is an odd prime p: proven/assumed above.
// a = -3 for all supported curves.
//
// Therefore step 3 is satisfied simply by showing that
// y**2 === x**3 - 3*x + B (mod P).
//
// This proves that the public key is on the correct elliptic curve.
// But in practice, this test is provided by crypto/elliptic, so use that.
if !key.Curve.IsOnCurve(key.X, key.Y) {
return fmt.Errorf("Key point is not on the curve")
}
// SP800-56A § 5.6.2.3.2 Step 4.
// "Verify that n*Q == O.
// (Ensures that the public key has the correct order. Along with check 1,
// ensures that the public key is in the correct range in the correct EC
// subgroup, that is, it is in the correct EC subgroup and is not the
// identity element.)"
//
// Ensure that public key has the correct order:
// verify that n*Q = O.
//
// n*Q = O iff n*Q is the point at infinity (see step 1).
ox, oy := key.Curve.ScalarMult(key.X, key.Y, params.N.Bytes())
if !isPointAtInfinityNISTP(ox, oy) {
return fmt.Errorf("Public key does not have correct order")
}
// End of SP800-56A § 5.6.2.3.2 Public Key Validation Routine.
// Key is valid.
return nil
}
// Returns true iff the point (x,y) on NIST P-256, NIST P-384 or NIST P-521 is
// the point at infinity. These curves all have the same point at infinity
// (0,0). This function must ONLY be used on points on curves verified to have
// (0,0) as their point at infinity.
func isPointAtInfinityNISTP(x, y *big.Int) bool {
return x.Sign() == 0 && y.Sign() == 0
}
// GoodCurve determines if an elliptic curve meets our requirements.
func (policy *KeyPolicy) goodCurve(c elliptic.Curve) (err error) {
// Simply use a whitelist for now.
params := c.Params()
switch {
case policy.AllowECDSANISTP256 && params == elliptic.P256().Params():
return nil
case policy.AllowECDSANISTP384 && params == elliptic.P384().Params():
return nil
default:
return fmt.Errorf(fmt.Sprintf("ECDSA curve %v not allowed", params.Name))
}
}
// GoodKeyRSA determines if a RSA pubkey meets our requirements
func (policy *KeyPolicy) goodKeyRSA(key rsa.PublicKey) (err error) {
if !policy.AllowRSA {
return fmt.Errorf("RSA keys are not allowed")
}
// Baseline Requirements Appendix A
// Modulus must be >= 2048 bits
// Removed max keySize from original package version
modulus := key.N
modulusBitLen := modulus.BitLen()
if modulusBitLen < 2048 {
return fmt.Errorf(fmt.Sprintf("Key too small: %d", modulusBitLen))
}
// Bit lengths that are not a multiple of 8 may cause problems on some
// client implementations.
if modulusBitLen%8 != 0 {
return fmt.Errorf(fmt.Sprintf("Key length wasn't a multiple of 8: %d", modulusBitLen))
}
// The CA SHALL confirm that the value of the public exponent is an
// odd number equal to 3 or more. Additionally, the public exponent
// SHOULD be in the range between 2^16 + 1 and 2^256-1.
// NOTE: rsa.PublicKey cannot represent an exponent part greater than
// 2^32 - 1 or 2^64 - 1, because it stores E as an integer. So we
// don't need to check the upper bound.
if (key.E%2) == 0 || key.E < ((1<<16)+1) {
return fmt.Errorf(fmt.Sprintf("Key exponent should be odd and >2^16: %d", key.E))
}
// The modulus SHOULD also have the following characteristics: an odd
// number, not the power of a prime, and have no factors smaller than 752.
// TODO: We don't yet check for "power of a prime."
if checkSmallPrimes(modulus) {
return fmt.Errorf("Key divisible by small prime")
}
return nil
}
// Returns true iff integer i is divisible by any of the primes in smallPrimes.
//
// Short circuits; execution time is dependent on i. Do not use this on secret
// values.
func checkSmallPrimes(i *big.Int) bool {
smallPrimesSingleton.Do(func() {
for _, prime := range smallPrimeInts {
smallPrimes = append(smallPrimes, big.NewInt(prime))
}
})
for _, prime := range smallPrimes {
var result big.Int
result.Mod(i, prime)
if result.Sign() == 0 {
return true
}
}
return false
}

View File

@ -1,30 +0,0 @@
package publickey
import (
"strings"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/checks/certificate/publickey/goodkey"
"github.com/globalsign/certlint/errors"
)
const checkName = "Public Key Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
gkp := goodkey.NewKeyPolicy()
err := gkp.GoodKey(d.Cert.PublicKey)
if err != nil {
e.Err("Certificate %s", strings.ToLower(err.Error()))
return e
}
return e
}

View File

@ -1,48 +0,0 @@
package publicsuffix
import (
"fmt"
"strings"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
psl "golang.org/x/net/publicsuffix"
)
const checkName = "Public Suffix (xTLD) Check"
func init() {
filter := &checks.Filter{
Type: []string{"DV", "OV", "IV", "EV"},
}
checks.RegisterCertificateCheck(checkName, filter, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if len(d.Cert.Subject.CommonName) > 0 {
suffix, icann := psl.PublicSuffix(strings.ToLower(d.Cert.Subject.CommonName))
if fmt.Sprintf("*.%s", suffix) == d.Cert.Subject.CommonName || suffix == d.Cert.Subject.CommonName {
// if there is a dot on the suffix, it must be on the psl
if icann || strings.Count(suffix, ".") > 0 {
e.Err("Certificate CommonName %q equals %q from the public suffix list", d.Cert.Subject.CommonName, suffix)
}
}
}
for _, n := range d.Cert.DNSNames {
suffix, icann := psl.PublicSuffix(strings.ToLower(n))
if fmt.Sprintf("*.%s", suffix) == n || suffix == n {
// if there is a dot on the suffix, it must be on the psl
if icann || strings.Count(suffix, ".") > 0 {
e.Err("Certificate subjectAltName %q equals %q from the public suffix list", n, suffix)
}
}
}
return e
}

View File

@ -1,65 +0,0 @@
package revocation
import (
"net/url"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Certificate Revocation Information Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// OCSP signing certificates should not contain an OCSP server
if d.Type == "OCSP" {
if len(d.Cert.OCSPServer) > 0 {
e.Warning("OCSP signing certificate contains an OCSP server")
}
// no extra checks needed
return e
}
// Self signed CA certificates should not contain any revocation sources
if d.Type == "CA" && d.Cert.CheckSignatureFrom(d.Cert) == nil {
if len(d.Cert.CRLDistributionPoints) != 0 && len(d.Cert.OCSPServer) != 0 {
e.Warning("Self signed CA certificates should not contain any revocation sources")
}
return e
}
if len(d.Cert.CRLDistributionPoints) == 0 && len(d.Cert.OCSPServer) == 0 {
e.Err("Certificate contains no CRL or OCSP server")
return e
}
// Check CRL information
for _, crl := range d.Cert.CRLDistributionPoints {
l, err := url.Parse(crl)
if err != nil {
e.Err("Certificate contains an invalid CRL (%s)", crl)
} else if l.Scheme != "http" {
e.Err("Certificate contains a CRL with an non-preferred scheme (%s)", l.Scheme)
}
}
// Check OCSP information
for _, server := range d.Cert.OCSPServer {
s, err := url.Parse(server)
if err != nil {
e.Err("Certificate contains an invalid OCSP server (%s)", s)
} else if s.Scheme != "http" {
e.Err("Certificate contains a OCSP server with an non-preferred scheme (%s)", s.Scheme)
}
}
return e
}

View File

@ -1,44 +0,0 @@
package serialnumber
import (
"math/big"
"time"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Certificate Serial Number Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if d.Cert.SerialNumber.Cmp(big.NewInt(0)) == -1 {
e.Err("Certificate serial number MUST be a positive integer (%d)", d.Cert.SerialNumber)
}
// Remaining checks are not relevant for CA certificates
if d.Cert.IsCA {
return e
}
// https://cabforum.org/2016/07/08/ballot-164/
if d.Cert.NotBefore.After(time.Date(2016, 9, 30, 0, 0, 0, 0, time.UTC)) {
if d.Cert.SerialNumber.BitLen() < 64 {
e.Err("Certificate serial number should be 64 bits but contains %d bits", d.Cert.SerialNumber.BitLen())
}
} else {
// all new end-entity certificates must contain at least 20 bits of unpredictable random data (preferably in the serial number).
if d.Cert.SerialNumber.BitLen() < 20 {
e.Warning("Certificate serial number must contain at least 20 bits of unpredictable random data, found only %d bits", d.Cert.SerialNumber.BitLen())
}
}
return nil
}

View File

@ -1,44 +0,0 @@
package signaturealgorithm
import (
"crypto/x509"
"time"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Signature Algorithm Check"
func init() {
filter := &checks.Filter{
Type: []string{"DV", "OV", "IV", "EV"},
}
checks.RegisterCertificateCheck(checkName, filter, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// Check if we use SHA1 or less (MD5, MD2)
if d.Cert.SignatureAlgorithm > x509.SHA1WithRSA &&
d.Cert.SignatureAlgorithm != x509.DSAWithSHA1 &&
d.Cert.SignatureAlgorithm != x509.ECDSAWithSHA1 {
return e
}
if d.Cert.NotBefore.After(time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)) {
e.Err("Certificate is using SHA1, but is issued on/after 1 Jan 2016")
return e
}
if d.Cert.NotBefore.After(time.Date(2015, 1, 16, 0, 0, 0, 0, time.UTC)) &&
d.Cert.NotAfter.After(time.Date(2017, 1, 1, 0, 0, 0, 0, time.UTC)) {
e.Err("Certificate is using SHA1, but is still valid on/after 1 Jan 2017")
return e
}
return nil
}

View File

@ -1,90 +0,0 @@
package subject
import (
"encoding/asn1"
"fmt"
)
// Max field length:
// https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2001/UpperBounds.html
type object struct {
oid asn1.ObjectIdentifier
maxLength int
}
func (o *object) Equal(oid asn1.ObjectIdentifier) bool {
return o.oid.Equal(oid)
}
func (o *object) Valid(v interface{}) error {
if o.maxLength > 0 && len([]rune(v.(string))) > o.maxLength {
return fmt.Errorf("exceeding max length of %d", o.maxLength)
}
return nil
}
// http://www.alvestrand.no/objectid/2.5.4.html
var (
objectClass = object{asn1.ObjectIdentifier{2, 5, 4, 0}, 0}
aliasedEntryName = object{asn1.ObjectIdentifier{2, 5, 4, 1}, 0}
knowldgeinformation = object{asn1.ObjectIdentifier{2, 5, 4, 2}, 0}
commonName = object{asn1.ObjectIdentifier{2, 5, 4, 3}, 64}
surname = object{asn1.ObjectIdentifier{2, 5, 4, 4}, 40}
serialNumber = object{asn1.ObjectIdentifier{2, 5, 4, 5}, 64}
countryName = object{asn1.ObjectIdentifier{2, 5, 4, 6}, 2}
localityName = object{asn1.ObjectIdentifier{2, 5, 4, 7}, 128}
stateOrProvinceName = object{asn1.ObjectIdentifier{2, 5, 4, 8}, 128}
streetAddress = object{asn1.ObjectIdentifier{2, 5, 4, 9}, 128}
organizationName = object{asn1.ObjectIdentifier{2, 5, 4, 10}, 64}
organizationalUnitName = object{asn1.ObjectIdentifier{2, 5, 4, 11}, 64}
title = object{asn1.ObjectIdentifier{2, 5, 4, 12}, 64}
description = object{asn1.ObjectIdentifier{2, 5, 4, 13}, 1024}
searchGuide = object{asn1.ObjectIdentifier{2, 5, 4, 14}, 32768}
businessCategory = object{asn1.ObjectIdentifier{2, 5, 4, 15}, 128}
postalAddress = object{asn1.ObjectIdentifier{2, 5, 4, 16}, 128}
postalCode = object{asn1.ObjectIdentifier{2, 5, 4, 17}, 40}
postOfficeBox = object{asn1.ObjectIdentifier{2, 5, 4, 18}, 40}
physicalDeliveryOfficeName = object{asn1.ObjectIdentifier{2, 5, 4, 19}, 128}
telephoneNumber = object{asn1.ObjectIdentifier{2, 5, 4, 20}, 32}
telexNumber = object{asn1.ObjectIdentifier{2, 5, 4, 21}, 14}
teletexTerminalIdentifier = object{asn1.ObjectIdentifier{2, 5, 4, 22}, 1024}
facsimileTelephoneNumber = object{asn1.ObjectIdentifier{2, 5, 4, 23}, 32}
x121Address = object{asn1.ObjectIdentifier{2, 5, 4, 24}, 15}
internationalISDNNumber = object{asn1.ObjectIdentifier{2, 5, 4, 25}, 16}
registeredAddress = object{asn1.ObjectIdentifier{2, 5, 4, 26}, 128}
destinationIndicator = object{asn1.ObjectIdentifier{2, 5, 4, 27}, 128}
preferredDeliveryMethod = object{asn1.ObjectIdentifier{2, 5, 4, 28}, 0}
presentationAddress = object{asn1.ObjectIdentifier{2, 5, 4, 29}, 0}
supportedApplicationContext = object{asn1.ObjectIdentifier{2, 5, 4, 30}, 0}
member = object{asn1.ObjectIdentifier{2, 5, 4, 31}, 0}
owner = object{asn1.ObjectIdentifier{2, 5, 4, 32}, 0}
roleOccupant = object{asn1.ObjectIdentifier{2, 5, 4, 33}, 0}
seeAlso = object{asn1.ObjectIdentifier{2, 5, 4, 34}, 0}
userPassword = object{asn1.ObjectIdentifier{2, 5, 4, 35}, 128}
userCertificate = object{asn1.ObjectIdentifier{2, 5, 4, 36}, 0}
cACertificate = object{asn1.ObjectIdentifier{2, 5, 4, 37}, 0}
authorityRevocationList = object{asn1.ObjectIdentifier{2, 5, 4, 38}, 0}
certificateRevocationList = object{asn1.ObjectIdentifier{2, 5, 4, 39}, 0}
crossCertificatePair = object{asn1.ObjectIdentifier{2, 5, 4, 40}, 0}
name = object{asn1.ObjectIdentifier{2, 5, 4, 41}, 128}
givenName = object{asn1.ObjectIdentifier{2, 5, 4, 42}, 128}
initials = object{asn1.ObjectIdentifier{2, 5, 4, 43}, 0}
generationQualifier = object{asn1.ObjectIdentifier{2, 5, 4, 44}, 0}
uniqueIdentifier = object{asn1.ObjectIdentifier{2, 5, 4, 45}, 0}
dnQualifier = object{asn1.ObjectIdentifier{2, 5, 4, 46}, 0}
enhancedSearchGuide = object{asn1.ObjectIdentifier{2, 5, 4, 47}, 0}
protocolInformation = object{asn1.ObjectIdentifier{2, 5, 4, 48}, 0}
distinguishedName = object{asn1.ObjectIdentifier{2, 5, 4, 49}, 0}
uniqueMember = object{asn1.ObjectIdentifier{2, 5, 4, 50}, 0}
houseIdentifier = object{asn1.ObjectIdentifier{2, 5, 4, 51}, 0}
supportedAlgorithms = object{asn1.ObjectIdentifier{2, 5, 4, 52}, 0}
deltaRevocationList = object{asn1.ObjectIdentifier{2, 5, 4, 53}, 0}
attributeCertificate = object{asn1.ObjectIdentifier{2, 5, 4, 58}, 0}
pseudonym = object{asn1.ObjectIdentifier{2, 5, 4, 65}, 0}
emailAddress = object{asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 1}, 255}
jurisdictionLocalityName = object{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 1}, 128}
jurisdictionStateOrProvinceName = object{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 2}, 128}
jurisdictionCountryName = object{asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 3}, 2}
)

View File

@ -1,225 +0,0 @@
package subject
import (
"crypto/x509/pkix"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Subject Check"
func init() {
filter := &checks.Filter{
//Type: []string{"DV", "OV", "IV", "EV"},
}
checks.RegisterCertificateCheck(checkName, filter, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
return checkDN(d.Type, d.Cert.Subject.Names)
}
// Subject Distinguished Name Fields
func checkDN(vetting string, dn []pkix.AttributeTypeAndValue) *errors.Errors {
var e = errors.New(nil)
// DNS must not be empty
if len(dn) == 0 {
e.Err("Distinguished Name contains no values")
return e
}
// OV & EV requirements
if vetting == "OV" || vetting == "EV" {
if !inDN(dn, organizationName) {
e.Err("organizationName is required for %s certificates", vetting)
}
}
// EV specific requirements
if vetting == "EV" {
if !inDN(dn, localityName) {
e.Err("localityName is required for %s certificates", vetting)
}
if !inDN(dn, businessCategory) {
e.Err("businessCategory is required for %s certificates", vetting)
}
if !inDN(dn, jurisdictionCountryName) {
e.Err("jurisdictionCountryName is required for %s certificates", vetting)
}
if !inDN(dn, serialNumber) {
e.Err("serialNumber is required for %s certificates", vetting)
}
}
// Field related requirements
//
// Max field length:
// https://www.itu.int/ITU-T/formal-language/itu-t/x/x520/2001/UpperBounds.html
for _, n := range dn {
switch {
// commonName
// If present, this field MUST contain a single IP address or FullyQualified Domain Name
case commonName.Equal(n.Type):
// report deprecated common name field as info until not commenly used/accepted
e.Info("commonName field is deprecated")
// check if value is exceeding max length
if err := commonName.Valid(n.Value); err != nil {
e.Err("commonName %s", err.Error())
}
case emailAddress.Equal(n.Type):
// report deprecated email address field as info until not commenly used/accepted
e.Info("emailAddress field is deprecated")
// RFC5280: ub-emailaddress-length was changed from 128 to 255 in order to
// align with PKCS #9 [RFC2985].
if err := emailAddress.Valid(n.Value); err != nil {
e.Err("emailAddress %s", err.Error())
}
// surname
// A Certificate containing a givenName field or surname field MUST contain
// the (2.23.140.1.2.3) Certificate Policy OID.
case surname.Equal(n.Type):
// Prohibited
if !inDN(dn, givenName) {
e.Err("surname may only set in combination with givenName")
}
// Require field if surname is set
if !inDN(dn, localityName) && !inDN(dn, stateOrProvinceName) {
e.Err("localityName or stateOrProvinceName is required if surname is set")
}
// ub-surname-length INTEGER ::= 40
if err := surname.Valid(n.Value); err != nil {
e.Err("surname %s", err.Error())
}
// countryName
case countryName.Equal(n.Type):
// TODO: Check against the values in ISO 31661
if len(n.Value.(string)) != 2 {
e.Err("countryName MUST contain the two-letter ISO 3166-1 country code")
}
// jurisdictionCountryName
case jurisdictionCountryName.Equal(n.Type):
// TODO: Check against the values in ISO 31661
if len(n.Value.(string)) != 2 {
e.Err("jurisdictionCountryName MUST contain the two-letter ISO 3166-1 country code")
}
// localityName
case localityName.Equal(n.Type):
// Prohibited
if !inDN(dn, organizationName) && !(inDN(dn, givenName) && inDN(dn, surname)) {
e.Err("localityName is not allowed without organizationName or givenName and surname")
}
if err := localityName.Valid(n.Value); err != nil {
e.Err("localityName %s", err.Error())
}
// stateOrProvinceName
case stateOrProvinceName.Equal(n.Type):
// Prohibited
if !inDN(dn, organizationName) && !(inDN(dn, givenName) && inDN(dn, surname)) {
e.Err("stateOrProvinceName is not allowed without organizationName or givenName and surname")
}
if err := stateOrProvinceName.Valid(n.Value); err != nil {
e.Err("stateOrProvinceName %s", err.Error())
}
// streetAddress
case streetAddress.Equal(n.Type):
// Prohibited
if !inDN(dn, organizationName) && !(inDN(dn, givenName) && inDN(dn, surname)) {
e.Err("streetAddress is not allowed without organizationName or givenName and surname")
}
if err := streetAddress.Valid(n.Value); err != nil {
e.Err("streetAddress %s", err.Error())
}
// postalCode
case postalCode.Equal(n.Type):
// Prohibited
if !inDN(dn, organizationName) && !(inDN(dn, givenName) && inDN(dn, surname)) {
e.Err("postalCode is not allowed without organizationName or givenName and surname")
}
if err := postalCode.Valid(n.Value); err != nil {
e.Err("postalCode %s", err.Error())
}
// organizationName
case organizationName.Equal(n.Type):
// Require field if organizationName is set
if !inDN(dn, localityName) && !inDN(dn, stateOrProvinceName) {
e.Err("localityName or stateOrProvinceName is required if organizationName is set")
}
if !inDN(dn, stateOrProvinceName) {
e.Err("stateOrProvinceName is required if organizationName is set")
}
if !inDN(dn, countryName) {
e.Err("countryName is required if organizationName is set")
}
if err := organizationName.Valid(n.Value); err != nil {
e.Err("organizationName %s", err.Error())
}
// organizationalUnitName
case organizationalUnitName.Equal(n.Type):
if err := organizationalUnitName.Valid(n.Value); err != nil {
e.Err("organizationalUnitName %s", err.Error())
}
// businessCategory
case businessCategory.Equal(n.Type):
bc := n.Value.(string)
if bc != "Private Organization" && bc != "Government Entity" && bc != "Business Entity" && bc != "Non-Commercial Entity" {
e.Err("businessCategory should contain 'Private Organization', 'Government Entity', 'Business Entity', or 'Non-Commercial Entity'")
}
if err := businessCategory.Valid(n.Value); err != nil {
e.Err("businessCategory %s", err.Error())
}
// serialNumber
case serialNumber.Equal(n.Type):
if err := serialNumber.Valid(n.Value); err != nil {
e.Err("serialNumber %s", err.Error())
}
// givenName
case givenName.Equal(n.Type):
// Prohibited
if !inDN(dn, surname) {
e.Err("givenName may only set in combination with surname")
}
if err := givenName.Valid(n.Value); err != nil {
e.Err("givenName %s", err.Error())
}
}
}
return e
}
func inDN(dn []pkix.AttributeTypeAndValue, attr object) bool {
for _, n := range dn {
if attr.Equal(n.Type) {
return true
}
}
return false
}

View File

@ -1,104 +0,0 @@
package subjectaltname
import (
goerr "errors"
"strings"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
"golang.org/x/net/idna"
)
const checkName = "Subject Alternative Names Check"
var idnaProfile *idna.Profile
var idnaUnderscoreError = goerr.New("idna: disallowed rune U+005F")
func init() {
idnaProfile = idna.New(
idna.BidiRule(),
idna.MapForLookup(),
idna.ValidateForRegistration(),
idna.ValidateLabels(true),
idna.VerifyDNSLength(true),
idna.StrictDomainName(true),
idna.Transitional(false))
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// TODO: Should we check against cross usage of certificate types (for example DV certificate with emial address)?
switch d.Type {
case "PS":
// TODO: Check EmailAddresses in the Subject DN
if len(d.Cert.EmailAddresses) == 0 {
e.Err("Certificate doesn't contain any subjectAltName")
return e
}
for _, s := range d.Cert.EmailAddresses {
// Splitting domain of mail address, using lowercase
em := strings.SplitAfter(strings.ToLower(s), "@")
if len(em) != 2 {
e.Err("Certificate subjectAltName '%s' contains an invalid email address", s)
continue
}
// Check email address domain part
if _, err := idnaProfile.ToASCII(em[1]); err != nil {
e.Err("Certificate subjectAltName '%s', %s", s, err.Error())
}
// TODO: Implement more checks for the left side of the @ sign
if strings.Contains(em[0], " ") {
e.Err("Certificate subjectAltName '%s' contains a whitespace", s)
}
}
case "DV", "OV", "EV":
if len(d.Cert.DNSNames) == 0 && len(d.Cert.IPAddresses) == 0 {
e.Err("Certificate doesn't contain any subjectAltName")
return e
}
// While the commonname is not a subjectAltName we use the same rule to
// validate the domain name. Check with stripped wildcards as they are non
// registrable.
if _, err := idnaProfile.ToASCII(strings.TrimPrefix(strings.ToLower(d.Cert.Subject.CommonName), "*.")); err != nil && err != idnaUnderscoreError {
e.Err("Certificate CommonName '%s', %s", d.Cert.Subject.CommonName, err.Error())
}
var cnInSan bool
for _, s := range d.Cert.DNSNames {
if strings.EqualFold(d.Cert.Subject.CommonName, s) {
cnInSan = true
}
// Check subjectAltName with stripped wildcards as they are non registrable
if _, err := idnaProfile.ToASCII(strings.TrimPrefix(strings.ToLower(s), "*.")); err != nil && err != idnaUnderscoreError {
e.Err("Certificate subjectAltName '%s', %s", s, err.Error())
}
}
// Maybe it's an IP address
if !cnInSan {
for _, s := range d.Cert.IPAddresses {
if strings.EqualFold(d.Cert.Subject.CommonName, s.String()) {
cnInSan = true
}
}
}
if !cnInSan {
e.Err("Certificate CN is not listed in subjectAltName")
}
}
return e
}

View File

@ -1,41 +0,0 @@
package validity
import (
"time"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Validity Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
switch d.Type {
case "EV":
if d.Cert.NotBefore.After(d.Cert.NotBefore.AddDate(0, 27, 0)) {
e.Err("EV Certificate LifeTime exceeds 27 months")
return e
}
case "DV", "OV":
if d.Cert.NotBefore.After(time.Date(2015, 4, 1, 0, 0, 0, 0, time.UTC)) {
if d.Cert.NotBefore.After(d.Cert.NotBefore.AddDate(0, 39, 0)) {
e.Err("Certificate LifeTime exceeds 39 months")
return e
}
} else {
if d.Cert.NotBefore.After(d.Cert.NotBefore.AddDate(0, 60, 0)) {
e.Err("Certificate LifeTime exceeds 60 months")
return e
}
}
}
return e
}

View File

@ -1,25 +0,0 @@
package version
import (
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Certificate Version Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if d.Cert.Version != 3 {
e.Err("Certificate is not V3 (%d)", d.Cert.Version)
return e
}
return nil
}

View File

@ -1,43 +0,0 @@
package wildcard
import (
"strings"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Wildcard(s) Check"
func init() {
checks.RegisterCertificateCheck(checkName, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
switch d.Type {
case "EV":
if strings.LastIndex(d.Cert.Subject.CommonName, "*") > -1 {
e.Err("Certificate should not contain a wildcard")
}
for _, n := range d.Cert.DNSNames {
if strings.LastIndex(n, "*") > -1 {
e.Err("Certificate subjectAltName '%s' should not contain a wildcard", n)
}
}
case "DV", "OV":
if strings.LastIndex(d.Cert.Subject.CommonName, "*") > 0 {
e.Err("Certificate wildcard is only allowed as prefix")
}
for _, n := range d.Cert.DNSNames {
if strings.LastIndex(n, "*") > 0 {
e.Err("Certificate subjectAltName '%s' wildcard is only allowed as prefix", n)
}
}
}
return e
}

View File

@ -1,59 +0,0 @@
package checks
import (
"crypto/x509/pkix"
"encoding/asn1"
"strings"
"sync"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/errors"
)
var extMutex = &sync.Mutex{}
type extensions []extensionCheck
type extensionCheck struct {
name string
oid asn1.ObjectIdentifier
filter *Filter
f func(pkix.Extension, *certdata.Data) *errors.Errors
}
// Extensions contains all imported extension checks
var Extensions extensions
// RegisterExtensionCheck adds a new check to Extensions
func RegisterExtensionCheck(name string, oid asn1.ObjectIdentifier, filter *Filter, f func(pkix.Extension, *certdata.Data) *errors.Errors) {
extMutex.Lock()
Extensions = append(Extensions, extensionCheck{name, oid, filter, f})
extMutex.Unlock()
}
// Check lookups the registered extension checks and runs all checks with the
// same Object Identifier.
func (ex extensions) Check(ext pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
var found bool
for _, ec := range ex {
if ec.oid.Equal(ext.Id) {
found = true
if ec.filter != nil && ec.filter.Check(d) {
continue
}
e.Append(ec.f(ext, d))
}
}
if !found {
// Don't report private enterprise extensions as unknown, registered private
// extensions have still been checked above.
if !strings.HasPrefix(ext.Id.String(), "1.3.6.1.4.1.") {
e.Warning("Certificate contains unknown extension (%s)", ext.Id.String())
}
}
return e
}

View File

@ -1,29 +0,0 @@
package adobetimestamp
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Adobe Timestamp Extension Check"
var extensionOid = asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 1, 9, 1}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("Adobe Timestamp extension set critical")
}
return e
}

View File

@ -1,21 +0,0 @@
package all
import (
// Import all default extensions
_ "github.com/globalsign/certlint/checks/extensions/adobetimestamp"
_ "github.com/globalsign/certlint/checks/extensions/authorityinfoaccess"
_ "github.com/globalsign/certlint/checks/extensions/authoritykeyid"
_ "github.com/globalsign/certlint/checks/extensions/basicconstraints"
_ "github.com/globalsign/certlint/checks/extensions/crldistributionpoints"
_ "github.com/globalsign/certlint/checks/extensions/ct"
_ "github.com/globalsign/certlint/checks/extensions/extkeyusage"
_ "github.com/globalsign/certlint/checks/extensions/keyusage"
_ "github.com/globalsign/certlint/checks/extensions/nameconstraints"
_ "github.com/globalsign/certlint/checks/extensions/ocspmuststaple"
_ "github.com/globalsign/certlint/checks/extensions/ocspnocheck"
_ "github.com/globalsign/certlint/checks/extensions/pdfrevocation"
_ "github.com/globalsign/certlint/checks/extensions/policyidentifiers"
_ "github.com/globalsign/certlint/checks/extensions/smimecapabilities"
_ "github.com/globalsign/certlint/checks/extensions/subjectaltname"
_ "github.com/globalsign/certlint/checks/extensions/subjectkeyid"
)

View File

@ -1,30 +0,0 @@
package authorityinfoaccess
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "AuthorityInfoAccess Extension Check"
var extensionOid = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 1}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
// TODO: Add more checks https://golang.org/src/github.com/globalsign/certlint/certdata/x509.go?s=15439:18344#L1157
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("AuthorityInfoAccess extension set critical")
}
return e
}

View File

@ -1,29 +0,0 @@
package authoritykeyid
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "AuthorityKeyId Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 35}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("AuthorityKeyId extension set critical")
}
return e
}

View File

@ -1,50 +0,0 @@
package basicconstraints
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "BasicConstraints Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 19}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
//
// https://tools.ietf.org/html/rfc5280#section-4.2.1.9
//
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// This extension MAY appear as a critical or non-critical extension in end
// entity certificates.
if d.Cert.IsCA {
// Conforming CAs MUST include this extension in all CA certificates
// that contain public keys used to validate digital signatures on
// certificates and MUST mark the extension as critical in such
// certificates. This extension MAY appear as a critical or non-
// critical extension in CA certificates that contain public keys used
// exclusively for purposes other than validating digital signatures on
// certificates. Such CA certificates include ones that contain public
// keys used exclusively for validating digital signatures on CRLs and
// ones that contain key management public keys used with certificate
// enrollment protocols.
//
// The CA Browser Forum BR 1.4.1 state that it should always be true for
// CA certificates.
if !ex.Critical {
e.Err("BasicConstraints extension must be critical in CA certificates")
}
}
return e
}

View File

@ -1,29 +0,0 @@
package crldistributionpoints
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "CRLDistributionPoints Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 31}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("CRLDistributionPoints extension set critical")
}
return e
}

View File

@ -1,33 +0,0 @@
package ct
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "Certificate Transparency Extension Check"
var extensionOid = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 2}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
//
// https://tools.ietf.org/html/rfc6962
//
// TODO: Check it's present in EV certificates issued after xxx
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("Certificate Transparency extension set critical")
}
return e
}

View File

@ -1,47 +0,0 @@
package extkeyusage
import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "ExtKeyUsage Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 37}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
//
// https://tools.ietf.org/html/rfc5280#section-4.2.1.12
//
// This extension MAY, at the option of the certificate issuer, be either critical or non-critical.
//
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// RFC: In general, this extension will appear only in end entity certificates.
if d.Cert.IsCA {
e.Err("In general ExtKeyUsage will appear only in end entity certificates")
}
// RFC: Conforming CAs SHOULD NOT mark this extension as critical if the
// anyExtendedKeyUsage KeyPurposeId is present.
if ex.Critical {
for _, ku := range d.Cert.ExtKeyUsage {
if ku == x509.ExtKeyUsageAny {
e.Err("ExtKeyUsage extension SHOULD NOT be critical if anyExtendedKeyUsage is present")
break
}
}
}
return e
}

View File

@ -1,32 +0,0 @@
package keyusage
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "KeyUsage Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 15}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
//
// https://tools.ietf.org/html/rfc5280#section-4.2.1.3
//
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if !ex.Critical {
e.Err("KeyUsage extension SHOULD be marked as critical when present")
}
return e
}

View File

@ -1,37 +0,0 @@
package nameconstraints
import (
"encoding/asn1"
"crypto/x509/pkix"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "NameConstraints Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 30}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// NameConstraints do officially need to be set critical, often they are not
// because many implementations still don't support Name Constraints.
if !ex.Critical {
e.Warning("NameConstraints extension set non-critical")
}
// NameConstraints should only be included in CA or subordinate certificates
if !d.Cert.IsCA {
e.Err("End entity certificate should not contain a NameConstraints extension")
}
return e
}

View File

@ -1,65 +0,0 @@
package ocspmuststaple
import (
"bytes"
"crypto/x509/pkix"
"encoding/asn1"
"fmt"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const (
checkName = "OCSP Must Staple Extension Check"
certTypeErr = "OCSP Must Staple extension set in non end-entity/issuer certificate"
critExtErr = "OCSP Must Staple extension set critical"
)
var (
// RFC 7633 OID of the OCSP Must Staple TLS Extension Feature
extensionOid = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24}
// Expected extension value (DER encoded ASN.1 bytestring)
expectedExtensionValue = []uint8{0x30, 0x3, 0x2, 0x1, 0x5}
extValueErr = fmt.Sprintf(
"OCSP Must Staple extension had incorrect value. "+
"Should be ASN.1 DER %#v", expectedExtensionValue)
)
// RFC 7633 only defines this extension for PKIX end-entity certificates,
// certificate signing requests, and certificate signing certificates (CAs).
// We should not allow it for cert types like "OCSP", "PS", "CS", etc.
var allowedCertTypes = map[string]bool{
"DV": true,
"OV": true,
"EV": true,
"CA": true,
}
func init() {
// Register this check for the OCSP Must Staple extension OID.
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// If the cert type isn't one of the `allowedCertTypes`, return an error
if _, allowed := allowedCertTypes[d.Type]; !allowed {
e.Err(certTypeErr)
}
// Per RFC 7633 "The TLS feature extension SHOULD NOT be marked critical"
if ex.Critical {
e.Err(critExtErr)
}
// Check that the extension value is the expected slice of DER encoded ASN.1
if bytes.Compare(ex.Value, expectedExtensionValue) != 0 {
e.Err(extValueErr)
}
return e
}

View File

@ -1,33 +0,0 @@
package ocspnocheck
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "OCSP Nocheck Extension Check"
var extensionOid = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1, 5}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if d.Type != "OCSP" {
e.Err("OCSP Nocheck extension set in non OCSP signing certificate")
}
if ex.Critical {
e.Err("OCSP Nocheck Capabilities extension set critical")
}
return e
}

View File

@ -1,29 +0,0 @@
package pdfrevocation
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "PDF Certificate Revocation Check"
var extensionOid = asn1.ObjectIdentifier{1, 2, 840, 113583, 1, 1, 8}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("PDF Certificate Revocation extension set critical")
}
return e
}

View File

@ -1,43 +0,0 @@
package policyidentifiers
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "PolicyIdentifiers Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 32}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
//
// Section 7.1.2.3 (a) of the Baseline Requirements states:
//
// This extension MUST be present and SHOULD NOT be marked critical.
//
// A Policy Identifier, defined by the issuing CA, that indicates a
// Certificate Policy asserting the issuing CA's adherence to and compliance
// with these Requirements.
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
// certificatePolicies SHOULD NOT be marked critical
if ex.Critical {
e.Err("PolicyIdentifiers extension set critical")
}
// A policy must be defined
if len(d.Cert.PolicyIdentifiers) == 0 {
e.Err("PolicyIdentifiers not present")
}
return e
}

View File

@ -1,29 +0,0 @@
package smimecapabilities
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "S/MIME Capabilities Extension Check"
var extensionOid = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 15}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("S/MIME Capabilities extension set critical")
}
return e
}

View File

@ -1,29 +0,0 @@
package subjectaltname
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "SubjectAltName Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 17}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("SubjectAltName extension set critical")
}
return e
}

View File

@ -1,29 +0,0 @@
package subjectkeyid
import (
"crypto/x509/pkix"
"encoding/asn1"
"github.com/globalsign/certlint/certdata"
"github.com/globalsign/certlint/checks"
"github.com/globalsign/certlint/errors"
)
const checkName = "SubjectKeyId Extension Check"
var extensionOid = asn1.ObjectIdentifier{2, 5, 29, 14}
func init() {
checks.RegisterExtensionCheck(checkName, extensionOid, nil, Check)
}
// Check performs a strict verification on the extension according to the standard(s)
func Check(ex pkix.Extension, d *certdata.Data) *errors.Errors {
var e = errors.New(nil)
if ex.Critical {
e.Err("SubjectKeyId extension set critical")
}
return e
}

View File

@ -1,51 +0,0 @@
package checks
import (
"time"
"github.com/globalsign/certlint/certdata"
)
// Filter defines condition on when a check is performed or not
type Filter struct {
Type []string
IssuedBefore *time.Time
IssuedAfter *time.Time
ExpiresBefore *time.Time
ExpiresAfter *time.Time
}
// Check returns true if a certificate complies with the given filter
func (f *Filter) Check(d *certdata.Data) bool {
// Is certificate recognised as one of the given types
if len(f.Type) > 0 {
var inFilter bool
for _, t := range f.Type {
if d.Type == t {
inFilter = true
}
}
if !inFilter {
return false
}
}
// Issued before given date
if f.IssuedBefore != nil && !d.Cert.NotBefore.Before(*f.IssuedBefore) {
return false
}
// Issued after given date
if f.IssuedAfter != nil && !d.Cert.NotBefore.After(*f.IssuedAfter) {
return false
}
// Expires before given date
if f.ExpiresBefore != nil && !d.Cert.NotBefore.Before(*f.ExpiresBefore) {
return false
}
// Expires after given date
if f.ExpiresAfter != nil && !d.Cert.NotAfter.After(*f.ExpiresAfter) {
return false
}
return true
}

View File

@ -1,178 +0,0 @@
package errors
import (
"fmt"
"sync"
)
//go:generate stringer -type=Priority
// Priority defines how an error should be threaded
type Priority int
// Priorities that can be used to create and list errors
const (
Unknown Priority = iota
Debug
Info
Notice
Warning
Error
Critical
Alert
Emergency
)
// Config defines the error configuration, currently no configuration options
// are available.
type Config struct {
}
// Err contains a single error
type Err struct {
p Priority
msg string
}
// Priority returns the priority of this error
func (e Err) Priority() Priority {
return e.p
}
// String returns the message of this error
func (e Err) Error() string {
return e.msg
}
// Errors contains a list of Error
type Errors struct {
err []Err
config *Config
p Priority
m sync.Mutex
}
// New creates an empty error container
func New(c *Config) *Errors {
return &Errors{config: c}
}
// IsError returns true on one or more errors
func (e *Errors) IsError() bool {
if len(e.err) > 0 {
return true
}
return false
}
// Priority returns the priority of this error
func (e *Errors) Priority() Priority {
return e.p
}
// List returns all errors of a given priority, if no priority is given all
// errors are returned.
func (e *Errors) List(p ...Priority) []Err {
if len(p) == 0 {
return e.err
}
// filter errors to given priorities
var l []Err
for _, e := range e.err {
for _, priority := range p {
if e.p == priority {
l = append(l, e)
}
}
}
return l
}
// Append add all Errors to existing Errors
func (e *Errors) Append(err *Errors) error {
if err == nil {
return nil
}
e.m.Lock()
// append Errors at the end of the current list
e.err = append(e.err, err.err...)
// set highest priority
if err.p > e.p {
e.p = err.p
}
e.m.Unlock()
return nil
}
// Emerg log an error with severity Emergency
func (e *Errors) Emerg(format string, a ...interface{}) error {
return e.add(Emergency, format, a...)
}
// Alert log an error with severity Alert
func (e *Errors) Alert(format string, a ...interface{}) error {
return e.add(Alert, format, a...)
}
// Crit log an error with severity Critical
func (e *Errors) Crit(format string, a ...interface{}) error {
return e.add(Critical, format, a...)
}
// Err log an error with severity Error
func (e *Errors) Err(format string, a ...interface{}) error {
return e.add(Error, format, a...)
}
// Warning log an error with severity Warning
func (e *Errors) Warning(format string, a ...interface{}) error {
return e.add(Warning, format, a...)
}
// Notice log an error with severity Notice
func (e *Errors) Notice(format string, a ...interface{}) error {
return e.add(Notice, format, a...)
}
// Info log an error with severity Info
func (e *Errors) Info(format string, a ...interface{}) error {
return e.add(Info, format, a...)
}
// Debug log an error with severity Debug
func (e *Errors) Debug(format string, a ...interface{}) error {
return e.add(Debug, format, a...)
}
func (e *Errors) add(p Priority, format string, a ...interface{}) error {
// no error in request
if len(format) == 0 && len(a) == 0 {
return nil
}
e.m.Lock()
msg := format
if len(a) > 0 {
msg = fmt.Sprintf(format, a...)
}
// add this priority to the end of the list
e.err = append(e.err, Err{
p: p,
msg: msg,
})
// set highest priority in this list
if p > e.p {
e.p = p
}
e.m.Unlock()
return nil
}

View File

@ -1,16 +0,0 @@
// Code generated by "stringer -type=Priority"; DO NOT EDIT.
package errors
import "strconv"
const _Priority_name = "UnknownDebugInfoNoticeWarningErrorCriticalAlertEmergency"
var _Priority_index = [...]uint8{0, 7, 12, 16, 22, 29, 34, 42, 47, 56}
func (i Priority) String() string {
if i < 0 || i >= Priority(len(_Priority_index)-1) {
return "Priority(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Priority_name[_Priority_index[i]:_Priority_index[i+1]]
}

229
vendor/github.com/zmap/zcrypto/LICENSE generated vendored Normal file
View File

@ -0,0 +1,229 @@
ZCrypto is an original work created at the University of Michigan, and is
licensed under the Apache 2.0 license. However, ZCrypto contains a fork of
several packages from Golang standard library, as well as code from the
BoringSSL test runner. Files that were created by Google, and new files in
forks of packages maintained by Google have a Google copyright and fall under
the ISC license. All other files are copyright Regents of the University of
Michigan, and fall under the Apache 2.0 license. Both licenses are reproduced
at the bottom of this file.
--------
ISC License used for Google code
/* Copyright (c) 2015, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
ZCrypto Copyright 2015 Regents of the University of Michigan
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

130
vendor/github.com/zmap/zcrypto/json/dhe.go generated vendored Normal file
View File

@ -0,0 +1,130 @@
/*
* ZGrab Copyright 2015 Regents of the University of Michigan
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package json
import (
"encoding/json"
"math/big"
)
// DHParams can be used to store finite-field Diffie-Hellman parameters. At any
// point in time, it is unlikely that both OurPrivate and TheirPrivate will be
// non-nil.
type DHParams struct {
Prime *big.Int
Generator *big.Int
ServerPublic *big.Int
ServerPrivate *big.Int
ClientPublic *big.Int
ClientPrivate *big.Int
SessionKey *big.Int
}
type auxDHParams struct {
Prime *cryptoParameter `json:"prime"`
Generator *cryptoParameter `json:"generator"`
ServerPublic *cryptoParameter `json:"server_public,omitempty"`
ServerPrivate *cryptoParameter `json:"server_private,omitempty"`
ClientPublic *cryptoParameter `json:"client_public,omitempty"`
ClientPrivate *cryptoParameter `json:"client_private,omitempty"`
SessionKey *cryptoParameter `json:"session_key,omitempty"`
}
// MarshalJSON implements the json.Marshal interface
func (p *DHParams) MarshalJSON() ([]byte, error) {
aux := auxDHParams{
Prime: &cryptoParameter{Int: p.Prime},
Generator: &cryptoParameter{Int: p.Generator},
}
if p.ServerPublic != nil {
aux.ServerPublic = &cryptoParameter{Int: p.ServerPublic}
}
if p.ServerPrivate != nil {
aux.ServerPrivate = &cryptoParameter{Int: p.ServerPrivate}
}
if p.ClientPublic != nil {
aux.ClientPublic = &cryptoParameter{Int: p.ClientPublic}
}
if p.ClientPrivate != nil {
aux.ClientPrivate = &cryptoParameter{Int: p.ClientPrivate}
}
if p.SessionKey != nil {
aux.SessionKey = &cryptoParameter{Int: p.SessionKey}
}
return json.Marshal(aux)
}
// UnmarshalJSON implement the json.Unmarshaler interface
func (p *DHParams) UnmarshalJSON(b []byte) error {
var aux auxDHParams
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
if aux.Prime != nil {
p.Prime = aux.Prime.Int
}
if aux.Generator != nil {
p.Generator = aux.Generator.Int
}
if aux.ServerPublic != nil {
p.ServerPublic = aux.ServerPublic.Int
}
if aux.ServerPrivate != nil {
p.ServerPrivate = aux.ServerPrivate.Int
}
if aux.ClientPublic != nil {
p.ClientPublic = aux.ClientPublic.Int
}
if aux.ClientPrivate != nil {
p.ClientPrivate = aux.ClientPrivate.Int
}
if aux.SessionKey != nil {
p.SessionKey = aux.SessionKey.Int
}
return nil
}
// CryptoParameter represents a big.Int used a parameter in some cryptography.
// It serializes to json as a tupe of a base64-encoded number and a length in
// bits.
type cryptoParameter struct {
*big.Int
}
type auxCryptoParameter struct {
Raw []byte `json:"value"`
Length int `json:"length"`
}
// MarshalJSON implements the json.Marshaler interface
func (p *cryptoParameter) MarshalJSON() ([]byte, error) {
var aux auxCryptoParameter
if p.Int != nil {
aux.Raw = p.Bytes()
aux.Length = 8 * len(aux.Raw)
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshal interface
func (p *cryptoParameter) UnmarshalJSON(b []byte) error {
var aux auxCryptoParameter
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
p.Int = new(big.Int)
p.SetBytes(aux.Raw)
return nil
}

107
vendor/github.com/zmap/zcrypto/json/ecdhe.go generated vendored Normal file
View File

@ -0,0 +1,107 @@
/*
* ZGrab Copyright 2015 Regents of the University of Michigan
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package json
import (
"crypto/elliptic"
"encoding/json"
"math/big"
)
// TLSCurveID is the type of a TLS identifier for an elliptic curve. See
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
type TLSCurveID uint16
// ECDHPrivateParams are the TLS key exchange parameters for ECDH keys.
type ECDHPrivateParams struct {
Value []byte `json:"value,omitempty"`
Length int `json:"length,omitempty"`
}
// ECDHParams stores elliptic-curve Diffie-Hellman paramters.At any point in
// time, it is unlikely that both ServerPrivate and ClientPrivate will be non-nil.
type ECDHParams struct {
TLSCurveID TLSCurveID `json:"curve_id,omitempty"`
Curve elliptic.Curve `json:"-"`
ServerPublic *ECPoint `json:"server_public,omitempty"`
ServerPrivate *ECDHPrivateParams `json:"server_private,omitempty"`
ClientPublic *ECPoint `json:"client_public,omitempty"`
ClientPrivate *ECDHPrivateParams `json:"client_private,omitempty"`
}
// ECPoint represents an elliptic curve point and serializes nicely to JSON
type ECPoint struct {
X *big.Int
Y *big.Int
}
// MarshalJSON implements the json.Marshler interface
func (p *ECPoint) MarshalJSON() ([]byte, error) {
aux := struct {
X *cryptoParameter `json:"x"`
Y *cryptoParameter `json:"y"`
}{
X: &cryptoParameter{Int: p.X},
Y: &cryptoParameter{Int: p.Y},
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshler interface
func (p *ECPoint) UnmarshalJSON(b []byte) error {
aux := struct {
X *cryptoParameter `json:"x"`
Y *cryptoParameter `json:"y"`
}{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
p.X = aux.X.Int
p.Y = aux.Y.Int
return nil
}
// Description returns the description field for the given ID. See
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
func (c *TLSCurveID) Description() string {
if desc, ok := ecIDToName[*c]; ok {
return desc
}
return "unknown"
}
// MarshalJSON implements the json.Marshaler interface
func (c *TLSCurveID) MarshalJSON() ([]byte, error) {
aux := struct {
Name string `json:"name"`
ID uint16 `json:"id"`
}{
Name: c.Description(),
ID: uint16(*c),
}
return json.Marshal(&aux)
}
//UnmarshalJSON implements the json.Unmarshaler interface
func (c *TLSCurveID) UnmarshalJSON(b []byte) error {
aux := struct {
ID uint16 `json:"id"`
}{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
*c = TLSCurveID(aux.ID)
return nil
}

113
vendor/github.com/zmap/zcrypto/json/names.go generated vendored Normal file
View File

@ -0,0 +1,113 @@
/*
* ZGrab Copyright 2015 Regents of the University of Michigan
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package json
// IANA-assigned curve ID values, see
// http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-8
const (
Sect163k1 TLSCurveID = 1
Sect163r1 TLSCurveID = 2
Sect163r2 TLSCurveID = 3
Sect193r1 TLSCurveID = 4
Sect193r2 TLSCurveID = 5
Sect233k1 TLSCurveID = 6
Sect233r1 TLSCurveID = 7
Sect239k1 TLSCurveID = 8
Sect283k1 TLSCurveID = 9
Sect283r1 TLSCurveID = 10
Sect409k1 TLSCurveID = 11
Sect409r1 TLSCurveID = 12
Sect571k1 TLSCurveID = 13
Sect571r1 TLSCurveID = 14
Secp160k1 TLSCurveID = 15
Secp160r1 TLSCurveID = 16
Secp160r2 TLSCurveID = 17
Secp192k1 TLSCurveID = 18
Secp192r1 TLSCurveID = 19
Secp224k1 TLSCurveID = 20
Secp224r1 TLSCurveID = 21
Secp256k1 TLSCurveID = 22
Secp256r1 TLSCurveID = 23
Secp384r1 TLSCurveID = 24
Secp521r1 TLSCurveID = 25
BrainpoolP256r1 TLSCurveID = 26
BrainpoolP384r1 TLSCurveID = 27
BrainpoolP512r1 TLSCurveID = 28
)
var ecIDToName map[TLSCurveID]string
var ecNameToID map[string]TLSCurveID
func init() {
ecIDToName = make(map[TLSCurveID]string, 64)
ecIDToName[Sect163k1] = "sect163k1"
ecIDToName[Sect163r1] = "sect163r1"
ecIDToName[Sect163r2] = "sect163r2"
ecIDToName[Sect193r1] = "sect193r1"
ecIDToName[Sect193r2] = "sect193r2"
ecIDToName[Sect233k1] = "sect233k1"
ecIDToName[Sect233r1] = "sect233r1"
ecIDToName[Sect239k1] = "sect239k1"
ecIDToName[Sect283k1] = "sect283k1"
ecIDToName[Sect283r1] = "sect283r1"
ecIDToName[Sect409k1] = "sect409k1"
ecIDToName[Sect409r1] = "sect409r1"
ecIDToName[Sect571k1] = "sect571k1"
ecIDToName[Sect571r1] = "sect571r1"
ecIDToName[Secp160k1] = "secp160k1"
ecIDToName[Secp160r1] = "secp160r1"
ecIDToName[Secp160r2] = "secp160r2"
ecIDToName[Secp192k1] = "secp192k1"
ecIDToName[Secp192r1] = "secp192r1"
ecIDToName[Secp224k1] = "secp224k1"
ecIDToName[Secp224r1] = "secp224r1"
ecIDToName[Secp256k1] = "secp256k1"
ecIDToName[Secp256r1] = "secp256r1"
ecIDToName[Secp384r1] = "secp384r1"
ecIDToName[Secp521r1] = "secp521r1"
ecIDToName[BrainpoolP256r1] = "brainpoolp256r1"
ecIDToName[BrainpoolP384r1] = "brainpoolp384r1"
ecIDToName[BrainpoolP512r1] = "brainpoolp512r1"
ecNameToID = make(map[string]TLSCurveID, 64)
ecNameToID["sect163k1"] = Sect163k1
ecNameToID["sect163r1"] = Sect163r1
ecNameToID["sect163r2"] = Sect163r2
ecNameToID["sect193r1"] = Sect193r1
ecNameToID["sect193r2"] = Sect193r2
ecNameToID["sect233k1"] = Sect233k1
ecNameToID["sect233r1"] = Sect233r1
ecNameToID["sect239k1"] = Sect239k1
ecNameToID["sect283k1"] = Sect283k1
ecNameToID["sect283r1"] = Sect283r1
ecNameToID["sect409k1"] = Sect409k1
ecNameToID["sect409r1"] = Sect409r1
ecNameToID["sect571k1"] = Sect571k1
ecNameToID["sect571r1"] = Sect571r1
ecNameToID["secp160k1"] = Secp160k1
ecNameToID["secp160r1"] = Secp160r1
ecNameToID["secp160r2"] = Secp160r2
ecNameToID["secp192k1"] = Secp192k1
ecNameToID["secp192r1"] = Secp192r1
ecNameToID["secp224k1"] = Secp224k1
ecNameToID["secp224r1"] = Secp224r1
ecNameToID["secp256k1"] = Secp256k1
ecNameToID["secp256r1"] = Secp256r1
ecNameToID["secp384r1"] = Secp384r1
ecNameToID["secp521r1"] = Secp521r1
ecNameToID["brainpoolp256r1"] = BrainpoolP256r1
ecNameToID["brainpoolp384r1"] = BrainpoolP384r1
ecNameToID["brainpoolp512r1"] = BrainpoolP512r1
}

67
vendor/github.com/zmap/zcrypto/json/rsa.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
/*
* ZGrab Copyright 2015 Regents of the University of Michigan
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package json
import (
"crypto/rsa"
"encoding/json"
"fmt"
"math/big"
)
// RSAPublicKey provides JSON methods for the standard rsa.PublicKey.
type RSAPublicKey struct {
*rsa.PublicKey
}
type auxRSAPublicKey struct {
Exponent int `json:"exponent"`
Modulus []byte `json:"modulus"`
Length int `json:"length"`
}
// RSAClientParams are the TLS key exchange parameters for RSA keys.
type RSAClientParams struct {
Length uint16 `json:"length,omitempty"`
EncryptedPMS []byte `json:"encrypted_pre_master_secret,omitempty"`
}
// MarshalJSON implements the json.Marshal interface
func (rp *RSAPublicKey) MarshalJSON() ([]byte, error) {
var aux auxRSAPublicKey
if rp.PublicKey != nil {
aux.Exponent = rp.E
aux.Modulus = rp.N.Bytes()
aux.Length = len(aux.Modulus) * 8
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshal interface
func (rp *RSAPublicKey) UnmarshalJSON(b []byte) error {
var aux auxRSAPublicKey
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
if rp.PublicKey == nil {
rp.PublicKey = new(rsa.PublicKey)
}
rp.E = aux.Exponent
rp.N = big.NewInt(0).SetBytes(aux.Modulus)
if len(aux.Modulus)*8 != aux.Length {
return fmt.Errorf("mismatched length (got %d, field specified %d)", len(aux.Modulus), aux.Length)
}
return nil
}

6
vendor/github.com/zmap/zcrypto/x509/README.md generated vendored Normal file
View File

@ -0,0 +1,6 @@
This package is a port of github.com/golang/go/crypto/x509 package at:
branch: release-branch.go1.9
revision: c03ee1985cb6e4467246a2bdb07bb1c62e05f8e9
Modifications to shared files are located in $name_modified.go to
facilitate tracking the stdlib updates.

143
vendor/github.com/zmap/zcrypto/x509/cert_pool.go generated vendored Normal file
View 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
}

View File

@ -0,0 +1,128 @@
// 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
// CertPool is a set of certificates.
type CertPool struct {
bySubjectKeyId map[string][]int
byName map[string][]int
bySHA256 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),
bySHA256: make(map[string]int),
}
}
// 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 {
cert.validSignature = true
parents = append(parents, c)
} else {
errCert = s.certs[c]
}
}
return
}
// 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.
sha256fp := string(cert.FingerprintSHA256)
if _, ok := s.bySHA256[sha256fp]; ok {
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)
s.bySHA256[sha256fp] = n
}
// Contains returns true if c is in s.
func (s *CertPool) Contains(c *Certificate) bool {
if s == nil {
return false
}
_, ok := s.bySHA256[string(c.FingerprintSHA256)]
return ok
}
// Covers returns true if all certs in pool are in s.
func (s *CertPool) Covers(pool *CertPool) bool {
if pool == nil {
return true
}
for _, c := range pool.certs {
if !s.Contains(c) {
return false
}
}
return true
}
// Certificates returns a list of parsed certificates in the pool.
func (s *CertPool) Certificates() []*Certificate {
out := make([]*Certificate, 0, len(s.certs))
out = append(out, s.certs...)
return out
}
// Size returns the number of unique certificates in the CertPool.
func (s *CertPool) Size() int {
if s == nil {
return 0
}
return len(s.certs)
}
// Sum returns the union of two certificate pools as a new certificate pool.
func (s *CertPool) Sum(other *CertPool) (sum *CertPool) {
sum = NewCertPool()
if s != nil {
for _, c := range s.certs {
sum.AddCert(c)
}
}
if other != nil {
for _, c := range other.certs {
sum.AddCert(c)
}
}
return
}

View File

@ -0,0 +1,64 @@
// 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.
package x509
import "encoding/json"
// TODO: Automatically generate this file from a CSV
// CertificateType represents whether a certificate is a root, intermediate, or
// leaf.
type CertificateType int
// CertificateType constants. Values should not be considered significant aside
// from CertificateTypeUnknown is the zero value.
const (
CertificateTypeUnknown CertificateType = 0
CertificateTypeLeaf CertificateType = 1
CertificateTypeIntermediate CertificateType = 2
CertificateTypeRoot CertificateType = 3
)
const (
certificateTypeStringLeaf = "leaf"
certificateTypeStringIntermediate = "intermediate"
certificateTypeStringRoot = "root"
certificateTypeStringUnknown = "unknown"
)
// MarshalJSON implements the json.Marshaler interface. Any unknown integer
// value is considered the same as CertificateTypeUnknown.
func (t CertificateType) MarshalJSON() ([]byte, error) {
switch t {
case CertificateTypeLeaf:
return json.Marshal(certificateTypeStringLeaf)
case CertificateTypeIntermediate:
return json.Marshal(certificateTypeStringIntermediate)
case CertificateTypeRoot:
return json.Marshal(certificateTypeStringRoot)
default:
return json.Marshal(certificateTypeStringUnknown)
}
}
// UnmarshalJSON implements the json.Unmarshaler interface. Any unknown string
// is considered the same CertificateTypeUnknown.
func (t *CertificateType) UnmarshalJSON(b []byte) error {
var certificateTypeString string
if err := json.Unmarshal(b, &certificateTypeString); err != nil {
return err
}
switch certificateTypeString {
case certificateTypeStringLeaf:
*t = CertificateTypeLeaf
case certificateTypeStringIntermediate:
*t = CertificateTypeIntermediate
case certificateTypeStringRoot:
*t = CertificateTypeRoot
default:
*t = CertificateTypeUnknown
}
return nil
}

70
vendor/github.com/zmap/zcrypto/x509/chain.go generated vendored Normal file
View File

@ -0,0 +1,70 @@
// 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.
package x509
import (
"bytes"
"strings"
)
// CertificateChain is a slice of certificates. The 0'th element is the leaf,
// and the last element is a root. Successive elements have a child-parent
// relationship.
type CertificateChain []*Certificate
// Range runs a function on each element of chain. It can modify each
// certificate in place.
func (chain CertificateChain) Range(f func(int, *Certificate)) {
for i, c := range chain {
f(i, c)
}
}
// SubjectAndKeyInChain returns true if the given SubjectAndKey is found in any
// certificate in the chain.
func (chain CertificateChain) SubjectAndKeyInChain(sk *SubjectAndKey) bool {
for _, cert := range chain {
if bytes.Equal(sk.RawSubject, cert.RawSubject) && bytes.Equal(sk.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) {
return true
}
}
return false
}
// CertificateSubjectAndKeyInChain returns true if the SubjectAndKey from c is
// found in any certificate in the chain.
func (chain CertificateChain) CertificateSubjectAndKeyInChain(c *Certificate) bool {
for _, cert := range chain {
if bytes.Equal(c.RawSubject, cert.RawSubject) && bytes.Equal(c.RawSubjectPublicKeyInfo, cert.RawSubjectPublicKeyInfo) {
return true
}
}
return false
}
// CertificateInChain returns true if c is in the chain.
func (chain CertificateChain) CertificateInChain(c *Certificate) bool {
for _, cert := range chain {
if bytes.Equal(c.Raw, cert.Raw) {
return true
}
}
return false
}
func (chain CertificateChain) AppendToFreshChain(c *Certificate) CertificateChain {
n := make([]*Certificate, len(chain)+1)
copy(n, chain)
n[len(chain)] = c
return n
}
func (chain CertificateChain) chainID() string {
var parts []string
for _, c := range chain {
parts = append(parts, string(c.FingerprintSHA256))
}
return strings.Join(parts, "")
}

172
vendor/github.com/zmap/zcrypto/x509/ct/serialization.go generated vendored Normal file
View File

@ -0,0 +1,172 @@
package ct
// This file contains selectively chosen snippets of
// github.com/google/certificate-transparency-go@ 5cfe585726ad9d990d4db524d6ce2567b13e2f80
//
// These snippets only perform deserialization for SCTs and are recreated here to prevent pulling in the whole of the ct
// which contains yet another version of x509,asn1 and tls
import (
"encoding/binary"
"errors"
"fmt"
"io"
)
// Variable size structure prefix-header byte lengths
const (
CertificateLengthBytes = 3
PreCertificateLengthBytes = 3
ExtensionsLengthBytes = 2
CertificateChainLengthBytes = 3
SignatureLengthBytes = 2
)
func writeUint(w io.Writer, value uint64, numBytes int) error {
buf := make([]uint8, numBytes)
for i := 0; i < numBytes; i++ {
buf[numBytes-i-1] = uint8(value & 0xff)
value >>= 8
}
if value != 0 {
return errors.New("numBytes was insufficiently large to represent value")
}
if _, err := w.Write(buf); err != nil {
return err
}
return nil
}
func writeVarBytes(w io.Writer, value []byte, numLenBytes int) error {
if err := writeUint(w, uint64(len(value)), numLenBytes); err != nil {
return err
}
if _, err := w.Write(value); err != nil {
return err
}
return nil
}
func readUint(r io.Reader, numBytes int) (uint64, error) {
var l uint64
for i := 0; i < numBytes; i++ {
l <<= 8
var t uint8
if err := binary.Read(r, binary.BigEndian, &t); err != nil {
return 0, err
}
l |= uint64(t)
}
return l, nil
}
// Reads a variable length array of bytes from |r|. |numLenBytes| specifies the
// number of (BigEndian) prefix-bytes which contain the length of the actual
// array data bytes that follow.
// Allocates an array to hold the contents and returns a slice view into it if
// the read was successful, or an error otherwise.
func readVarBytes(r io.Reader, numLenBytes int) ([]byte, error) {
switch {
case numLenBytes > 8:
return nil, fmt.Errorf("numLenBytes too large (%d)", numLenBytes)
case numLenBytes == 0:
return nil, errors.New("numLenBytes should be > 0")
}
l, err := readUint(r, numLenBytes)
if err != nil {
return nil, err
}
data := make([]byte, l)
if n, err := io.ReadFull(r, data); err != nil {
if err == io.EOF || err == io.ErrUnexpectedEOF {
return nil, fmt.Errorf("short read: expected %d but got %d", l, n)
}
return nil, err
}
return data, nil
}
// UnmarshalDigitallySigned reconstructs a DigitallySigned structure from a Reader
func UnmarshalDigitallySigned(r io.Reader) (*DigitallySigned, error) {
var h byte
if err := binary.Read(r, binary.BigEndian, &h); err != nil {
return nil, fmt.Errorf("failed to read HashAlgorithm: %v", err)
}
var s byte
if err := binary.Read(r, binary.BigEndian, &s); err != nil {
return nil, fmt.Errorf("failed to read SignatureAlgorithm: %v", err)
}
sig, err := readVarBytes(r, SignatureLengthBytes)
if err != nil {
return nil, fmt.Errorf("failed to read Signature bytes: %v", err)
}
return &DigitallySigned{
HashAlgorithm: HashAlgorithm(h),
SignatureAlgorithm: SignatureAlgorithm(s),
Signature: sig,
}, nil
}
func marshalDigitallySignedHere(ds DigitallySigned, here []byte) ([]byte, error) {
sigLen := len(ds.Signature)
dsOutLen := 2 + SignatureLengthBytes + sigLen
if here == nil {
here = make([]byte, dsOutLen)
}
if len(here) < dsOutLen {
return nil, ErrNotEnoughBuffer
}
here = here[0:dsOutLen]
here[0] = byte(ds.HashAlgorithm)
here[1] = byte(ds.SignatureAlgorithm)
binary.BigEndian.PutUint16(here[2:4], uint16(sigLen))
copy(here[4:], ds.Signature)
return here, nil
}
// MarshalDigitallySigned marshalls a DigitallySigned structure into a byte array
func MarshalDigitallySigned(ds DigitallySigned) ([]byte, error) {
return marshalDigitallySignedHere(ds, nil)
}
func deserializeSCTV1(r io.Reader, sct *SignedCertificateTimestamp) error {
if err := binary.Read(r, binary.BigEndian, &sct.LogID); err != nil {
return err
}
if err := binary.Read(r, binary.BigEndian, &sct.Timestamp); err != nil {
return err
}
ext, err := readVarBytes(r, ExtensionsLengthBytes)
if err != nil {
return err
}
sct.Extensions = ext
ds, err := UnmarshalDigitallySigned(r)
if err != nil {
return err
}
sct.Signature = *ds
return nil
}
func DeserializeSCT(r io.Reader) (*SignedCertificateTimestamp, error) {
var sct SignedCertificateTimestamp
if err := binary.Read(r, binary.BigEndian, &sct.SCTVersion); err != nil {
return nil, err
}
switch sct.SCTVersion {
case V1:
return &sct, deserializeSCTV1(r, &sct)
default:
return nil, fmt.Errorf("unknown SCT version %d", sct.SCTVersion)
}
}

213
vendor/github.com/zmap/zcrypto/x509/ct/types.go generated vendored Normal file
View File

@ -0,0 +1,213 @@
package ct
// This file contains selectively chosen snippets of
// github.com/google/certificate-transparency-go@ 5cfe585726ad9d990d4db524d6ce2567b13e2f80
//
// These snippets only perform deserialization for SCTs and are recreated here to prevent pulling in the whole of the ct
// which contains yet another version of x509,asn1 and tls
import (
"bytes"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"fmt"
)
// CTExtensions is a representation of the raw bytes of any CtExtension
// structure (see section 3.2)
type CTExtensions []byte
// SHA256Hash represents the output from the SHA256 hash function.
type SHA256Hash [sha256.Size]byte
// FromBase64String populates the SHA256 struct with the contents of the base64 data passed in.
func (s *SHA256Hash) FromBase64String(b64 string) error {
bs, err := base64.StdEncoding.DecodeString(b64)
if err != nil {
return fmt.Errorf("failed to unbase64 LogID: %v", err)
}
if len(bs) != sha256.Size {
return fmt.Errorf("invalid SHA256 length, expected 32 but got %d", len(bs))
}
copy(s[:], bs)
return nil
}
// Base64String returns the base64 representation of this SHA256Hash.
func (s SHA256Hash) Base64String() string {
return base64.StdEncoding.EncodeToString(s[:])
}
// MarshalJSON implements the json.Marshaller interface for SHA256Hash.
func (s SHA256Hash) MarshalJSON() ([]byte, error) {
return []byte(`"` + s.Base64String() + `"`), nil
}
// UnmarshalJSON implements the json.Unmarshaller interface.
func (s *SHA256Hash) UnmarshalJSON(b []byte) error {
var content string
if err := json.Unmarshal(b, &content); err != nil {
return fmt.Errorf("failed to unmarshal SHA256Hash: %v", err)
}
return s.FromBase64String(content)
}
// HashAlgorithm from the DigitallySigned struct
type HashAlgorithm byte
// HashAlgorithm constants
const (
None HashAlgorithm = 0
MD5 HashAlgorithm = 1
SHA1 HashAlgorithm = 2
SHA224 HashAlgorithm = 3
SHA256 HashAlgorithm = 4
SHA384 HashAlgorithm = 5
SHA512 HashAlgorithm = 6
)
func (h HashAlgorithm) String() string {
switch h {
case None:
return "None"
case MD5:
return "MD5"
case SHA1:
return "SHA1"
case SHA224:
return "SHA224"
case SHA256:
return "SHA256"
case SHA384:
return "SHA384"
case SHA512:
return "SHA512"
default:
return fmt.Sprintf("UNKNOWN(%d)", h)
}
}
// SignatureAlgorithm from the the DigitallySigned struct
type SignatureAlgorithm byte
// SignatureAlgorithm constants
const (
Anonymous SignatureAlgorithm = 0
RSA SignatureAlgorithm = 1
DSA SignatureAlgorithm = 2
ECDSA SignatureAlgorithm = 3
)
func (s SignatureAlgorithm) String() string {
switch s {
case Anonymous:
return "Anonymous"
case RSA:
return "RSA"
case DSA:
return "DSA"
case ECDSA:
return "ECDSA"
default:
return fmt.Sprintf("UNKNOWN(%d)", s)
}
}
// DigitallySigned represents an RFC5246 DigitallySigned structure
type DigitallySigned struct {
HashAlgorithm HashAlgorithm
SignatureAlgorithm SignatureAlgorithm
Signature []byte
}
// FromBase64String populates the DigitallySigned structure from the base64 data passed in.
// Returns an error if the base64 data is invalid.
func (d *DigitallySigned) FromBase64String(b64 string) error {
raw, err := base64.StdEncoding.DecodeString(b64)
if err != nil {
return fmt.Errorf("failed to unbase64 DigitallySigned: %v", err)
}
ds, err := UnmarshalDigitallySigned(bytes.NewReader(raw))
if err != nil {
return fmt.Errorf("failed to unmarshal DigitallySigned: %v", err)
}
*d = *ds
return nil
}
// Base64String returns the base64 representation of the DigitallySigned struct.
func (d DigitallySigned) Base64String() (string, error) {
b, err := MarshalDigitallySigned(d)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(b), nil
}
// MarshalJSON implements the json.Marshaller interface.
func (d DigitallySigned) MarshalJSON() ([]byte, error) {
b64, err := d.Base64String()
if err != nil {
return []byte{}, err
}
return []byte(`"` + b64 + `"`), nil
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (d *DigitallySigned) UnmarshalJSON(b []byte) error {
var content string
if err := json.Unmarshal(b, &content); err != nil {
return fmt.Errorf("failed to unmarshal DigitallySigned: %v", err)
}
return d.FromBase64String(content)
}
// Version represents the Version enum from section 3.2 of the RFC:
// enum { v1(0), (255) } Version;
type Version uint8
func (v Version) String() string {
switch v {
case V1:
return "V1"
default:
return fmt.Sprintf("UnknownVersion(%d)", v)
}
}
// CT Version constants, see section 3.2 of the RFC.
const (
V1 Version = 0
)
// SignedCertificateTimestamp represents the structure returned by the
// add-chain and add-pre-chain methods after base64 decoding. (see RFC sections
// 3.2 ,4.1 and 4.2)
type SignedCertificateTimestamp struct {
SCTVersion Version `json:"version"` // The version of the protocol to which the SCT conforms
LogID SHA256Hash `json:"log_id"` // the SHA-256 hash of the log's public key, calculated over
// the DER encoding of the key represented as SubjectPublicKeyInfo.
Timestamp uint64 `json:"timestamp,omitempty"` // Timestamp (in ms since unix epoc) at which the SCT was issued
Extensions CTExtensions `json:"extensions,omitempty"` // For future extensions to the protocol
Signature DigitallySigned `json:"signature"` // The Log's signature for this SCT
}
type sctError int
// Preallocate errors for performance
var (
ErrInvalidVersion error = sctError(1)
ErrNotEnoughBuffer error = sctError(2)
)
func (e sctError) Error() string {
switch e {
case ErrInvalidVersion:
return "invalid SCT version detected"
case ErrNotEnoughBuffer:
return "provided buffer was too small"
default:
return "unknown error"
}
}

65
vendor/github.com/zmap/zcrypto/x509/example.json generated vendored Normal file
View File

@ -0,0 +1,65 @@
{
"domain": null,
"certificate": {
"version": 3,
"serial_number": 123893,
"signature_algorithm": {
"id": 123,
"name": "SHA1"
},
"issuer": {
"common_name": "Starfield CA",
"attributes": [
{ "organization": "Startfield" },
{ "location": "Scottsdale" },
{ "state": "Arizona" },
{ "country": "US" }
]
},
"validity": {
"start": "20140102",
"end": "20150102",
"length" :8760
},
"subject": {
"common_name": "*.tools.ieft.org",
"attributes": [
{ "organization_unit": "Domain Control Validated" }
]
},
"subject_key_info": {
"algorithm": {
"id": 234,
"name": "RSA"
},
"key": {
"modulus": "base64encodedmodulus",
"exponent": 65537
}
},
"extensions": [
{
"id": 345,
"name": "Certificate Basic Constraints",
"is_ca": false
},
{
"id": 456,
"name": "Alt Names",
"alt_names": [
"*.tools.ietf.org",
"tools.ietf.org"
]
}
]
},
"signature_algorithm": {
"id": 123,
"name": "SHA1"
},
"signature": {
"value": "base64encodedsignature",
"is_valid": true,
"matches_domain": null
}
}

View File

@ -0,0 +1,665 @@
// Created by extended_key_usage_gen; DO NOT EDIT
// 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.
package x509
import (
"encoding/asn1"
)
const (
OID_EKU_APPLE_CODE_SIGNING = "1.2.840.113635.100.4.1"
OID_EKU_APPLE_CRYPTO_ENV = "1.2.840.113635.100.4.5"
OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE = "1.3.6.1.4.1.311.47.1.3"
OID_EKU_ANY = "2.5.29.37.0"
OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV = "1.2.840.113635.100.4.5.2"
OID_EKU_IPSEC_TUNNEL = "1.3.6.1.5.5.7.3.6"
OID_EKU_MICROSOFT_LIFETIME_SIGNING = "1.3.6.1.4.1.311.10.3.13"
OID_EKU_MICROSOFT_CSP_SIGNATURE = "1.3.6.1.4.1.311.10.3.16"
OID_EKU_MICROSOFT_SGC_SERIALIZED = "1.3.6.1.4.1.311.10.3.3.1"
OID_EKU_SBGP_CERT_AA_SERVICE_AUTH = "1.3.6.1.5.5.7.3.11"
OID_EKU_EAP_OVER_LAN = "1.3.6.1.5.5.7.3.14"
OID_EKU_APPLE_SYSTEM_IDENTITY = "1.2.840.113635.100.4.4"
OID_EKU_MICROSOFT_KEY_RECOVERY_3 = "1.3.6.1.4.1.311.10.3.11"
OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING = "1.3.6.1.4.1.311.10.3.1"
OID_EKU_MICROSOFT_DRM = "1.3.6.1.4.1.311.10.5.1"
OID_EKU_MICROSOFT_LICENSES = "1.3.6.1.4.1.311.10.5.3"
OID_EKU_MICROSOFT_LICENSE_SERVER = "1.3.6.1.4.1.311.10.5.4"
OID_EKU_MICROSOFT_ENROLLMENT_AGENT = "1.3.6.1.4.1.311.20.2.1"
OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING = "1.2.840.113635.100.4.1.2"
OID_EKU_APPLE_CRYPTO_TEST_ENV = "1.2.840.113635.100.4.5.3"
OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO = "1.3.6.1.4.1.311.10.3.8"
OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION = "1.3.6.1.4.1.311.10.5.2"
OID_EKU_MICROSOFT_KEY_RECOVERY_21 = "1.3.6.1.4.1.311.21.6"
OID_EKU_EAP_OVER_PPP = "1.3.6.1.5.5.7.3.13"
OID_EKU_OCSP_SIGNING = "1.3.6.1.5.5.7.3.9"
OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV = "1.2.840.113635.100.4.5.1"
OID_EKU_APPLE_CRYPTO_TIER1_QOS = "1.2.840.113635.100.4.6.2"
OID_EKU_CLIENT_AUTH = "1.3.6.1.5.5.7.3.2"
OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV = "1.2.840.113635.100.4.5.4"
OID_EKU_APPLE_CRYPTO_TIER0_QOS = "1.2.840.113635.100.4.6.1"
OID_EKU_APPLE_CRYPTO_TIER2_QOS = "1.2.840.113635.100.4.6.3"
OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE = "1.3.6.1.4.1.311.10.3.14"
OID_EKU_MICROSOFT_NT5_CRYPTO = "1.3.6.1.4.1.311.10.3.6"
OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3"
OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY = "1.2.840.113635.100.4.1.3"
OID_EKU_MICROSOFT_TIMESTAMP_SIGNING = "1.3.6.1.4.1.311.10.3.2"
OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT = "1.2.840.113635.100.4.1.1"
OID_EKU_APPLE_CRYPTO_QOS = "1.2.840.113635.100.4.6"
OID_EKU_MICROSOFT_DOCUMENT_SIGNING = "1.3.6.1.4.1.311.10.3.12"
OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM = "1.3.6.1.4.1.311.10.3.4"
OID_EKU_MICROSOFT_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.5"
OID_EKU_MICROSOFT_ROOT_LIST_SIGNER = "1.3.6.1.4.1.311.10.3.9"
OID_EKU_MICROSOFT_SYSTEM_HEALTH = "1.3.6.1.4.1.311.47.1.1"
OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8"
OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO = "2.16.840.1.113730.4.1"
OID_EKU_APPLE_CRYPTO_TIER3_QOS = "1.2.840.113635.100.4.6.4"
OID_EKU_MICROSOFT_SMART_DISPLAY = "1.3.6.1.4.1.311.10.3.15"
OID_EKU_MICROSOFT_EFS_RECOVERY = "1.3.6.1.4.1.311.10.3.4.1"
OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING = "1.3.6.1.4.1.311.61.1.1"
OID_EKU_SERVER_AUTH = "1.3.6.1.5.5.7.3.1"
OID_EKU_IPSEC_END_SYSTEM = "1.3.6.1.5.5.7.3.5"
OID_EKU_IPSEC_USER = "1.3.6.1.5.5.7.3.7"
OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE = "1.3.6.1.4.1.311.10.3.10"
OID_EKU_APPLE_RESOURCE_SIGNING = "1.2.840.113635.100.4.1.4"
OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO = "1.3.6.1.4.1.311.10.3.7"
OID_EKU_MICROSOFT_SMARTCARD_LOGON = "1.3.6.1.4.1.311.20.2.2"
OID_EKU_EMAIL_PROTECTION = "1.3.6.1.5.5.7.3.4"
OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO = "1.3.6.1.4.1.311.10.3.3"
OID_EKU_MICROSOFT_CA_EXCHANGE = "1.3.6.1.4.1.311.21.5"
OID_EKU_DVCS = "1.3.6.1.5.5.7.3.10"
OID_EKU_APPLE_ICHAT_SIGNING = "1.2.840.113635.100.4.2"
OID_EKU_APPLE_ICHAT_ENCRYPTION = "1.2.840.113635.100.4.3"
)
var (
oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
oidExtKeyUsageAppleCodeSigningDevelopment = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 1}
oidExtKeyUsageAppleCryptoQos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6}
oidExtKeyUsageMicrosoftDocumentSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 12}
oidExtKeyUsageMicrosoftEncryptedFileSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 4}
oidExtKeyUsageMicrosoftWhqlCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 5}
oidExtKeyUsageMicrosoftRootListSigner = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 9}
oidExtKeyUsageMicrosoftSystemHealth = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 47, 1, 1}
oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1}
oidExtKeyUsageAppleCryptoTier3Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 4}
oidExtKeyUsageMicrosoftSmartDisplay = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 15}
oidExtKeyUsageMicrosoftEfsRecovery = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 4, 1}
oidExtKeyUsageMicrosoftKernelModeCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 61, 1, 1}
oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
oidExtKeyUsageIpsecEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}
oidExtKeyUsageIpsecUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}
oidExtKeyUsageMicrosoftQualifiedSubordinate = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 10}
oidExtKeyUsageAppleResourceSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 4}
oidExtKeyUsageMicrosoftOemWhqlCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 7}
oidExtKeyUsageMicrosoftSmartcardLogon = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 20, 2, 2}
oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3}
oidExtKeyUsageMicrosoftCaExchange = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 21, 5}
oidExtKeyUsageDvcs = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 10}
oidExtKeyUsageAppleIchatSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 2}
oidExtKeyUsageAppleIchatEncryption = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 3}
oidExtKeyUsageAppleCodeSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1}
oidExtKeyUsageAppleCryptoEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5}
oidExtKeyUsageMicrosoftSystemHealthLoophole = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 47, 1, 3}
oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
oidExtKeyUsageAppleCryptoMaintenanceEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 2}
oidExtKeyUsageIpsecTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}
oidExtKeyUsageMicrosoftLifetimeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 13}
oidExtKeyUsageMicrosoftCspSignature = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 16}
oidExtKeyUsageMicrosoftSgcSerialized = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3, 1}
oidExtKeyUsageSbgpCertAaServiceAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 11}
oidExtKeyUsageEapOverLan = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 14}
oidExtKeyUsageAppleSystemIdentity = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 4}
oidExtKeyUsageMicrosoftKeyRecovery3 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 11}
oidExtKeyUsageMicrosoftCertTrustListSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 1}
oidExtKeyUsageMicrosoftDrm = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 1}
oidExtKeyUsageMicrosoftLicenses = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 3}
oidExtKeyUsageMicrosoftLicenseServer = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 4}
oidExtKeyUsageMicrosoftEnrollmentAgent = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 20, 2, 1}
oidExtKeyUsageAppleSoftwareUpdateSigning = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 2}
oidExtKeyUsageAppleCryptoTestEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 3}
oidExtKeyUsageMicrosoftEmbeddedNtCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 8}
oidExtKeyUsageMicrosoftDrmIndividualization = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 5, 2}
oidExtKeyUsageMicrosoftKeyRecovery21 = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 21, 6}
oidExtKeyUsageEapOverPpp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 13}
oidExtKeyUsageOcspSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
oidExtKeyUsageAppleCryptoProductionEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 1}
oidExtKeyUsageAppleCryptoTier1Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 2}
oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
oidExtKeyUsageAppleCryptoDevelopmentEnv = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 5, 4}
oidExtKeyUsageAppleCryptoTier0Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 1}
oidExtKeyUsageAppleCryptoTier2Qos = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 6, 3}
oidExtKeyUsageMicrosoftMobileDeviceSoftware = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 14}
oidExtKeyUsageMicrosoftNt5Crypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 6}
oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
oidExtKeyUsageAppleCodeSigningThirdParty = asn1.ObjectIdentifier{1, 2, 840, 113635, 100, 4, 1, 3}
oidExtKeyUsageMicrosoftTimestampSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 2}
)
const (
ExtKeyUsageAppleResourceSigning ExtKeyUsage = iota
ExtKeyUsageMicrosoftOemWhqlCrypto
ExtKeyUsageMicrosoftSmartcardLogon
ExtKeyUsageEmailProtection
ExtKeyUsageMicrosoftServerGatedCrypto
ExtKeyUsageMicrosoftCaExchange
ExtKeyUsageDvcs
ExtKeyUsageAppleIchatSigning
ExtKeyUsageAppleIchatEncryption
ExtKeyUsageAppleCodeSigning
ExtKeyUsageAppleCryptoEnv
ExtKeyUsageMicrosoftSystemHealthLoophole
ExtKeyUsageAny
ExtKeyUsageAppleCryptoMaintenanceEnv
ExtKeyUsageIpsecTunnel
ExtKeyUsageMicrosoftLifetimeSigning
ExtKeyUsageMicrosoftCspSignature
ExtKeyUsageMicrosoftSgcSerialized
ExtKeyUsageSbgpCertAaServiceAuth
ExtKeyUsageEapOverLan
ExtKeyUsageMicrosoftEnrollmentAgent
ExtKeyUsageAppleSystemIdentity
ExtKeyUsageMicrosoftKeyRecovery3
ExtKeyUsageMicrosoftCertTrustListSigning
ExtKeyUsageMicrosoftDrm
ExtKeyUsageMicrosoftLicenses
ExtKeyUsageMicrosoftLicenseServer
ExtKeyUsageOcspSigning
ExtKeyUsageAppleSoftwareUpdateSigning
ExtKeyUsageAppleCryptoTestEnv
ExtKeyUsageMicrosoftEmbeddedNtCrypto
ExtKeyUsageMicrosoftDrmIndividualization
ExtKeyUsageMicrosoftKeyRecovery21
ExtKeyUsageEapOverPpp
ExtKeyUsageAppleCryptoProductionEnv
ExtKeyUsageAppleCryptoTier1Qos
ExtKeyUsageClientAuth
ExtKeyUsageAppleCryptoDevelopmentEnv
ExtKeyUsageAppleCryptoTier0Qos
ExtKeyUsageAppleCryptoTier2Qos
ExtKeyUsageMicrosoftMobileDeviceSoftware
ExtKeyUsageMicrosoftNt5Crypto
ExtKeyUsageCodeSigning
ExtKeyUsageAppleCodeSigningThirdParty
ExtKeyUsageMicrosoftTimestampSigning
ExtKeyUsageMicrosoftSystemHealth
ExtKeyUsageTimeStamping
ExtKeyUsageAppleCodeSigningDevelopment
ExtKeyUsageAppleCryptoQos
ExtKeyUsageMicrosoftDocumentSigning
ExtKeyUsageMicrosoftEncryptedFileSystem
ExtKeyUsageMicrosoftWhqlCrypto
ExtKeyUsageMicrosoftRootListSigner
ExtKeyUsageNetscapeServerGatedCrypto
ExtKeyUsageAppleCryptoTier3Qos
ExtKeyUsageMicrosoftSmartDisplay
ExtKeyUsageMicrosoftEfsRecovery
ExtKeyUsageMicrosoftKernelModeCodeSigning
ExtKeyUsageServerAuth
ExtKeyUsageIpsecEndSystem
ExtKeyUsageIpsecUser
ExtKeyUsageMicrosoftQualifiedSubordinate
)
type auxExtendedKeyUsage struct {
EapOverPpp bool `json:"eap_over_ppp,omitempty" oid:"1.3.6.1.5.5.7.3.13"`
OcspSigning bool `json:"ocsp_signing,omitempty" oid:"1.3.6.1.5.5.7.3.9"`
AppleSoftwareUpdateSigning bool `json:"apple_software_update_signing,omitempty" oid:"1.2.840.113635.100.4.1.2"`
AppleCryptoTestEnv bool `json:"apple_crypto_test_env,omitempty" oid:"1.2.840.113635.100.4.5.3"`
MicrosoftEmbeddedNtCrypto bool `json:"microsoft_embedded_nt_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.8"`
MicrosoftDrmIndividualization bool `json:"microsoft_drm_individualization,omitempty" oid:"1.3.6.1.4.1.311.10.5.2"`
MicrosoftKeyRecovery21 bool `json:"microsoft_key_recovery_21,omitempty" oid:"1.3.6.1.4.1.311.21.6"`
AppleCryptoProductionEnv bool `json:"apple_crypto_production_env,omitempty" oid:"1.2.840.113635.100.4.5.1"`
AppleCryptoTier1Qos bool `json:"apple_crypto_tier1_qos,omitempty" oid:"1.2.840.113635.100.4.6.2"`
ClientAuth bool `json:"client_auth,omitempty" oid:"1.3.6.1.5.5.7.3.2"`
CodeSigning bool `json:"code_signing,omitempty" oid:"1.3.6.1.5.5.7.3.3"`
AppleCryptoDevelopmentEnv bool `json:"apple_crypto_development_env,omitempty" oid:"1.2.840.113635.100.4.5.4"`
AppleCryptoTier0Qos bool `json:"apple_crypto_tier0_qos,omitempty" oid:"1.2.840.113635.100.4.6.1"`
AppleCryptoTier2Qos bool `json:"apple_crypto_tier2_qos,omitempty" oid:"1.2.840.113635.100.4.6.3"`
MicrosoftMobileDeviceSoftware bool `json:"microsoft_mobile_device_software,omitempty" oid:"1.3.6.1.4.1.311.10.3.14"`
MicrosoftNt5Crypto bool `json:"microsoft_nt5_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.6"`
AppleCodeSigningThirdParty bool `json:"apple_code_signing_third_party,omitempty" oid:"1.2.840.113635.100.4.1.3"`
MicrosoftTimestampSigning bool `json:"microsoft_timestamp_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.2"`
MicrosoftRootListSigner bool `json:"microsoft_root_list_signer,omitempty" oid:"1.3.6.1.4.1.311.10.3.9"`
MicrosoftSystemHealth bool `json:"microsoft_system_health,omitempty" oid:"1.3.6.1.4.1.311.47.1.1"`
TimeStamping bool `json:"time_stamping,omitempty" oid:"1.3.6.1.5.5.7.3.8"`
AppleCodeSigningDevelopment bool `json:"apple_code_signing_development,omitempty" oid:"1.2.840.113635.100.4.1.1"`
AppleCryptoQos bool `json:"apple_crypto_qos,omitempty" oid:"1.2.840.113635.100.4.6"`
MicrosoftDocumentSigning bool `json:"microsoft_document_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.12"`
MicrosoftEncryptedFileSystem bool `json:"microsoft_encrypted_file_system,omitempty" oid:"1.3.6.1.4.1.311.10.3.4"`
MicrosoftWhqlCrypto bool `json:"microsoft_whql_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.5"`
NetscapeServerGatedCrypto bool `json:"netscape_server_gated_crypto,omitempty" oid:"2.16.840.1.113730.4.1"`
AppleCryptoTier3Qos bool `json:"apple_crypto_tier3_qos,omitempty" oid:"1.2.840.113635.100.4.6.4"`
MicrosoftSmartDisplay bool `json:"microsoft_smart_display,omitempty" oid:"1.3.6.1.4.1.311.10.3.15"`
MicrosoftEfsRecovery bool `json:"microsoft_efs_recovery,omitempty" oid:"1.3.6.1.4.1.311.10.3.4.1"`
MicrosoftKernelModeCodeSigning bool `json:"microsoft_kernel_mode_code_signing,omitempty" oid:"1.3.6.1.4.1.311.61.1.1"`
ServerAuth bool `json:"server_auth,omitempty" oid:"1.3.6.1.5.5.7.3.1"`
IpsecEndSystem bool `json:"ipsec_end_system,omitempty" oid:"1.3.6.1.5.5.7.3.5"`
IpsecUser bool `json:"ipsec_user,omitempty" oid:"1.3.6.1.5.5.7.3.7"`
MicrosoftQualifiedSubordinate bool `json:"microsoft_qualified_subordinate,omitempty" oid:"1.3.6.1.4.1.311.10.3.10"`
AppleResourceSigning bool `json:"apple_resource_signing,omitempty" oid:"1.2.840.113635.100.4.1.4"`
MicrosoftOemWhqlCrypto bool `json:"microsoft_oem_whql_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.7"`
MicrosoftSmartcardLogon bool `json:"microsoft_smartcard_logon,omitempty" oid:"1.3.6.1.4.1.311.20.2.2"`
EmailProtection bool `json:"email_protection,omitempty" oid:"1.3.6.1.5.5.7.3.4"`
MicrosoftServerGatedCrypto bool `json:"microsoft_server_gated_crypto,omitempty" oid:"1.3.6.1.4.1.311.10.3.3"`
MicrosoftCaExchange bool `json:"microsoft_ca_exchange,omitempty" oid:"1.3.6.1.4.1.311.21.5"`
Dvcs bool `json:"dvcs,omitempty" oid:"1.3.6.1.5.5.7.3.10"`
AppleIchatSigning bool `json:"apple_ichat_signing,omitempty" oid:"1.2.840.113635.100.4.2"`
AppleIchatEncryption bool `json:"apple_ichat_encryption,omitempty" oid:"1.2.840.113635.100.4.3"`
AppleCodeSigning bool `json:"apple_code_signing,omitempty" oid:"1.2.840.113635.100.4.1"`
AppleCryptoEnv bool `json:"apple_crypto_env,omitempty" oid:"1.2.840.113635.100.4.5"`
MicrosoftSystemHealthLoophole bool `json:"microsoft_system_health_loophole,omitempty" oid:"1.3.6.1.4.1.311.47.1.3"`
Any bool `json:"any,omitempty" oid:"2.5.29.37.0"`
AppleCryptoMaintenanceEnv bool `json:"apple_crypto_maintenance_env,omitempty" oid:"1.2.840.113635.100.4.5.2"`
IpsecTunnel bool `json:"ipsec_tunnel,omitempty" oid:"1.3.6.1.5.5.7.3.6"`
MicrosoftLifetimeSigning bool `json:"microsoft_lifetime_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.13"`
MicrosoftCspSignature bool `json:"microsoft_csp_signature,omitempty" oid:"1.3.6.1.4.1.311.10.3.16"`
MicrosoftSgcSerialized bool `json:"microsoft_sgc_serialized,omitempty" oid:"1.3.6.1.4.1.311.10.3.3.1"`
SbgpCertAaServiceAuth bool `json:"sbgp_cert_aa_service_auth,omitempty" oid:"1.3.6.1.5.5.7.3.11"`
EapOverLan bool `json:"eap_over_lan,omitempty" oid:"1.3.6.1.5.5.7.3.14"`
MicrosoftLicenseServer bool `json:"microsoft_license_server,omitempty" oid:"1.3.6.1.4.1.311.10.5.4"`
MicrosoftEnrollmentAgent bool `json:"microsoft_enrollment_agent,omitempty" oid:"1.3.6.1.4.1.311.20.2.1"`
AppleSystemIdentity bool `json:"apple_system_identity,omitempty" oid:"1.2.840.113635.100.4.4"`
MicrosoftKeyRecovery3 bool `json:"microsoft_key_recovery_3,omitempty" oid:"1.3.6.1.4.1.311.10.3.11"`
MicrosoftCertTrustListSigning bool `json:"microsoft_cert_trust_list_signing,omitempty" oid:"1.3.6.1.4.1.311.10.3.1"`
MicrosoftDrm bool `json:"microsoft_drm,omitempty" oid:"1.3.6.1.4.1.311.10.5.1"`
MicrosoftLicenses bool `json:"microsoft_licenses,omitempty" oid:"1.3.6.1.4.1.311.10.5.3"`
Unknown []string `json:"unknown,omitempty"`}
func (aux *auxExtendedKeyUsage) populateFromASN1(oid asn1.ObjectIdentifier) {
s := oid.String()
switch s {
case OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO:
aux.MicrosoftEmbeddedNtCrypto = true
case OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION:
aux.MicrosoftDrmIndividualization = true
case OID_EKU_MICROSOFT_KEY_RECOVERY_21:
aux.MicrosoftKeyRecovery21 = true
case OID_EKU_EAP_OVER_PPP:
aux.EapOverPpp = true
case OID_EKU_OCSP_SIGNING:
aux.OcspSigning = true
case OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING:
aux.AppleSoftwareUpdateSigning = true
case OID_EKU_APPLE_CRYPTO_TEST_ENV:
aux.AppleCryptoTestEnv = true
case OID_EKU_CLIENT_AUTH:
aux.ClientAuth = true
case OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV:
aux.AppleCryptoProductionEnv = true
case OID_EKU_APPLE_CRYPTO_TIER1_QOS:
aux.AppleCryptoTier1Qos = true
case OID_EKU_APPLE_CRYPTO_TIER2_QOS:
aux.AppleCryptoTier2Qos = true
case OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE:
aux.MicrosoftMobileDeviceSoftware = true
case OID_EKU_MICROSOFT_NT5_CRYPTO:
aux.MicrosoftNt5Crypto = true
case OID_EKU_CODE_SIGNING:
aux.CodeSigning = true
case OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV:
aux.AppleCryptoDevelopmentEnv = true
case OID_EKU_APPLE_CRYPTO_TIER0_QOS:
aux.AppleCryptoTier0Qos = true
case OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY:
aux.AppleCodeSigningThirdParty = true
case OID_EKU_MICROSOFT_TIMESTAMP_SIGNING:
aux.MicrosoftTimestampSigning = true
case OID_EKU_MICROSOFT_DOCUMENT_SIGNING:
aux.MicrosoftDocumentSigning = true
case OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM:
aux.MicrosoftEncryptedFileSystem = true
case OID_EKU_MICROSOFT_WHQL_CRYPTO:
aux.MicrosoftWhqlCrypto = true
case OID_EKU_MICROSOFT_ROOT_LIST_SIGNER:
aux.MicrosoftRootListSigner = true
case OID_EKU_MICROSOFT_SYSTEM_HEALTH:
aux.MicrosoftSystemHealth = true
case OID_EKU_TIME_STAMPING:
aux.TimeStamping = true
case OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT:
aux.AppleCodeSigningDevelopment = true
case OID_EKU_APPLE_CRYPTO_QOS:
aux.AppleCryptoQos = true
case OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO:
aux.NetscapeServerGatedCrypto = true
case OID_EKU_APPLE_CRYPTO_TIER3_QOS:
aux.AppleCryptoTier3Qos = true
case OID_EKU_MICROSOFT_SMART_DISPLAY:
aux.MicrosoftSmartDisplay = true
case OID_EKU_SERVER_AUTH:
aux.ServerAuth = true
case OID_EKU_IPSEC_END_SYSTEM:
aux.IpsecEndSystem = true
case OID_EKU_IPSEC_USER:
aux.IpsecUser = true
case OID_EKU_MICROSOFT_EFS_RECOVERY:
aux.MicrosoftEfsRecovery = true
case OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING:
aux.MicrosoftKernelModeCodeSigning = true
case OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE:
aux.MicrosoftQualifiedSubordinate = true
case OID_EKU_MICROSOFT_SMARTCARD_LOGON:
aux.MicrosoftSmartcardLogon = true
case OID_EKU_EMAIL_PROTECTION:
aux.EmailProtection = true
case OID_EKU_APPLE_RESOURCE_SIGNING:
aux.AppleResourceSigning = true
case OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO:
aux.MicrosoftOemWhqlCrypto = true
case OID_EKU_DVCS:
aux.Dvcs = true
case OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO:
aux.MicrosoftServerGatedCrypto = true
case OID_EKU_MICROSOFT_CA_EXCHANGE:
aux.MicrosoftCaExchange = true
case OID_EKU_APPLE_ICHAT_SIGNING:
aux.AppleIchatSigning = true
case OID_EKU_APPLE_ICHAT_ENCRYPTION:
aux.AppleIchatEncryption = true
case OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE:
aux.MicrosoftSystemHealthLoophole = true
case OID_EKU_ANY:
aux.Any = true
case OID_EKU_APPLE_CODE_SIGNING:
aux.AppleCodeSigning = true
case OID_EKU_APPLE_CRYPTO_ENV:
aux.AppleCryptoEnv = true
case OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV:
aux.AppleCryptoMaintenanceEnv = true
case OID_EKU_IPSEC_TUNNEL:
aux.IpsecTunnel = true
case OID_EKU_MICROSOFT_SGC_SERIALIZED:
aux.MicrosoftSgcSerialized = true
case OID_EKU_SBGP_CERT_AA_SERVICE_AUTH:
aux.SbgpCertAaServiceAuth = true
case OID_EKU_EAP_OVER_LAN:
aux.EapOverLan = true
case OID_EKU_MICROSOFT_LIFETIME_SIGNING:
aux.MicrosoftLifetimeSigning = true
case OID_EKU_MICROSOFT_CSP_SIGNATURE:
aux.MicrosoftCspSignature = true
case OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING:
aux.MicrosoftCertTrustListSigning = true
case OID_EKU_MICROSOFT_DRM:
aux.MicrosoftDrm = true
case OID_EKU_MICROSOFT_LICENSES:
aux.MicrosoftLicenses = true
case OID_EKU_MICROSOFT_LICENSE_SERVER:
aux.MicrosoftLicenseServer = true
case OID_EKU_MICROSOFT_ENROLLMENT_AGENT:
aux.MicrosoftEnrollmentAgent = true
case OID_EKU_APPLE_SYSTEM_IDENTITY:
aux.AppleSystemIdentity = true
case OID_EKU_MICROSOFT_KEY_RECOVERY_3:
aux.MicrosoftKeyRecovery3 = true
default:
}
return}
func (aux *auxExtendedKeyUsage) populateFromExtKeyUsage(eku ExtKeyUsage) {
switch eku {
case ExtKeyUsageAppleCryptoProductionEnv:
aux.AppleCryptoProductionEnv = true
case ExtKeyUsageAppleCryptoTier1Qos:
aux.AppleCryptoTier1Qos = true
case ExtKeyUsageClientAuth:
aux.ClientAuth = true
case ExtKeyUsageMicrosoftMobileDeviceSoftware:
aux.MicrosoftMobileDeviceSoftware = true
case ExtKeyUsageMicrosoftNt5Crypto:
aux.MicrosoftNt5Crypto = true
case ExtKeyUsageCodeSigning:
aux.CodeSigning = true
case ExtKeyUsageAppleCryptoDevelopmentEnv:
aux.AppleCryptoDevelopmentEnv = true
case ExtKeyUsageAppleCryptoTier0Qos:
aux.AppleCryptoTier0Qos = true
case ExtKeyUsageAppleCryptoTier2Qos:
aux.AppleCryptoTier2Qos = true
case ExtKeyUsageAppleCodeSigningThirdParty:
aux.AppleCodeSigningThirdParty = true
case ExtKeyUsageMicrosoftTimestampSigning:
aux.MicrosoftTimestampSigning = true
case ExtKeyUsageMicrosoftEncryptedFileSystem:
aux.MicrosoftEncryptedFileSystem = true
case ExtKeyUsageMicrosoftWhqlCrypto:
aux.MicrosoftWhqlCrypto = true
case ExtKeyUsageMicrosoftRootListSigner:
aux.MicrosoftRootListSigner = true
case ExtKeyUsageMicrosoftSystemHealth:
aux.MicrosoftSystemHealth = true
case ExtKeyUsageTimeStamping:
aux.TimeStamping = true
case ExtKeyUsageAppleCodeSigningDevelopment:
aux.AppleCodeSigningDevelopment = true
case ExtKeyUsageAppleCryptoQos:
aux.AppleCryptoQos = true
case ExtKeyUsageMicrosoftDocumentSigning:
aux.MicrosoftDocumentSigning = true
case ExtKeyUsageNetscapeServerGatedCrypto:
aux.NetscapeServerGatedCrypto = true
case ExtKeyUsageAppleCryptoTier3Qos:
aux.AppleCryptoTier3Qos = true
case ExtKeyUsageMicrosoftSmartDisplay:
aux.MicrosoftSmartDisplay = true
case ExtKeyUsageIpsecEndSystem:
aux.IpsecEndSystem = true
case ExtKeyUsageIpsecUser:
aux.IpsecUser = true
case ExtKeyUsageMicrosoftEfsRecovery:
aux.MicrosoftEfsRecovery = true
case ExtKeyUsageMicrosoftKernelModeCodeSigning:
aux.MicrosoftKernelModeCodeSigning = true
case ExtKeyUsageServerAuth:
aux.ServerAuth = true
case ExtKeyUsageMicrosoftQualifiedSubordinate:
aux.MicrosoftQualifiedSubordinate = true
case ExtKeyUsageEmailProtection:
aux.EmailProtection = true
case ExtKeyUsageAppleResourceSigning:
aux.AppleResourceSigning = true
case ExtKeyUsageMicrosoftOemWhqlCrypto:
aux.MicrosoftOemWhqlCrypto = true
case ExtKeyUsageMicrosoftSmartcardLogon:
aux.MicrosoftSmartcardLogon = true
case ExtKeyUsageMicrosoftServerGatedCrypto:
aux.MicrosoftServerGatedCrypto = true
case ExtKeyUsageMicrosoftCaExchange:
aux.MicrosoftCaExchange = true
case ExtKeyUsageDvcs:
aux.Dvcs = true
case ExtKeyUsageAppleIchatSigning:
aux.AppleIchatSigning = true
case ExtKeyUsageAppleIchatEncryption:
aux.AppleIchatEncryption = true
case ExtKeyUsageAny:
aux.Any = true
case ExtKeyUsageAppleCodeSigning:
aux.AppleCodeSigning = true
case ExtKeyUsageAppleCryptoEnv:
aux.AppleCryptoEnv = true
case ExtKeyUsageMicrosoftSystemHealthLoophole:
aux.MicrosoftSystemHealthLoophole = true
case ExtKeyUsageAppleCryptoMaintenanceEnv:
aux.AppleCryptoMaintenanceEnv = true
case ExtKeyUsageIpsecTunnel:
aux.IpsecTunnel = true
case ExtKeyUsageSbgpCertAaServiceAuth:
aux.SbgpCertAaServiceAuth = true
case ExtKeyUsageEapOverLan:
aux.EapOverLan = true
case ExtKeyUsageMicrosoftLifetimeSigning:
aux.MicrosoftLifetimeSigning = true
case ExtKeyUsageMicrosoftCspSignature:
aux.MicrosoftCspSignature = true
case ExtKeyUsageMicrosoftSgcSerialized:
aux.MicrosoftSgcSerialized = true
case ExtKeyUsageMicrosoftDrm:
aux.MicrosoftDrm = true
case ExtKeyUsageMicrosoftLicenses:
aux.MicrosoftLicenses = true
case ExtKeyUsageMicrosoftLicenseServer:
aux.MicrosoftLicenseServer = true
case ExtKeyUsageMicrosoftEnrollmentAgent:
aux.MicrosoftEnrollmentAgent = true
case ExtKeyUsageAppleSystemIdentity:
aux.AppleSystemIdentity = true
case ExtKeyUsageMicrosoftKeyRecovery3:
aux.MicrosoftKeyRecovery3 = true
case ExtKeyUsageMicrosoftCertTrustListSigning:
aux.MicrosoftCertTrustListSigning = true
case ExtKeyUsageMicrosoftDrmIndividualization:
aux.MicrosoftDrmIndividualization = true
case ExtKeyUsageMicrosoftKeyRecovery21:
aux.MicrosoftKeyRecovery21 = true
case ExtKeyUsageEapOverPpp:
aux.EapOverPpp = true
case ExtKeyUsageOcspSigning:
aux.OcspSigning = true
case ExtKeyUsageAppleSoftwareUpdateSigning:
aux.AppleSoftwareUpdateSigning = true
case ExtKeyUsageAppleCryptoTestEnv:
aux.AppleCryptoTestEnv = true
case ExtKeyUsageMicrosoftEmbeddedNtCrypto:
aux.MicrosoftEmbeddedNtCrypto = true
default:
}
return}
var ekuOIDs map[string]asn1.ObjectIdentifier
var ekuConstants map[string]ExtKeyUsage
func init() {
ekuOIDs = make(map[string]asn1.ObjectIdentifier)
ekuOIDs[OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV] = oidExtKeyUsageAppleCryptoDevelopmentEnv
ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER0_QOS] = oidExtKeyUsageAppleCryptoTier0Qos
ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER2_QOS] = oidExtKeyUsageAppleCryptoTier2Qos
ekuOIDs[OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE] = oidExtKeyUsageMicrosoftMobileDeviceSoftware
ekuOIDs[OID_EKU_MICROSOFT_NT5_CRYPTO] = oidExtKeyUsageMicrosoftNt5Crypto
ekuOIDs[OID_EKU_CODE_SIGNING] = oidExtKeyUsageCodeSigning
ekuOIDs[OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY] = oidExtKeyUsageAppleCodeSigningThirdParty
ekuOIDs[OID_EKU_MICROSOFT_TIMESTAMP_SIGNING] = oidExtKeyUsageMicrosoftTimestampSigning
ekuOIDs[OID_EKU_MICROSOFT_SYSTEM_HEALTH] = oidExtKeyUsageMicrosoftSystemHealth
ekuOIDs[OID_EKU_TIME_STAMPING] = oidExtKeyUsageTimeStamping
ekuOIDs[OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT] = oidExtKeyUsageAppleCodeSigningDevelopment
ekuOIDs[OID_EKU_APPLE_CRYPTO_QOS] = oidExtKeyUsageAppleCryptoQos
ekuOIDs[OID_EKU_MICROSOFT_DOCUMENT_SIGNING] = oidExtKeyUsageMicrosoftDocumentSigning
ekuOIDs[OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM] = oidExtKeyUsageMicrosoftEncryptedFileSystem
ekuOIDs[OID_EKU_MICROSOFT_WHQL_CRYPTO] = oidExtKeyUsageMicrosoftWhqlCrypto
ekuOIDs[OID_EKU_MICROSOFT_ROOT_LIST_SIGNER] = oidExtKeyUsageMicrosoftRootListSigner
ekuOIDs[OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO] = oidExtKeyUsageNetscapeServerGatedCrypto
ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER3_QOS] = oidExtKeyUsageAppleCryptoTier3Qos
ekuOIDs[OID_EKU_MICROSOFT_SMART_DISPLAY] = oidExtKeyUsageMicrosoftSmartDisplay
ekuOIDs[OID_EKU_MICROSOFT_EFS_RECOVERY] = oidExtKeyUsageMicrosoftEfsRecovery
ekuOIDs[OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING] = oidExtKeyUsageMicrosoftKernelModeCodeSigning
ekuOIDs[OID_EKU_SERVER_AUTH] = oidExtKeyUsageServerAuth
ekuOIDs[OID_EKU_IPSEC_END_SYSTEM] = oidExtKeyUsageIpsecEndSystem
ekuOIDs[OID_EKU_IPSEC_USER] = oidExtKeyUsageIpsecUser
ekuOIDs[OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE] = oidExtKeyUsageMicrosoftQualifiedSubordinate
ekuOIDs[OID_EKU_APPLE_RESOURCE_SIGNING] = oidExtKeyUsageAppleResourceSigning
ekuOIDs[OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO] = oidExtKeyUsageMicrosoftOemWhqlCrypto
ekuOIDs[OID_EKU_MICROSOFT_SMARTCARD_LOGON] = oidExtKeyUsageMicrosoftSmartcardLogon
ekuOIDs[OID_EKU_EMAIL_PROTECTION] = oidExtKeyUsageEmailProtection
ekuOIDs[OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO] = oidExtKeyUsageMicrosoftServerGatedCrypto
ekuOIDs[OID_EKU_MICROSOFT_CA_EXCHANGE] = oidExtKeyUsageMicrosoftCaExchange
ekuOIDs[OID_EKU_DVCS] = oidExtKeyUsageDvcs
ekuOIDs[OID_EKU_APPLE_ICHAT_SIGNING] = oidExtKeyUsageAppleIchatSigning
ekuOIDs[OID_EKU_APPLE_ICHAT_ENCRYPTION] = oidExtKeyUsageAppleIchatEncryption
ekuOIDs[OID_EKU_APPLE_CODE_SIGNING] = oidExtKeyUsageAppleCodeSigning
ekuOIDs[OID_EKU_APPLE_CRYPTO_ENV] = oidExtKeyUsageAppleCryptoEnv
ekuOIDs[OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE] = oidExtKeyUsageMicrosoftSystemHealthLoophole
ekuOIDs[OID_EKU_ANY] = oidExtKeyUsageAny
ekuOIDs[OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV] = oidExtKeyUsageAppleCryptoMaintenanceEnv
ekuOIDs[OID_EKU_IPSEC_TUNNEL] = oidExtKeyUsageIpsecTunnel
ekuOIDs[OID_EKU_MICROSOFT_LIFETIME_SIGNING] = oidExtKeyUsageMicrosoftLifetimeSigning
ekuOIDs[OID_EKU_MICROSOFT_CSP_SIGNATURE] = oidExtKeyUsageMicrosoftCspSignature
ekuOIDs[OID_EKU_MICROSOFT_SGC_SERIALIZED] = oidExtKeyUsageMicrosoftSgcSerialized
ekuOIDs[OID_EKU_SBGP_CERT_AA_SERVICE_AUTH] = oidExtKeyUsageSbgpCertAaServiceAuth
ekuOIDs[OID_EKU_EAP_OVER_LAN] = oidExtKeyUsageEapOverLan
ekuOIDs[OID_EKU_MICROSOFT_ENROLLMENT_AGENT] = oidExtKeyUsageMicrosoftEnrollmentAgent
ekuOIDs[OID_EKU_APPLE_SYSTEM_IDENTITY] = oidExtKeyUsageAppleSystemIdentity
ekuOIDs[OID_EKU_MICROSOFT_KEY_RECOVERY_3] = oidExtKeyUsageMicrosoftKeyRecovery3
ekuOIDs[OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING] = oidExtKeyUsageMicrosoftCertTrustListSigning
ekuOIDs[OID_EKU_MICROSOFT_DRM] = oidExtKeyUsageMicrosoftDrm
ekuOIDs[OID_EKU_MICROSOFT_LICENSES] = oidExtKeyUsageMicrosoftLicenses
ekuOIDs[OID_EKU_MICROSOFT_LICENSE_SERVER] = oidExtKeyUsageMicrosoftLicenseServer
ekuOIDs[OID_EKU_OCSP_SIGNING] = oidExtKeyUsageOcspSigning
ekuOIDs[OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING] = oidExtKeyUsageAppleSoftwareUpdateSigning
ekuOIDs[OID_EKU_APPLE_CRYPTO_TEST_ENV] = oidExtKeyUsageAppleCryptoTestEnv
ekuOIDs[OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO] = oidExtKeyUsageMicrosoftEmbeddedNtCrypto
ekuOIDs[OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION] = oidExtKeyUsageMicrosoftDrmIndividualization
ekuOIDs[OID_EKU_MICROSOFT_KEY_RECOVERY_21] = oidExtKeyUsageMicrosoftKeyRecovery21
ekuOIDs[OID_EKU_EAP_OVER_PPP] = oidExtKeyUsageEapOverPpp
ekuOIDs[OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV] = oidExtKeyUsageAppleCryptoProductionEnv
ekuOIDs[OID_EKU_APPLE_CRYPTO_TIER1_QOS] = oidExtKeyUsageAppleCryptoTier1Qos
ekuOIDs[OID_EKU_CLIENT_AUTH] = oidExtKeyUsageClientAuth
ekuConstants = make(map[string]ExtKeyUsage)
ekuConstants[OID_EKU_APPLE_ICHAT_SIGNING] = ExtKeyUsageAppleIchatSigning
ekuConstants[OID_EKU_APPLE_ICHAT_ENCRYPTION] = ExtKeyUsageAppleIchatEncryption
ekuConstants[OID_EKU_MICROSOFT_SYSTEM_HEALTH_LOOPHOLE] = ExtKeyUsageMicrosoftSystemHealthLoophole
ekuConstants[OID_EKU_ANY] = ExtKeyUsageAny
ekuConstants[OID_EKU_APPLE_CODE_SIGNING] = ExtKeyUsageAppleCodeSigning
ekuConstants[OID_EKU_APPLE_CRYPTO_ENV] = ExtKeyUsageAppleCryptoEnv
ekuConstants[OID_EKU_APPLE_CRYPTO_MAINTENANCE_ENV] = ExtKeyUsageAppleCryptoMaintenanceEnv
ekuConstants[OID_EKU_IPSEC_TUNNEL] = ExtKeyUsageIpsecTunnel
ekuConstants[OID_EKU_MICROSOFT_SGC_SERIALIZED] = ExtKeyUsageMicrosoftSgcSerialized
ekuConstants[OID_EKU_SBGP_CERT_AA_SERVICE_AUTH] = ExtKeyUsageSbgpCertAaServiceAuth
ekuConstants[OID_EKU_EAP_OVER_LAN] = ExtKeyUsageEapOverLan
ekuConstants[OID_EKU_MICROSOFT_LIFETIME_SIGNING] = ExtKeyUsageMicrosoftLifetimeSigning
ekuConstants[OID_EKU_MICROSOFT_CSP_SIGNATURE] = ExtKeyUsageMicrosoftCspSignature
ekuConstants[OID_EKU_MICROSOFT_CERT_TRUST_LIST_SIGNING] = ExtKeyUsageMicrosoftCertTrustListSigning
ekuConstants[OID_EKU_MICROSOFT_DRM] = ExtKeyUsageMicrosoftDrm
ekuConstants[OID_EKU_MICROSOFT_LICENSES] = ExtKeyUsageMicrosoftLicenses
ekuConstants[OID_EKU_MICROSOFT_LICENSE_SERVER] = ExtKeyUsageMicrosoftLicenseServer
ekuConstants[OID_EKU_MICROSOFT_ENROLLMENT_AGENT] = ExtKeyUsageMicrosoftEnrollmentAgent
ekuConstants[OID_EKU_APPLE_SYSTEM_IDENTITY] = ExtKeyUsageAppleSystemIdentity
ekuConstants[OID_EKU_MICROSOFT_KEY_RECOVERY_3] = ExtKeyUsageMicrosoftKeyRecovery3
ekuConstants[OID_EKU_MICROSOFT_EMBEDDED_NT_CRYPTO] = ExtKeyUsageMicrosoftEmbeddedNtCrypto
ekuConstants[OID_EKU_MICROSOFT_DRM_INDIVIDUALIZATION] = ExtKeyUsageMicrosoftDrmIndividualization
ekuConstants[OID_EKU_MICROSOFT_KEY_RECOVERY_21] = ExtKeyUsageMicrosoftKeyRecovery21
ekuConstants[OID_EKU_EAP_OVER_PPP] = ExtKeyUsageEapOverPpp
ekuConstants[OID_EKU_OCSP_SIGNING] = ExtKeyUsageOcspSigning
ekuConstants[OID_EKU_APPLE_SOFTWARE_UPDATE_SIGNING] = ExtKeyUsageAppleSoftwareUpdateSigning
ekuConstants[OID_EKU_APPLE_CRYPTO_TEST_ENV] = ExtKeyUsageAppleCryptoTestEnv
ekuConstants[OID_EKU_CLIENT_AUTH] = ExtKeyUsageClientAuth
ekuConstants[OID_EKU_APPLE_CRYPTO_PRODUCTION_ENV] = ExtKeyUsageAppleCryptoProductionEnv
ekuConstants[OID_EKU_APPLE_CRYPTO_TIER1_QOS] = ExtKeyUsageAppleCryptoTier1Qos
ekuConstants[OID_EKU_APPLE_CRYPTO_TIER2_QOS] = ExtKeyUsageAppleCryptoTier2Qos
ekuConstants[OID_EKU_MICROSOFT_MOBILE_DEVICE_SOFTWARE] = ExtKeyUsageMicrosoftMobileDeviceSoftware
ekuConstants[OID_EKU_MICROSOFT_NT5_CRYPTO] = ExtKeyUsageMicrosoftNt5Crypto
ekuConstants[OID_EKU_CODE_SIGNING] = ExtKeyUsageCodeSigning
ekuConstants[OID_EKU_APPLE_CRYPTO_DEVELOPMENT_ENV] = ExtKeyUsageAppleCryptoDevelopmentEnv
ekuConstants[OID_EKU_APPLE_CRYPTO_TIER0_QOS] = ExtKeyUsageAppleCryptoTier0Qos
ekuConstants[OID_EKU_APPLE_CODE_SIGNING_THIRD_PARTY] = ExtKeyUsageAppleCodeSigningThirdParty
ekuConstants[OID_EKU_MICROSOFT_TIMESTAMP_SIGNING] = ExtKeyUsageMicrosoftTimestampSigning
ekuConstants[OID_EKU_MICROSOFT_DOCUMENT_SIGNING] = ExtKeyUsageMicrosoftDocumentSigning
ekuConstants[OID_EKU_MICROSOFT_ENCRYPTED_FILE_SYSTEM] = ExtKeyUsageMicrosoftEncryptedFileSystem
ekuConstants[OID_EKU_MICROSOFT_WHQL_CRYPTO] = ExtKeyUsageMicrosoftWhqlCrypto
ekuConstants[OID_EKU_MICROSOFT_ROOT_LIST_SIGNER] = ExtKeyUsageMicrosoftRootListSigner
ekuConstants[OID_EKU_MICROSOFT_SYSTEM_HEALTH] = ExtKeyUsageMicrosoftSystemHealth
ekuConstants[OID_EKU_TIME_STAMPING] = ExtKeyUsageTimeStamping
ekuConstants[OID_EKU_APPLE_CODE_SIGNING_DEVELOPMENT] = ExtKeyUsageAppleCodeSigningDevelopment
ekuConstants[OID_EKU_APPLE_CRYPTO_QOS] = ExtKeyUsageAppleCryptoQos
ekuConstants[OID_EKU_NETSCAPE_SERVER_GATED_CRYPTO] = ExtKeyUsageNetscapeServerGatedCrypto
ekuConstants[OID_EKU_APPLE_CRYPTO_TIER3_QOS] = ExtKeyUsageAppleCryptoTier3Qos
ekuConstants[OID_EKU_MICROSOFT_SMART_DISPLAY] = ExtKeyUsageMicrosoftSmartDisplay
ekuConstants[OID_EKU_SERVER_AUTH] = ExtKeyUsageServerAuth
ekuConstants[OID_EKU_IPSEC_END_SYSTEM] = ExtKeyUsageIpsecEndSystem
ekuConstants[OID_EKU_IPSEC_USER] = ExtKeyUsageIpsecUser
ekuConstants[OID_EKU_MICROSOFT_EFS_RECOVERY] = ExtKeyUsageMicrosoftEfsRecovery
ekuConstants[OID_EKU_MICROSOFT_KERNEL_MODE_CODE_SIGNING] = ExtKeyUsageMicrosoftKernelModeCodeSigning
ekuConstants[OID_EKU_MICROSOFT_QUALIFIED_SUBORDINATE] = ExtKeyUsageMicrosoftQualifiedSubordinate
ekuConstants[OID_EKU_MICROSOFT_SMARTCARD_LOGON] = ExtKeyUsageMicrosoftSmartcardLogon
ekuConstants[OID_EKU_EMAIL_PROTECTION] = ExtKeyUsageEmailProtection
ekuConstants[OID_EKU_APPLE_RESOURCE_SIGNING] = ExtKeyUsageAppleResourceSigning
ekuConstants[OID_EKU_MICROSOFT_OEM_WHQL_CRYPTO] = ExtKeyUsageMicrosoftOemWhqlCrypto
ekuConstants[OID_EKU_DVCS] = ExtKeyUsageDvcs
ekuConstants[OID_EKU_MICROSOFT_SERVER_GATED_CRYPTO] = ExtKeyUsageMicrosoftServerGatedCrypto
ekuConstants[OID_EKU_MICROSOFT_CA_EXCHANGE] = ExtKeyUsageMicrosoftCaExchange
}

View File

@ -0,0 +1,300 @@
// The following directive is necessary to make the package coherent:
// +build ignore
// This program generates extended_key_usage.go. It can be invoked by running
// `$ go generate`
package main
import (
"bytes"
"encoding/csv"
"io"
"net/http"
"os"
"strings"
)
const (
COLUMN_IDX_OID = 0
COLUMN_IDX_SHORT_NAME = 2
)
const (
GO_PREFIX = "oidExtKeyUsage"
CONST_PREFIX = "OID_EKU"
)
type OID struct {
OID string
ShortName string
}
func (o *OID) OIDDecl() string {
parts := strings.Split(o.OID, ".")
buffer := bytes.Buffer{}
buffer.WriteString("asn1.ObjectIdentifier{")
for idx, p := range parts {
buffer.WriteString(p)
if idx != len(parts)-1 {
buffer.WriteString(", ")
}
}
buffer.WriteString("}")
return buffer.String()
}
func (o *OID) GoName(prefix string) string {
parts := strings.Split(o.ShortName, "-")
for idx, p := range parts {
if prefix == "" && idx == 0 {
continue
}
parts[idx] = strings.Title(p)
}
return prefix + strings.Join(parts, "")
}
func (o *OID) GoConstant(prefix string) string {
parts := strings.Split(o.ShortName, "-")
buffer := bytes.Buffer{}
if prefix != "" {
buffer.WriteString(strings.ToUpper(prefix))
buffer.WriteString("_")
}
for idx, p := range parts {
buffer.WriteString(strings.ToUpper(p))
if idx != len(parts)-1 {
buffer.WriteString("_")
}
}
return buffer.String()
}
func (o *OID) JSONName(prefix string) string {
parts := strings.Split(o.ShortName, "-")
buffer := bytes.Buffer{}
if prefix != "" {
buffer.WriteString(strings.ToLower(prefix))
buffer.WriteString("_")
}
for idx, p := range parts {
buffer.WriteString(strings.ToLower(p))
if idx != len(parts)-1 {
buffer.WriteString("_")
}
}
return buffer.String()
}
func (o *OID) StructFieldName() string {
parts := strings.Split(o.ShortName, "-")
buffer := bytes.Buffer{}
for _, p := range parts {
buffer.WriteString(strings.Title(p))
}
return buffer.String()
}
func writeHeader(out io.Writer) {
s := `// Created by extended_key_usage_gen; DO NOT EDIT
// 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.
package x509
import (
"encoding/asn1"
)
`
out.Write([]byte(s))
}
func generateASN1(oidToName map[string]OID) []byte {
buffer := bytes.Buffer{}
for _, oid := range oidToName {
goName := oid.GoName(GO_PREFIX)
oidDecl := oid.OIDDecl()
buffer.WriteString(goName)
buffer.WriteString(" = ")
buffer.WriteString(oidDecl)
buffer.WriteString("\n")
}
return buffer.Bytes()
}
func generateIntegerConstants(oidToName map[string]OID) []byte {
buffer := bytes.Buffer{}
buffer.WriteString("const (\n")
first := true
for _, oid := range oidToName {
goName := oid.GoName("ExtKeyUsage")
buffer.WriteString(goName)
if first {
buffer.WriteString(" ExtKeyUsage = iota")
first = false
}
buffer.WriteString("\n")
}
buffer.WriteString(")\n")
return buffer.Bytes()
}
func generateNameConstants(oidToName map[string]OID) []byte {
buffer := bytes.Buffer{}
for _, oid := range oidToName {
constantName := oid.GoConstant(CONST_PREFIX)
buffer.WriteString(constantName)
buffer.WriteString(" = \"")
buffer.WriteString(oid.OID)
buffer.WriteString("\"\n")
}
return buffer.Bytes()
}
func generateOIDMap(oidToName map[string]OID, mapName string) []byte {
buffer := bytes.Buffer{}
buffer.WriteString(mapName)
buffer.WriteString(" = make(map[string]asn1.ObjectIdentifier)\n")
for _, oid := range oidToName {
constantName := oid.GoConstant(CONST_PREFIX)
goName := oid.GoName(GO_PREFIX)
buffer.WriteString(mapName)
buffer.WriteString("[")
buffer.WriteString(constantName)
buffer.WriteString("] = ")
buffer.WriteString(goName)
buffer.WriteString("\n")
}
return buffer.Bytes()
}
func generateIntegerMap(oidToName map[string]OID, mapName string) []byte {
buffer := bytes.Buffer{}
buffer.WriteString(mapName)
buffer.WriteString(" = make(map[string]ExtKeyUsage)\n")
for _, oid := range oidToName {
constantName := oid.GoConstant(CONST_PREFIX)
goName := oid.GoName("ExtKeyUsage")
buffer.WriteString(mapName)
buffer.WriteString("[")
buffer.WriteString(constantName)
buffer.WriteString("] = ")
buffer.WriteString(goName)
buffer.WriteString("\n")
}
return buffer.Bytes()
}
func generateEKUJSONStruct(oidToName map[string]OID) []byte {
buffer := bytes.Buffer{}
buffer.WriteString("type auxExtendedKeyUsage struct {\n")
for _, oid := range oidToName {
buffer.WriteString(oid.StructFieldName())
buffer.WriteString(" bool `json:\"")
buffer.WriteString(oid.JSONName(""))
buffer.WriteString(",omitempty\"`\n")
}
buffer.WriteString("Unknown []string `json:\"unknown,omitempty\"`")
buffer.WriteString("}\n\n")
buffer.WriteString("func (aux *auxExtendedKeyUsage) populateFromASN1(oid asn1.ObjectIdentifier) {\n")
buffer.WriteString("s := oid.String()\n")
buffer.WriteString("switch s {\n")
for _, oid := range oidToName {
buffer.WriteString("case ")
constantName := oid.GoConstant(CONST_PREFIX)
buffer.WriteString(constantName)
buffer.WriteString(":\n")
buffer.WriteString("aux.")
buffer.WriteString(oid.StructFieldName())
buffer.WriteString(" = true\n")
}
buffer.WriteString("default:\n")
buffer.WriteString("}\n")
buffer.WriteString("return")
buffer.WriteString("}\n\n")
buffer.WriteString("func (aux *auxExtendedKeyUsage) populateFromExtKeyUsage(eku ExtKeyUsage) {\n")
buffer.WriteString("switch eku {\n")
for _, oid := range oidToName {
buffer.WriteString("case ")
ekuName := oid.GoName("ExtKeyUsage")
buffer.WriteString(ekuName)
buffer.WriteString(":\n")
buffer.WriteString("aux.")
buffer.WriteString(oid.StructFieldName())
buffer.WriteString(" = true\n")
}
buffer.WriteString("default:\n")
buffer.WriteString("}\n")
buffer.WriteString("return")
buffer.WriteString("}\n\n")
return buffer.Bytes()
}
func main() {
out, err := os.Create("extended_key_usage.go")
if err != nil {
panic(err.Error())
}
defer out.Close()
writeHeader(out)
resp, err := http.Get("https://raw.githubusercontent.com/zmap/constants/master/x509/extended_key_usage.csv")
if err != nil {
panic(err.Error())
}
defer resp.Body.Close()
oidToName := make(map[string]OID)
r := csv.NewReader(resp.Body)
for lines := 0; ; lines++ {
record, err := r.Read()
if err == io.EOF {
break
}
if err != nil {
panic(err.Error())
}
if lines == 0 {
// Header row
continue
}
oid := record[COLUMN_IDX_OID]
shortName := record[COLUMN_IDX_SHORT_NAME]
oidToName[oid] = OID{
OID: oid,
ShortName: shortName,
}
}
out.Write([]byte("const (\n"))
constants := generateNameConstants(oidToName)
out.Write(constants)
out.Write([]byte(")\n"))
out.Write([]byte("var (\n"))
oidDecls := generateASN1(oidToName)
out.Write(oidDecls)
out.Write([]byte(")\n"))
integersConstants := generateIntegerConstants(oidToName)
out.Write(integersConstants)
out.Write(generateEKUJSONStruct(oidToName))
out.Write([]byte("\nvar ekuOIDs map[string]asn1.ObjectIdentifier\n\n"))
out.Write([]byte("\nvar ekuConstants map[string]ExtKeyUsage\n\n"))
out.Write([]byte("func init() {\n"))
mapEntries := generateOIDMap(oidToName, "ekuOIDs")
out.Write(mapEntries)
out.Write([]byte("\n"))
intMapEntries := generateIntegerMap(oidToName, "ekuConstants")
out.Write(intMapEntries)
out.Write([]byte("}\n"))
}

View File

@ -0,0 +1,21 @@
#!/bin/bash
set -e
# TODO: This should really be generated by Go code as a subrecord, but
# importing in Python is hard. This is quick and dirty.
FIELDS=$(\
cat extended_key_usage.go |\
grep json |\
cut -d ':' -f 2 |\
sed 's|,omitempty||g' |\
tr -d '`')
echo "extended_key_usage = SubRecord({"
for f in $FIELDS; do
if [ $f == "\"unknown\"" ]; then
echo " $f: ListOf(OID())"
else
echo " $f: Boolean(),"
fi
done
echo "})"

765
vendor/github.com/zmap/zcrypto/x509/extensions.go generated vendored Normal file
View File

@ -0,0 +1,765 @@
// 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 (
"encoding/asn1"
"encoding/hex"
"encoding/json"
"net"
"strconv"
"strings"
"github.com/zmap/zcrypto/x509/ct"
"github.com/zmap/zcrypto/x509/pkix"
)
var (
oidExtKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 15}
oidExtBasicConstraints = asn1.ObjectIdentifier{2, 5, 29, 19}
oidExtSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17}
oidExtIssuerAltName = asn1.ObjectIdentifier{2, 5, 29, 18}
oidExtNameConstraints = asn1.ObjectIdentifier{2, 5, 29, 30}
oidCRLDistributionPoints = asn1.ObjectIdentifier{2, 5, 29, 31}
oidExtAuthKeyId = asn1.ObjectIdentifier{2, 5, 29, 35}
oidExtSubjectKeyId = asn1.ObjectIdentifier{2, 5, 29, 14}
oidExtExtendedKeyUsage = asn1.ObjectIdentifier{2, 5, 29, 37}
oidExtCertificatePolicy = asn1.ObjectIdentifier{2, 5, 29, 32}
oidExtAuthorityInfoAccess = oidExtensionAuthorityInfoAccess
oidExtensionCTPrecertificatePoison = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 11129, 2, 4, 3}
oidExtSignedCertificateTimestampList = oidExtensionSignedCertificateTimestampList
)
type encodedUnknownExtensions []encodedUnknownExtension
type CertificateExtensions struct {
KeyUsage KeyUsage `json:"key_usage,omitempty"`
BasicConstraints *BasicConstraints `json:"basic_constraints,omitempty"`
SubjectAltName *GeneralNames `json:"subject_alt_name,omitempty"`
IssuerAltName *GeneralNames `json:"issuer_alt_name,omitempty"`
NameConstraints *NameConstraints `json:"name_constraints,omitempty"`
CRLDistributionPoints CRLDistributionPoints `json:"crl_distribution_points,omitempty"`
AuthKeyID SubjAuthKeyId `json:"authority_key_id,omitempty"`
SubjectKeyID SubjAuthKeyId `json:"subject_key_id,omitempty"`
ExtendedKeyUsage *ExtendedKeyUsageExtension `json:"extended_key_usage,omitempty"`
CertificatePolicies *CertificatePoliciesData `json:"certificate_policies,omitempty"`
AuthorityInfoAccess *AuthorityInfoAccess `json:"authority_info_access,omitempty"`
IsPrecert IsPrecert `json:"ct_poison,omitempty"`
SignedCertificateTimestampList []*ct.SignedCertificateTimestamp `json:"signed_certificate_timestamps,omitempty"`
}
type UnknownCertificateExtensions []pkix.Extension
type encodedUnknownExtension struct {
OID string `json:"oid"`
Critical bool `json:"critical"`
Value []byte `json:"raw,omitempty"`
}
type IsPrecert bool
type BasicConstraints struct {
IsCA bool `json:"is_ca"`
MaxPathLen *int `json:"max_path_len,omitempty"`
}
type NoticeReference struct {
Organization string `json:"organization,omitempty"`
NoticeNumbers NoticeNumber `json:"notice_numbers,omitempty"`
}
type UserNoticeData struct {
ExplicitText string `json:"explicit_text,omitempty"`
NoticeReference []NoticeReference `json:"notice_reference,omitempty"`
}
type CertificatePoliciesJSON struct {
PolicyIdentifier string `json:"id,omitempty"`
CPSUri []string `json:"cps,omitempty"`
UserNotice []UserNoticeData `json:"user_notice,omitempty"`
}
type CertificatePolicies []CertificatePoliciesJSON
type CertificatePoliciesData struct {
PolicyIdentifiers []asn1.ObjectIdentifier
QualifierId [][]asn1.ObjectIdentifier
CPSUri [][]string
ExplicitTexts [][]string
NoticeRefOrganization [][]string
NoticeRefNumbers [][]NoticeNumber
}
func (cp *CertificatePoliciesData) MarshalJSON() ([]byte, error) {
policies := CertificatePolicies{}
for idx, oid := range cp.PolicyIdentifiers {
cpsJSON := CertificatePoliciesJSON{}
cpsJSON.PolicyIdentifier = oid.String()
for _, uri := range cp.CPSUri[idx] {
cpsJSON.CPSUri = append(cpsJSON.CPSUri, uri)
}
for idx2, explicit_text := range cp.ExplicitTexts[idx] {
uNoticeData := UserNoticeData{}
uNoticeData.ExplicitText = explicit_text
noticeRef := NoticeReference{}
if len(cp.NoticeRefOrganization[idx]) > 0 {
organization := cp.NoticeRefOrganization[idx][idx2]
noticeRef.Organization = organization
noticeRef.NoticeNumbers = cp.NoticeRefNumbers[idx][idx2]
uNoticeData.NoticeReference = append(uNoticeData.NoticeReference, noticeRef)
}
cpsJSON.UserNotice = append(cpsJSON.UserNotice, uNoticeData)
}
policies = append(policies, cpsJSON)
}
return json.Marshal(policies)
}
// GeneralNames corresponds an X.509 GeneralName defined in
// Section 4.2.1.6 of RFC 5280.
//
// GeneralName ::= CHOICE {
// otherName [0] AnotherName,
// 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 }
type GeneralNames struct {
DirectoryNames []pkix.Name
DNSNames []string
EDIPartyNames []pkix.EDIPartyName
EmailAddresses []string
IPAddresses []net.IP
OtherNames []pkix.OtherName
RegisteredIDs []asn1.ObjectIdentifier
URIs []string
}
type jsonGeneralNames struct {
DirectoryNames []pkix.Name `json:"directory_names,omitempty"`
DNSNames []string `json:"dns_names,omitempty"`
EDIPartyNames []pkix.EDIPartyName `json:"edi_party_names,omitempty"`
EmailAddresses []string `json:"email_addresses,omitempty"`
IPAddresses []net.IP `json:"ip_addresses,omitempty"`
OtherNames []pkix.OtherName `json:"other_names,omitempty"`
RegisteredIDs []string `json:"registered_ids,omitempty"`
URIs []string `json:"uniform_resource_identifiers,omitempty"`
}
func (gn *GeneralNames) MarshalJSON() ([]byte, error) {
jsan := jsonGeneralNames{
DirectoryNames: gn.DirectoryNames,
DNSNames: gn.DNSNames,
EDIPartyNames: gn.EDIPartyNames,
EmailAddresses: gn.EmailAddresses,
IPAddresses: gn.IPAddresses,
OtherNames: gn.OtherNames,
RegisteredIDs: make([]string, 0, len(gn.RegisteredIDs)),
URIs: gn.URIs,
}
for _, id := range gn.RegisteredIDs {
jsan.RegisteredIDs = append(jsan.RegisteredIDs, id.String())
}
return json.Marshal(jsan)
}
func (gn *GeneralNames) UnmarshalJSON(b []byte) error {
var jsan jsonGeneralNames
err := json.Unmarshal(b, &jsan)
if err != nil {
return err
}
gn.DirectoryNames = jsan.DirectoryNames
gn.DNSNames = jsan.DNSNames
gn.EDIPartyNames = jsan.EDIPartyNames
gn.EmailAddresses = jsan.EmailAddresses
gn.IPAddresses = jsan.IPAddresses
gn.OtherNames = jsan.OtherNames
gn.RegisteredIDs = make([]asn1.ObjectIdentifier, len(jsan.RegisteredIDs))
gn.URIs = jsan.URIs
for i, rID := range jsan.RegisteredIDs {
arcs := strings.Split(rID, ".")
oid := make(asn1.ObjectIdentifier, len(arcs))
for j, s := range arcs {
tmp, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return err
}
oid[j] = int(tmp)
}
gn.RegisteredIDs[i] = oid
}
return nil
}
// TODO: Handle excluded names
type NameConstraints struct {
Critical bool `json:"critical"`
PermittedDNSNames []GeneralSubtreeString
PermittedEmailAddresses []GeneralSubtreeString
PermittedIPAddresses []GeneralSubtreeIP
PermittedDirectoryNames []GeneralSubtreeName
PermittedEdiPartyNames []GeneralSubtreeEdi
PermittedRegisteredIDs []GeneralSubtreeOid
ExcludedEmailAddresses []GeneralSubtreeString
ExcludedDNSNames []GeneralSubtreeString
ExcludedIPAddresses []GeneralSubtreeIP
ExcludedDirectoryNames []GeneralSubtreeName
ExcludedEdiPartyNames []GeneralSubtreeEdi
ExcludedRegisteredIDs []GeneralSubtreeOid
}
type NameConstraintsJSON struct {
Critical bool `json:"critical"`
PermittedDNSNames []string `json:"permitted_names,omitempty"`
PermittedEmailAddresses []string `json:"permitted_email_addresses,omitempty"`
PermittedIPAddresses []GeneralSubtreeIP `json:"permitted_ip_addresses,omitempty"`
PermittedDirectoryNames []pkix.Name `json:"permitted_directory_names,omitempty"`
PermittedEdiPartyNames []pkix.EDIPartyName `json:"permitted_edi_party_names,omitempty"`
PermittedRegisteredIDs []string `json:"permitted_registred_id,omitempty"`
ExcludedDNSNames []string `json:"excluded_names,omitempty"`
ExcludedEmailAddresses []string `json:"excluded_email_addresses,omitempty"`
ExcludedIPAddresses []GeneralSubtreeIP `json:"excluded_ip_addresses,omitempty"`
ExcludedDirectoryNames []pkix.Name `json:"excluded_directory_names,omitempty"`
ExcludedEdiPartyNames []pkix.EDIPartyName `json:"excluded_edi_party_names,omitempty"`
ExcludedRegisteredIDs []string `json:"excluded_registred_id,omitempty"`
}
func (nc *NameConstraints) UnmarshalJSON(b []byte) error {
var ncJson NameConstraintsJSON
err := json.Unmarshal(b, &ncJson)
if err != nil {
return err
}
for _, dns := range ncJson.PermittedDNSNames {
nc.PermittedDNSNames = append(nc.PermittedDNSNames, GeneralSubtreeString{Data: dns})
}
for _, email := range ncJson.PermittedEmailAddresses {
nc.PermittedEmailAddresses = append(nc.PermittedEmailAddresses, GeneralSubtreeString{Data: email})
}
for _, constraint := range ncJson.PermittedIPAddresses {
nc.PermittedIPAddresses = append(nc.PermittedIPAddresses, constraint)
}
for _, directory := range ncJson.PermittedDirectoryNames {
nc.PermittedDirectoryNames = append(nc.PermittedDirectoryNames, GeneralSubtreeName{Data: directory})
}
for _, edi := range ncJson.PermittedEdiPartyNames {
nc.PermittedEdiPartyNames = append(nc.PermittedEdiPartyNames, GeneralSubtreeEdi{Data: edi})
}
for _, id := range ncJson.PermittedRegisteredIDs {
arcs := strings.Split(id, ".")
oid := make(asn1.ObjectIdentifier, len(arcs))
for j, s := range arcs {
tmp, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return err
}
oid[j] = int(tmp)
}
nc.PermittedRegisteredIDs = append(nc.PermittedRegisteredIDs, GeneralSubtreeOid{Data: oid})
}
for _, dns := range ncJson.ExcludedDNSNames {
nc.ExcludedDNSNames = append(nc.ExcludedDNSNames, GeneralSubtreeString{Data: dns})
}
for _, email := range ncJson.ExcludedEmailAddresses {
nc.ExcludedEmailAddresses = append(nc.ExcludedEmailAddresses, GeneralSubtreeString{Data: email})
}
for _, constraint := range ncJson.ExcludedIPAddresses {
nc.ExcludedIPAddresses = append(nc.ExcludedIPAddresses, constraint)
}
for _, directory := range ncJson.ExcludedDirectoryNames {
nc.ExcludedDirectoryNames = append(nc.ExcludedDirectoryNames, GeneralSubtreeName{Data: directory})
}
for _, edi := range ncJson.ExcludedEdiPartyNames {
nc.ExcludedEdiPartyNames = append(nc.ExcludedEdiPartyNames, GeneralSubtreeEdi{Data: edi})
}
for _, id := range ncJson.ExcludedRegisteredIDs {
arcs := strings.Split(id, ".")
oid := make(asn1.ObjectIdentifier, len(arcs))
for j, s := range arcs {
tmp, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return err
}
oid[j] = int(tmp)
}
nc.ExcludedRegisteredIDs = append(nc.ExcludedRegisteredIDs, GeneralSubtreeOid{Data: oid})
}
return nil
}
func (nc NameConstraints) MarshalJSON() ([]byte, error) {
var out NameConstraintsJSON
for _, dns := range nc.PermittedDNSNames {
out.PermittedDNSNames = append(out.PermittedDNSNames, dns.Data)
}
for _, email := range nc.PermittedEmailAddresses {
out.PermittedEmailAddresses = append(out.PermittedEmailAddresses, email.Data)
}
out.PermittedIPAddresses = nc.PermittedIPAddresses
for _, directory := range nc.PermittedDirectoryNames {
out.PermittedDirectoryNames = append(out.PermittedDirectoryNames, directory.Data)
}
for _, edi := range nc.PermittedEdiPartyNames {
out.PermittedEdiPartyNames = append(out.PermittedEdiPartyNames, edi.Data)
}
for _, id := range nc.PermittedRegisteredIDs {
out.PermittedRegisteredIDs = append(out.PermittedRegisteredIDs, id.Data.String())
}
for _, dns := range nc.ExcludedDNSNames {
out.ExcludedDNSNames = append(out.ExcludedDNSNames, dns.Data)
}
for _, email := range nc.ExcludedEmailAddresses {
out.ExcludedEmailAddresses = append(out.ExcludedEmailAddresses, email.Data)
}
for _, ip := range nc.ExcludedIPAddresses {
out.ExcludedIPAddresses = append(out.ExcludedIPAddresses, ip)
}
for _, directory := range nc.ExcludedDirectoryNames {
out.ExcludedDirectoryNames = append(out.ExcludedDirectoryNames, directory.Data)
}
for _, edi := range nc.ExcludedEdiPartyNames {
out.ExcludedEdiPartyNames = append(out.ExcludedEdiPartyNames, edi.Data)
}
for _, id := range nc.ExcludedRegisteredIDs {
out.ExcludedRegisteredIDs = append(out.ExcludedRegisteredIDs, id.Data.String())
}
return json.Marshal(out)
}
type CRLDistributionPoints []string
type SubjAuthKeyId []byte
func (kid SubjAuthKeyId) MarshalJSON() ([]byte, error) {
enc := hex.EncodeToString(kid)
return json.Marshal(enc)
}
type ExtendedKeyUsage []ExtKeyUsage
type ExtendedKeyUsageExtension struct {
Known ExtendedKeyUsage
Unknown []asn1.ObjectIdentifier
}
// MarshalJSON implements the json.Marshal interface. The output is a struct of
// bools, with an additional `Value` field containing the actual OIDs.
func (e *ExtendedKeyUsageExtension) MarshalJSON() ([]byte, error) {
aux := new(auxExtendedKeyUsage)
for _, e := range e.Known {
aux.populateFromExtKeyUsage(e)
}
for _, oid := range e.Unknown {
aux.Unknown = append(aux.Unknown, oid.String())
}
return json.Marshal(aux)
}
func (e *ExtendedKeyUsageExtension) UnmarshalJSON(b []byte) error {
aux := new(auxExtendedKeyUsage)
if err := json.Unmarshal(b, aux); err != nil {
return err
}
// TODO: Generate the reverse functions.
return nil
}
//go:generate go run extended_key_usage_gen.go
// The string functions for CertValidationLevel are auto-generated via
// `go generate <full_path_to_x509_package>` or running `go generate` in the package directory
//go:generate stringer -type=CertValidationLevel -output=generated_certvalidationlevel_string.go
type CertValidationLevel int
const (
UnknownValidationLevel CertValidationLevel = 0
DV CertValidationLevel = 1
OV CertValidationLevel = 2
EV CertValidationLevel = 3
)
func (c *CertValidationLevel) MarshalJSON() ([]byte, error) {
if *c == UnknownValidationLevel || *c < 0 || *c > EV {
return json.Marshal("unknown")
}
return json.Marshal(c.String())
}
// TODO: All of validation-level maps should be auto-generated from
// https://github.com/zmap/constants.
// ExtendedValidationOIDs contains the UNION of Chromium
// (https://chromium.googlesource.com/chromium/src/net/+/master/cert/ev_root_ca_metadata.cc)
// and Firefox
// (http://hg.mozilla.org/mozilla-central/file/tip/security/certverifier/ExtendedValidation.cpp)
// EV OID lists
var ExtendedValidationOIDs = map[string]interface{}{
// CA/Browser Forum EV OID standard
// https://cabforum.org/object-registry/
"2.23.140.1.1": nil,
// CA/Browser Forum EV Code Signing
"2.23.140.1.3": nil,
// CA/Browser Forum .onion EV Certs
"2.23.140.1.31": nil,
// AC Camerfirma S.A. Chambers of Commerce Root - 2008
// https://www.camerfirma.com
// AC Camerfirma uses the last two arcs to track how the private key
// is managed - the effective verification policy is the same.
"1.3.6.1.4.1.17326.10.14.2.1.2": nil,
"1.3.6.1.4.1.17326.10.14.2.2.2": nil,
// AC Camerfirma S.A. Global Chambersign Root - 2008
// https://server2.camerfirma.com:8082
// AC Camerfirma uses the last two arcs to track how the private key
// is managed - the effective verification policy is the same.
"1.3.6.1.4.1.17326.10.8.12.1.2": nil,
"1.3.6.1.4.1.17326.10.8.12.2.2": nil,
// Actalis Authentication Root CA
// https://ssltest-a.actalis.it:8443
"1.3.159.1.17.1": nil,
// AffirmTrust Commercial
// https://commercial.affirmtrust.com/
"1.3.6.1.4.1.34697.2.1": nil,
// AffirmTrust Networking
// https://networking.affirmtrust.com:4431
"1.3.6.1.4.1.34697.2.2": nil,
// AffirmTrust Premium
// https://premium.affirmtrust.com:4432/
"1.3.6.1.4.1.34697.2.3": nil,
// AffirmTrust Premium ECC
// https://premiumecc.affirmtrust.com:4433/
"1.3.6.1.4.1.34697.2.4": nil,
// Autoridad de Certificacion Firmaprofesional CIF A62634068
// https://publifirma.firmaprofesional.com/
"1.3.6.1.4.1.13177.10.1.3.10": nil,
// Buypass Class 3 CA 1
// https://valid.evident.ca13.ssl.buypass.no/
"2.16.578.1.26.1.3.3": nil,
// Certification Authority of WoSign
// CA 沃通根证书
// https://root2evtest.wosign.com/
"1.3.6.1.4.1.36305.2": nil,
// CertPlus Class 2 Primary CA (KEYNECTIS)
// https://www.keynectis.com/
"1.3.6.1.4.1.22234.2.5.2.3.1": nil,
// Certum Trusted Network CA
// https://juice.certum.pl/
"1.2.616.1.113527.2.5.1.1": nil,
// China Internet Network Information Center EV Certificates Root
// https://evdemo.cnnic.cn/
"1.3.6.1.4.1.29836.1.10": nil,
// COMODO Certification Authority & USERTrust RSA Certification Authority & UTN-USERFirst-Hardware & AddTrust External CA Root
// https://secure.comodo.com/
// https://usertrustrsacertificationauthority-ev.comodoca.com/
// https://addtrustexternalcaroot-ev.comodoca.com
"1.3.6.1.4.1.6449.1.2.1.5.1": nil,
// Cybertrust Global Root & GTE CyberTrust Global Root & Baltimore CyberTrust Root
// https://evup.cybertrust.ne.jp/ctj-ev-upgrader/evseal.gif
// https://www.cybertrust.ne.jp/
// https://secure.omniroot.com/repository/
"1.3.6.1.4.1.6334.1.100.1": nil,
// DigiCert High Assurance EV Root CA
// https://www.digicert.com
"2.16.840.1.114412.2.1": nil,
// D-TRUST Root Class 3 CA 2 EV 2009
// https://certdemo-ev-valid.ssl.d-trust.net/
"1.3.6.1.4.1.4788.2.202.1": nil,
// Entrust.net Secure Server Certification Authority
// https://www.entrust.net/
"2.16.840.1.114028.10.1.2": nil,
// E-Tugra Certification Authority
// https://sslev.e-tugra.com.tr
"2.16.792.3.0.4.1.1.4": nil,
// GeoTrust Primary Certification Authority
// https://www.geotrust.com/
"1.3.6.1.4.1.14370.1.6": nil,
// GlobalSign Root CA - R2
// https://www.globalsign.com/
"1.3.6.1.4.1.4146.1.1": nil,
// Go Daddy Class 2 Certification Authority & Go Daddy Root Certificate Authority - G2
// https://www.godaddy.com/
// https://valid.gdig2.catest.godaddy.com/
"2.16.840.1.114413.1.7.23.3": nil,
// Izenpe.com - SHA256 root
// The first OID is for businesses and the second for government entities.
// These are the test sites, respectively:
// https://servicios.izenpe.com
// https://servicios1.izenpe.com
// Windows XP finds this, SHA1, root instead. The policy OIDs are the same
// as for the SHA256 root, above.
"1.3.6.1.4.1.14777.6.1.1": nil,
"1.3.6.1.4.1.14777.6.1.2": nil,
// Network Solutions Certificate Authority
// https://www.networksolutions.com/website-packages/index.jsp
"1.3.6.1.4.1.782.1.2.1.8.1": nil,
// QuoVadis Root CA 2
// https://www.quovadis.bm/
"1.3.6.1.4.1.8024.0.2.100.1.2": nil,
// SecureTrust CA, SecureTrust Corporation
// https://www.securetrust.com
// https://www.trustwave.com/
"2.16.840.1.114404.1.1.2.4.1": nil,
// Security Communication RootCA1
// https://www.secomtrust.net/contact/form.html
"1.2.392.200091.100.721.1": nil,
// Staat der Nederlanden EV Root CA
// https://pkioevssl-v.quovadisglobal.com/
"2.16.528.1.1003.1.2.7": nil,
// StartCom Certification Authority
// https://www.startssl.com/
"1.3.6.1.4.1.23223.1.1.1": nil,
// Starfield Class 2 Certification Authority
// https://www.starfieldtech.com/
"2.16.840.1.114414.1.7.23.3": nil,
// Starfield Services Root Certificate Authority - G2
// https://valid.sfsg2.catest.starfieldtech.com/
"2.16.840.1.114414.1.7.24.3": nil,
// SwissSign Gold CA - G2
// https://testevg2.swisssign.net/
"2.16.756.1.89.1.2.1.1": nil,
// Swisscom Root EV CA 2
// https://test-quarz-ev-ca-2.pre.swissdigicert.ch
"2.16.756.1.83.21.0": nil,
// thawte Primary Root CA
// https://www.thawte.com/
"2.16.840.1.113733.1.7.48.1": nil,
// TWCA Global Root CA
// https://evssldemo3.twca.com.tw/index.html
"1.3.6.1.4.1.40869.1.1.22.3": nil,
// T-TeleSec GlobalRoot Class 3
// http://www.telesec.de/ / https://root-class3.test.telesec.de/
"1.3.6.1.4.1.7879.13.24.1": nil,
// VeriSign Class 3 Public Primary Certification Authority - G5
// https://www.verisign.com/
"2.16.840.1.113733.1.7.23.6": nil,
// Wells Fargo WellsSecure Public Root Certificate Authority
// https://nerys.wellsfargo.com/test.html
"2.16.840.1.114171.500.9": nil,
// CN=CFCA EV ROOT,O=China Financial Certification Authority,C=CN
// https://www.cfca.com.cn/
"2.16.156.112554.3": nil,
// CN=OISTE WISeKey Global Root GB CA,OU=OISTE Foundation Endorsed,O=WISeKey,C=CH
// https://www.wisekey.com/repository/cacertificates/
"2.16.756.5.14.7.4.8": nil,
// CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H6,O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A...,L=Ankara,C=TR
// https://www.turktrust.com.tr/
"2.16.792.3.0.3.1.1.5": nil,
}
// OrganizationValidationOIDs contains CA specific OV OIDs from
// https://cabforum.org/object-registry/
var OrganizationValidationOIDs = map[string]interface{}{
// CA/Browser Forum OV OID standard
// https://cabforum.org/object-registry/
"2.23.140.1.2.2": nil,
// CA/Browser Forum individually validated
"2.23.140.1.2.3": nil,
// Digicert
"2.16.840.1.114412.1.1": nil,
// D-Trust
"1.3.6.1.4.1.4788.2.200.1": nil,
// GoDaddy
"2.16.840.1.114413.1.7.23.2": nil,
// Logius
"2.16.528.1.1003.1.2.5.6": nil,
// QuoVadis
"1.3.6.1.4.1.8024.0.2.100.1.1": nil,
// Starfield
"2.16.840.1.114414.1.7.23.2": nil,
// TurkTrust
"2.16.792.3.0.3.1.1.2": nil,
}
// DomainValidationOIDs contain OIDs that identify DV certs.
var DomainValidationOIDs = map[string]interface{}{
// Globalsign
"1.3.6.1.4.1.4146.1.10.10": nil,
// Let's Encrypt
"1.3.6.1.4.1.44947.1.1.1": nil,
// Comodo (eNom)
"1.3.6.1.4.1.6449.1.2.2.10": nil,
// Comodo (WoTrust)
"1.3.6.1.4.1.6449.1.2.2.15": nil,
// Comodo (RBC SOFT)
"1.3.6.1.4.1.6449.1.2.2.16": nil,
// Comodo (RegisterFly)
"1.3.6.1.4.1.6449.1.2.2.17": nil,
// Comodo (Central Security Patrols)
"1.3.6.1.4.1.6449.1.2.2.18": nil,
// Comodo (eBiz Networks)
"1.3.6.1.4.1.6449.1.2.2.19": nil,
// Comodo (OptimumSSL)
"1.3.6.1.4.1.6449.1.2.2.21": nil,
// Comodo (WoSign)
"1.3.6.1.4.1.6449.1.2.2.22": nil,
// Comodo (Register.com)
"1.3.6.1.4.1.6449.1.2.2.24": nil,
// Comodo (The Code Project)
"1.3.6.1.4.1.6449.1.2.2.25": nil,
// Comodo (Gandi)
"1.3.6.1.4.1.6449.1.2.2.26": nil,
// Comodo (GlobeSSL)
"1.3.6.1.4.1.6449.1.2.2.27": nil,
// Comodo (DreamHost)
"1.3.6.1.4.1.6449.1.2.2.28": nil,
// Comodo (TERENA)
"1.3.6.1.4.1.6449.1.2.2.29": nil,
// Comodo (GlobalSSL)
"1.3.6.1.4.1.6449.1.2.2.31": nil,
// Comodo (IceWarp)
"1.3.6.1.4.1.6449.1.2.2.35": nil,
// Comodo (Dotname Korea)
"1.3.6.1.4.1.6449.1.2.2.37": nil,
// Comodo (TrustSign)
"1.3.6.1.4.1.6449.1.2.2.38": nil,
// Comodo (Formidable)
"1.3.6.1.4.1.6449.1.2.2.39": nil,
// Comodo (SSL Blindado)
"1.3.6.1.4.1.6449.1.2.2.40": nil,
// Comodo (Dreamscape Networks)
"1.3.6.1.4.1.6449.1.2.2.41": nil,
// Comodo (K Software)
"1.3.6.1.4.1.6449.1.2.2.42": nil,
// Comodo (FBS)
"1.3.6.1.4.1.6449.1.2.2.44": nil,
// Comodo (ReliaSite)
"1.3.6.1.4.1.6449.1.2.2.45": nil,
// Comodo (CertAssure)
"1.3.6.1.4.1.6449.1.2.2.47": nil,
// Comodo (TrustAsia)
"1.3.6.1.4.1.6449.1.2.2.49": nil,
// Comodo (SecureCore)
"1.3.6.1.4.1.6449.1.2.2.50": nil,
// Comodo (Western Digital)
"1.3.6.1.4.1.6449.1.2.2.51": nil,
// Comodo (cPanel)
"1.3.6.1.4.1.6449.1.2.2.52": nil,
// Comodo (BlackCert)
"1.3.6.1.4.1.6449.1.2.2.53": nil,
// Comodo (KeyNet Systems)
"1.3.6.1.4.1.6449.1.2.2.54": nil,
// Comodo
"1.3.6.1.4.1.6449.1.2.2.7": nil,
// Comodo (CSC)
"1.3.6.1.4.1.6449.1.2.2.8": nil,
// Digicert
"2.16.840.1.114412.1.2": nil,
// GoDaddy
"2.16.840.1.114413.1.7.23.1": nil,
// Starfield
"2.16.840.1.114414.1.7.23.1": nil,
// CA/B Forum
"2.23.140.1.2.1": nil,
}
// TODO pull out other types
type AuthorityInfoAccess struct {
OCSPServer []string `json:"ocsp_urls,omitempty"`
IssuingCertificateURL []string `json:"issuer_urls,omitempty"`
}
func (c *Certificate) jsonifyExtensions() (*CertificateExtensions, UnknownCertificateExtensions) {
exts := new(CertificateExtensions)
unk := make([]pkix.Extension, 0, 2)
for _, e := range c.Extensions {
if e.Id.Equal(oidExtKeyUsage) {
exts.KeyUsage = c.KeyUsage
} else if e.Id.Equal(oidExtBasicConstraints) {
exts.BasicConstraints = new(BasicConstraints)
exts.BasicConstraints.IsCA = c.IsCA
if c.MaxPathLen > 0 || c.MaxPathLenZero {
exts.BasicConstraints.MaxPathLen = new(int)
*exts.BasicConstraints.MaxPathLen = c.MaxPathLen
}
} else if e.Id.Equal(oidExtSubjectAltName) {
exts.SubjectAltName = new(GeneralNames)
exts.SubjectAltName.DirectoryNames = c.DirectoryNames
exts.SubjectAltName.DNSNames = c.DNSNames
exts.SubjectAltName.EDIPartyNames = c.EDIPartyNames
exts.SubjectAltName.EmailAddresses = c.EmailAddresses
exts.SubjectAltName.IPAddresses = c.IPAddresses
exts.SubjectAltName.OtherNames = c.OtherNames
exts.SubjectAltName.RegisteredIDs = c.RegisteredIDs
exts.SubjectAltName.URIs = c.URIs
} else if e.Id.Equal(oidExtIssuerAltName) {
exts.IssuerAltName = new(GeneralNames)
exts.IssuerAltName.DirectoryNames = c.IANDirectoryNames
exts.IssuerAltName.DNSNames = c.IANDNSNames
exts.IssuerAltName.EDIPartyNames = c.IANEDIPartyNames
exts.IssuerAltName.EmailAddresses = c.IANEmailAddresses
exts.IssuerAltName.IPAddresses = c.IANIPAddresses
exts.IssuerAltName.OtherNames = c.IANOtherNames
exts.IssuerAltName.RegisteredIDs = c.IANRegisteredIDs
exts.IssuerAltName.URIs = c.IANURIs
} else if e.Id.Equal(oidExtNameConstraints) {
exts.NameConstraints = new(NameConstraints)
exts.NameConstraints.Critical = c.NameConstraintsCritical
exts.NameConstraints.PermittedDNSNames = c.PermittedDNSNames
exts.NameConstraints.PermittedEmailAddresses = c.PermittedEmailAddresses
exts.NameConstraints.PermittedIPAddresses = c.PermittedIPAddresses
exts.NameConstraints.PermittedDirectoryNames = c.PermittedDirectoryNames
exts.NameConstraints.PermittedEdiPartyNames = c.PermittedEdiPartyNames
exts.NameConstraints.PermittedRegisteredIDs = c.PermittedRegisteredIDs
exts.NameConstraints.ExcludedEmailAddresses = c.ExcludedEmailAddresses
exts.NameConstraints.ExcludedDNSNames = c.ExcludedDNSNames
exts.NameConstraints.ExcludedIPAddresses = c.ExcludedIPAddresses
exts.NameConstraints.ExcludedDirectoryNames = c.ExcludedDirectoryNames
exts.NameConstraints.ExcludedEdiPartyNames = c.ExcludedEdiPartyNames
exts.NameConstraints.ExcludedRegisteredIDs = c.ExcludedRegisteredIDs
} else if e.Id.Equal(oidCRLDistributionPoints) {
exts.CRLDistributionPoints = c.CRLDistributionPoints
} else if e.Id.Equal(oidExtAuthKeyId) {
exts.AuthKeyID = c.AuthorityKeyId
} else if e.Id.Equal(oidExtExtendedKeyUsage) {
exts.ExtendedKeyUsage = new(ExtendedKeyUsageExtension)
exts.ExtendedKeyUsage.Known = c.ExtKeyUsage
exts.ExtendedKeyUsage.Unknown = c.UnknownExtKeyUsage
} else if e.Id.Equal(oidExtCertificatePolicy) {
exts.CertificatePolicies = new(CertificatePoliciesData)
exts.CertificatePolicies.PolicyIdentifiers = c.PolicyIdentifiers
exts.CertificatePolicies.NoticeRefNumbers = c.NoticeRefNumbers
exts.CertificatePolicies.NoticeRefOrganization = c.ParsedNoticeRefOrganization
exts.CertificatePolicies.ExplicitTexts = c.ParsedExplicitTexts
exts.CertificatePolicies.QualifierId = c.QualifierId
exts.CertificatePolicies.CPSUri = c.CPSuri
} else if e.Id.Equal(oidExtAuthorityInfoAccess) {
exts.AuthorityInfoAccess = new(AuthorityInfoAccess)
exts.AuthorityInfoAccess.OCSPServer = c.OCSPServer
exts.AuthorityInfoAccess.IssuingCertificateURL = c.IssuingCertificateURL
} else if e.Id.Equal(oidExtSubjectKeyId) {
exts.SubjectKeyID = c.SubjectKeyId
} else if e.Id.Equal(oidExtSignedCertificateTimestampList) {
exts.SignedCertificateTimestampList = c.SignedCertificateTimestampList
} else if e.Id.Equal(oidExtensionCTPrecertificatePoison) {
exts.IsPrecert = true
} else {
// Unknown extension
unk = append(unk, e)
}
}
return exts, unk
}

61
vendor/github.com/zmap/zcrypto/x509/fingerprint.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
// 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 (
"bytes"
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"encoding/json"
)
// CertificateFingerprint represents a digest/fingerprint of some data. It can
// easily be encoded to hex and JSON (as a hex string).
type CertificateFingerprint []byte
// MD5Fingerprint creates a fingerprint of data using the MD5 hash algorithm.
func MD5Fingerprint(data []byte) CertificateFingerprint {
sum := md5.Sum(data)
return sum[:]
}
// SHA1Fingerprint creates a fingerprint of data using the SHA1 hash algorithm.
func SHA1Fingerprint(data []byte) CertificateFingerprint {
sum := sha1.Sum(data)
return sum[:]
}
// SHA256Fingerprint creates a fingerprint of data using the SHA256 hash
// algorithm.
func SHA256Fingerprint(data []byte) CertificateFingerprint {
sum := sha256.Sum256(data)
return sum[:]
}
// SHA512Fingerprint creates a fingerprint of data using the SHA256 hash
// algorithm.
func SHA512Fingerprint(data []byte) CertificateFingerprint {
sum := sha512.Sum512(data)
return sum[:]
}
// Equal returns true if the fingerprints are bytewise-equal.
func (f CertificateFingerprint) Equal(other CertificateFingerprint) bool {
return bytes.Equal(f, other)
}
// Hex returns the given fingerprint encoded as a hex string.
func (f CertificateFingerprint) Hex() string {
return hex.EncodeToString(f)
}
// MarshalJSON implements the json.Marshaler interface, and marshals the
// fingerprint as a hex string.
func (f *CertificateFingerprint) MarshalJSON() ([]byte, error) {
return json.Marshal(f.Hex())
}

View File

@ -0,0 +1,16 @@
// Code generated by "stringer -type=CertValidationLevel -output=generated_certvalidationlevel_string.go"; DO NOT EDIT.
package x509
import "fmt"
const _CertValidationLevel_name = "UnknownValidationLevelDVOVEV"
var _CertValidationLevel_index = [...]uint8{0, 22, 24, 26, 28}
func (i CertValidationLevel) String() string {
if i < 0 || i >= CertValidationLevel(len(_CertValidationLevel_index)-1) {
return fmt.Sprintf("CertValidationLevel(%d)", i)
}
return _CertValidationLevel_name[_CertValidationLevel_index[i]:_CertValidationLevel_index[i+1]]
}

468
vendor/github.com/zmap/zcrypto/x509/json.go generated vendored Normal file
View File

@ -0,0 +1,468 @@
// 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 (
"crypto/dsa"
"crypto/ecdsa"
"crypto/rsa"
"encoding/asn1"
"encoding/json"
"net"
"strings"
"time"
"github.com/asaskevich/govalidator"
jsonKeys "github.com/zmap/zcrypto/json"
"github.com/zmap/zcrypto/x509/pkix"
)
var kMinTime, kMaxTime time.Time
func init() {
var err error
kMinTime, err = time.Parse(time.RFC3339, "0001-01-01T00:00:00Z")
if err != nil {
panic(err)
}
kMaxTime, err = time.Parse(time.RFC3339, "9999-12-31T23:59:59Z")
if err != nil {
panic(err)
}
}
type auxKeyUsage struct {
DigitalSignature bool `json:"digital_signature,omitempty"`
ContentCommitment bool `json:"content_commitment,omitempty"`
KeyEncipherment bool `json:"key_encipherment,omitempty"`
DataEncipherment bool `json:"data_encipherment,omitempty"`
KeyAgreement bool `json:"key_agreement,omitempty"`
CertificateSign bool `json:"certificate_sign,omitempty"`
CRLSign bool `json:"crl_sign,omitempty"`
EncipherOnly bool `json:"encipher_only,omitempty"`
DecipherOnly bool `json:"decipher_only,omitempty"`
Value uint32 `json:"value"`
}
// MarshalJSON implements the json.Marshaler interface
func (k KeyUsage) MarshalJSON() ([]byte, error) {
var enc auxKeyUsage
enc.Value = uint32(k)
if k&KeyUsageDigitalSignature > 0 {
enc.DigitalSignature = true
}
if k&KeyUsageContentCommitment > 0 {
enc.ContentCommitment = true
}
if k&KeyUsageKeyEncipherment > 0 {
enc.KeyEncipherment = true
}
if k&KeyUsageDataEncipherment > 0 {
enc.DataEncipherment = true
}
if k&KeyUsageKeyAgreement > 0 {
enc.KeyAgreement = true
}
if k&KeyUsageCertSign > 0 {
enc.CertificateSign = true
}
if k&KeyUsageCRLSign > 0 {
enc.CRLSign = true
}
if k&KeyUsageEncipherOnly > 0 {
enc.EncipherOnly = true
}
if k&KeyUsageDecipherOnly > 0 {
enc.DecipherOnly = true
}
return json.Marshal(&enc)
}
// UnmarshalJSON implements the json.Unmarshler interface
func (k *KeyUsage) UnmarshalJSON(b []byte) error {
var aux auxKeyUsage
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
// TODO: validate the flags match
v := int(aux.Value)
*k = KeyUsage(v)
return nil
}
type auxSignatureAlgorithm struct {
Name string `json:"name,omitempty"`
OID pkix.AuxOID `json:"oid"`
}
// MarshalJSON implements the json.Marshaler interface
func (s *SignatureAlgorithm) MarshalJSON() ([]byte, error) {
aux := auxSignatureAlgorithm{
Name: s.String(),
}
for _, val := range signatureAlgorithmDetails {
if val.algo == *s {
aux.OID = make([]int, len(val.oid))
for idx := range val.oid {
aux.OID[idx] = val.oid[idx]
}
}
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshler interface
func (s *SignatureAlgorithm) UnmarshalJSON(b []byte) error {
var aux auxSignatureAlgorithm
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
*s = UnknownSignatureAlgorithm
oid := asn1.ObjectIdentifier(aux.OID.AsSlice())
for _, val := range signatureAlgorithmDetails {
if val.oid.Equal(oid) {
*s = val.algo
break
}
}
return nil
}
type auxPublicKeyAlgorithm struct {
Name string `json:"name,omitempty"`
OID *pkix.AuxOID `json:"oid,omitempty"`
}
// MarshalJSON implements the json.Marshaler interface
func (p *PublicKeyAlgorithm) MarshalJSON() ([]byte, error) {
aux := auxPublicKeyAlgorithm{
Name: p.String(),
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (p *PublicKeyAlgorithm) UnmarshalJSON(b []byte) error {
var aux auxPublicKeyAlgorithm
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
panic("unimplemented")
}
func clampTime(t time.Time) time.Time {
if t.Before(kMinTime) {
return kMinTime
}
if t.After(kMaxTime) {
return kMaxTime
}
return t
}
type auxValidity struct {
Start string `json:"start"`
End string `json:"end"`
ValidityPeriod int `json:"length"`
}
func (v *validity) MarshalJSON() ([]byte, error) {
aux := auxValidity{
Start: clampTime(v.NotBefore.UTC()).Format(time.RFC3339),
End: clampTime(v.NotAfter.UTC()).Format(time.RFC3339),
ValidityPeriod: int(v.NotAfter.Sub(v.NotBefore).Seconds()),
}
return json.Marshal(&aux)
}
func (v *validity) UnmarshalJSON(b []byte) error {
var aux auxValidity
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
var err error
if v.NotBefore, err = time.Parse(time.RFC3339, aux.Start); err != nil {
return err
}
if v.NotAfter, err = time.Parse(time.RFC3339, aux.End); err != nil {
return err
}
return nil
}
type jsonSubjectKeyInfo struct {
KeyAlgorithm PublicKeyAlgorithm `json:"key_algorithm"`
RSAPublicKey *jsonKeys.RSAPublicKey `json:"rsa_public_key,omitempty"`
DSAPublicKey interface{} `json:"dsa_public_key,omitempty"`
ECDSAPublicKey interface{} `json:"ecdsa_public_key,omitempty"`
SPKIFingerprint CertificateFingerprint `json:"fingerprint_sha256"`
}
type jsonSignature struct {
SignatureAlgorithm SignatureAlgorithm `json:"signature_algorithm"`
Value []byte `json:"value"`
Valid bool `json:"valid"`
SelfSigned bool `json:"self_signed"`
}
type fullValidity struct {
validity
ValidityPeriod int
}
type jsonCertificate struct {
Version int `json:"version"`
SerialNumber string `json:"serial_number"`
SignatureAlgorithm SignatureAlgorithm `json:"signature_algorithm"`
Issuer pkix.Name `json:"issuer"`
IssuerDN string `json:"issuer_dn,omitempty"`
Validity fullValidity `json:"validity"`
Subject pkix.Name `json:"subject"`
SubjectDN string `json:"subject_dn,omitempty"`
SubjectKeyInfo jsonSubjectKeyInfo `json:"subject_key_info"`
Extensions *CertificateExtensions `json:"extensions,omitempty"`
UnknownExtensions UnknownCertificateExtensions `json:"unknown_extensions,omitempty"`
Signature jsonSignature `json:"signature"`
FingerprintMD5 CertificateFingerprint `json:"fingerprint_md5"`
FingerprintSHA1 CertificateFingerprint `json:"fingerprint_sha1"`
FingerprintSHA256 CertificateFingerprint `json:"fingerprint_sha256"`
FingerprintNoCT CertificateFingerprint `json:"tbs_noct_fingerprint"`
SPKISubjectFingerprint CertificateFingerprint `json:"spki_subject_fingerprint"`
TBSCertificateFingerprint CertificateFingerprint `json:"tbs_fingerprint"`
ValidationLevel CertValidationLevel `json:"validation_level"`
Names []string `json:"names,omitempty"`
Redacted bool `json:"redacted"`
}
func AddECDSAPublicKeyToKeyMap(keyMap map[string]interface{}, key *ecdsa.PublicKey) {
params := key.Params()
keyMap["p"] = params.P.Bytes()
keyMap["n"] = params.N.Bytes()
keyMap["b"] = params.B.Bytes()
keyMap["gx"] = params.Gx.Bytes()
keyMap["gy"] = params.Gy.Bytes()
keyMap["x"] = key.X.Bytes()
keyMap["y"] = key.Y.Bytes()
keyMap["curve"] = key.Curve.Params().Name
keyMap["length"] = key.Curve.Params().BitSize
}
func AddDSAPublicKeyToKeyMap(keyMap map[string]interface{}, key *dsa.PublicKey) {
keyMap["p"] = key.P.Bytes()
keyMap["q"] = key.Q.Bytes()
keyMap["g"] = key.G.Bytes()
keyMap["y"] = key.Y.Bytes()
}
func (c *Certificate) MarshalJSON() ([]byte, error) {
// Fill out the certificate
jc := new(jsonCertificate)
jc.Version = c.Version
jc.SerialNumber = c.SerialNumber.String()
jc.SignatureAlgorithm = c.SignatureAlgorithm
jc.Issuer = c.Issuer
jc.IssuerDN = c.Issuer.String()
jc.Validity.NotBefore = c.NotBefore
jc.Validity.NotAfter = c.NotAfter
jc.Validity.ValidityPeriod = c.ValidityPeriod
jc.Subject = c.Subject
jc.SubjectDN = c.Subject.String()
jc.SubjectKeyInfo.KeyAlgorithm = c.PublicKeyAlgorithm
if isValidName(c.Subject.CommonName) {
jc.Names = append(jc.Names, c.Subject.CommonName)
}
for _, name := range c.DNSNames {
if isValidName(name) {
jc.Names = append(jc.Names, name)
} else if !strings.Contains(name, ".") { //just a TLD
jc.Names = append(jc.Names, name)
}
}
for _, name := range c.URIs {
if govalidator.IsURL(name) {
jc.Names = append(jc.Names, name)
}
}
for _, name := range c.IPAddresses {
str := name.String()
if govalidator.IsURL(str) {
jc.Names = append(jc.Names, str)
}
}
jc.Names = purgeNameDuplicates(jc.Names)
jc.Redacted = false
for _, name := range jc.Names {
if strings.HasPrefix(name, "?") {
jc.Redacted = true
}
}
// Pull out the key
keyMap := make(map[string]interface{})
jc.SubjectKeyInfo.SPKIFingerprint = c.SPKIFingerprint
switch key := c.PublicKey.(type) {
case *rsa.PublicKey:
rsaKey := new(jsonKeys.RSAPublicKey)
rsaKey.PublicKey = key
jc.SubjectKeyInfo.RSAPublicKey = rsaKey
case *dsa.PublicKey:
AddDSAPublicKeyToKeyMap(keyMap, key)
jc.SubjectKeyInfo.DSAPublicKey = keyMap
case *ecdsa.PublicKey:
AddECDSAPublicKeyToKeyMap(keyMap, key)
jc.SubjectKeyInfo.ECDSAPublicKey = keyMap
case *AugmentedECDSA:
pub := key.Pub
keyMap["pub"] = key.Raw.Bytes
params := pub.Params()
keyMap["p"] = params.P.Bytes()
keyMap["n"] = params.N.Bytes()
keyMap["b"] = params.B.Bytes()
keyMap["gx"] = params.Gx.Bytes()
keyMap["gy"] = params.Gy.Bytes()
keyMap["x"] = pub.X.Bytes()
keyMap["y"] = pub.Y.Bytes()
keyMap["curve"] = pub.Curve.Params().Name
keyMap["length"] = pub.Curve.Params().BitSize
//keyMap["asn1_oid"] = c.SignatureAlgorithmOID.String()
jc.SubjectKeyInfo.ECDSAPublicKey = keyMap
}
jc.Extensions, jc.UnknownExtensions = c.jsonifyExtensions()
// TODO: Handle the fact this might not match
jc.Signature.SignatureAlgorithm = jc.SignatureAlgorithm
jc.Signature.Value = c.Signature
jc.Signature.Valid = c.validSignature
jc.Signature.SelfSigned = c.SelfSigned
jc.FingerprintMD5 = c.FingerprintMD5
jc.FingerprintSHA1 = c.FingerprintSHA1
jc.FingerprintSHA256 = c.FingerprintSHA256
jc.FingerprintNoCT = c.FingerprintNoCT
jc.SPKISubjectFingerprint = c.SPKISubjectFingerprint
jc.TBSCertificateFingerprint = c.TBSCertificateFingerprint
jc.ValidationLevel = c.ValidationLevel
return json.Marshal(jc)
}
func purgeNameDuplicates(names []string) (out []string) {
hashset := make(map[string]bool, len(names))
for _, name := range names {
if _, inc := hashset[name]; !inc {
hashset[name] = true
}
}
out = make([]string, 0, len(hashset))
for key := range hashset {
out = append(out, key)
}
return
}
func isValidName(name string) (ret bool) {
// Check for wildcards and redacts, ignore malformed urls
if strings.HasPrefix(name, "?.") || strings.HasPrefix(name, "*.") {
ret = isValidName(name[2:])
} else {
ret = govalidator.IsURL(name)
}
return
}
func orMask(ip net.IP, mask net.IPMask) net.IP {
if len(ip) == 0 || len(mask) == 0 {
return nil
}
if len(ip) != net.IPv4len && len(ip) != net.IPv6len {
return nil
}
if len(ip) != len(mask) {
return nil
}
out := make([]byte, len(ip))
for idx := range ip {
out[idx] = ip[idx] | mask[idx]
}
return out
}
func invertMask(mask net.IPMask) net.IPMask {
if mask == nil {
return nil
}
out := make([]byte, len(mask))
for idx := range mask {
out[idx] = ^mask[idx]
}
return out
}
type auxGeneralSubtreeIP struct {
CIDR string `json:"cidr,omitempty"`
Begin string `json:"begin,omitempty"`
End string `json:"end,omitempty"`
Mask string `json:"mask,omitempty"`
}
func (g *GeneralSubtreeIP) MarshalJSON() ([]byte, error) {
aux := auxGeneralSubtreeIP{}
aux.CIDR = g.Data.String()
// Check to see if the subnet is valid. An invalid subnet will return 0,0
// from Size(). If the subnet is invalid, only output the CIDR.
ones, bits := g.Data.Mask.Size()
if ones == 0 && bits == 0 {
return json.Marshal(&aux)
}
// The first IP in the range should be `ip & mask`.
begin := g.Data.IP.Mask(g.Data.Mask)
if begin != nil {
aux.Begin = begin.String()
}
// The last IP (inclusive) is `ip & (^mask)`.
inverseMask := invertMask(g.Data.Mask)
end := orMask(g.Data.IP, inverseMask)
if end != nil {
aux.End = end.String()
}
// Output the mask as an IP, but enforce it can be formatted correctly.
// net.IP.String() only works on byte arrays of the correct length.
maskLen := len(g.Data.Mask)
if maskLen == net.IPv4len || maskLen == net.IPv6len {
maskAsIP := net.IP(g.Data.Mask)
aux.Mask = maskAsIP.String()
}
return json.Marshal(&aux)
}
func (g *GeneralSubtreeIP) UnmarshalJSON(b []byte) error {
aux := auxGeneralSubtreeIP{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
ip, ipNet, err := net.ParseCIDR(aux.CIDR)
if err != nil {
return err
}
g.Data.IP = ip
g.Data.Mask = ipNet.Mask
g.Min = 0
g.Max = 0
return nil
}

31
vendor/github.com/zmap/zcrypto/x509/names.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
// 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
func (p PublicKeyAlgorithm) String() string {
if p >= total_key_algorithms || p < 0 {
p = UnknownPublicKeyAlgorithm
}
return keyAlgorithmNames[p]
}
func (c *Certificate) SignatureAlgorithmName() string {
switch c.SignatureAlgorithm {
case UnknownSignatureAlgorithm:
return c.SignatureAlgorithmOID.String()
default:
return c.SignatureAlgorithm.String()
}
}
func (c *Certificate) PublicKeyAlgorithmName() string {
switch c.PublicKeyAlgorithm {
case UnknownPublicKeyAlgorithm:
return c.PublicKeyAlgorithmOID.String()
default:
return c.PublicKeyAlgorithm.String()
}
}

240
vendor/github.com/zmap/zcrypto/x509/pem_decrypt.go generated vendored Normal file
View 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
}

121
vendor/github.com/zmap/zcrypto/x509/pkcs1.go generated vendored Normal file
View File

@ -0,0 +1,121 @@
// 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"
"encoding/asn1"
"errors"
"math/big"
)
// 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
}

54
vendor/github.com/zmap/zcrypto/x509/pkcs8.go generated vendored Normal file
View File

@ -0,0 +1,54 @@
// 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 (
"github.com/zmap/zcrypto/x509/pkix"
"encoding/asn1"
"errors"
"fmt"
)
// 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)
}
}

274
vendor/github.com/zmap/zcrypto/x509/pkix/json.go generated vendored Normal file
View File

@ -0,0 +1,274 @@
// 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 pkix
import (
"encoding/asn1"
"encoding/json"
"errors"
"strconv"
"strings"
)
type auxAttributeTypeAndValue struct {
Type string `json:"type,omitempty"`
Value string `json:"value,omitempty"`
}
// MarshalJSON implements the json.Marshaler interface.
func (a *AttributeTypeAndValue) MarshalJSON() ([]byte, error) {
aux := auxAttributeTypeAndValue{}
aux.Type = a.Type.String()
if s, ok := a.Value.(string); ok {
aux.Value = s
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (a *AttributeTypeAndValue) UnmarshalJSON(b []byte) error {
aux := auxAttributeTypeAndValue{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
a.Type = nil
if len(aux.Type) > 0 {
parts := strings.Split(aux.Type, ".")
for _, part := range parts {
i, err := strconv.Atoi(part)
if err != nil {
return err
}
a.Type = append(a.Type, i)
}
}
a.Value = aux.Value
return nil
}
type auxOtherName struct {
ID string `json:"id,omitempty"`
Value []byte `json:"value,omitempty"`
}
// MarshalJSON implements the json.Marshaler interface.
func (o *OtherName) MarshalJSON() ([]byte, error) {
aux := auxOtherName{
ID: o.TypeID.String(),
Value: o.Value.Bytes,
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (o *OtherName) UnmarshalJSON(b []byte) (err error) {
aux := auxOtherName{}
if err = json.Unmarshal(b, &aux); err != nil {
return
}
// Turn dot-notation back into an OID
if len(aux.ID) == 0 {
return errors.New("empty type ID")
}
parts := strings.Split(aux.ID, ".")
o.TypeID = nil
for _, part := range parts {
i, err := strconv.Atoi(part)
if err != nil {
return err
}
o.TypeID = append(o.TypeID, i)
}
// Build the ASN.1 value
o.Value = asn1.RawValue{
Tag: 0,
Class: asn1.ClassContextSpecific,
IsCompound: true,
Bytes: aux.Value,
}
o.Value.FullBytes, err = asn1.Marshal(o.Value)
return
}
type auxExtension struct {
ID string `json:"id,omitempty"`
Critical bool `json:"critical"`
Value []byte `json:"value,omitempty"`
}
// MarshalJSON implements the json.Marshaler interface.
func (ext *Extension) MarshalJSON() ([]byte, error) {
aux := auxExtension{
ID: ext.Id.String(),
Critical: ext.Critical,
Value: ext.Value,
}
return json.Marshal(&aux)
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (ext *Extension) UnmarshalJSON(b []byte) (err error) {
aux := auxExtension{}
if err = json.Unmarshal(b, &aux); err != nil {
return
}
parts := strings.Split(aux.ID, ".")
for _, part := range parts {
i, err := strconv.Atoi(part)
if err != nil {
return err
}
ext.Id = append(ext.Id, i)
}
ext.Critical = aux.Critical
ext.Value = aux.Value
return
}
type auxName struct {
CommonName []string `json:"common_name,omitempty"`
SerialNumber []string `json:"serial_number,omitempty"`
Country []string `json:"country,omitempty"`
Locality []string `json:"locality,omitempty"`
Province []string `json:"province,omitempty"`
StreetAddress []string `json:"street_address,omitempty"`
Organization []string `json:"organization,omitempty"`
OrganizationalUnit []string `json:"organizational_unit,omitempty"`
PostalCode []string `json:"postal_code,omitempty"`
DomainComponent []string `json:"domain_component,omitempty"`
EmailAddress []string `json:"email_address,omitempty"`
GivenName []string `json:"given_name,omitempty"`
Surname []string `json:"surname,omitempty"`
// EV
JurisdictionCountry []string `json:"jurisdiction_country,omitempty"`
JurisdictionLocality []string `json:"jurisdiction_locality,omitempty"`
JurisdictionProvince []string `json:"jurisdiction_province,omitempty"`
UnknownAttributes []AttributeTypeAndValue `json:"-"`
}
// MarshalJSON implements the json.Marshaler interface.
func (n *Name) MarshalJSON() ([]byte, error) {
aux := auxName{}
attrs := n.ToRDNSequence()
for _, attrSet := range attrs {
for _, a := range attrSet {
s, ok := a.Value.(string)
if !ok {
continue
}
if a.Type.Equal(oidCommonName) {
aux.CommonName = append(aux.CommonName, s)
} else if a.Type.Equal(oidSurname) {
aux.Surname = append(aux.Surname, s)
} else if a.Type.Equal(oidSerialNumber) {
aux.SerialNumber = append(aux.SerialNumber, s)
} else if a.Type.Equal(oidCountry) {
aux.Country = append(aux.Country, s)
} else if a.Type.Equal(oidLocality) {
aux.Locality = append(aux.Locality, s)
} else if a.Type.Equal(oidProvince) {
aux.Province = append(aux.Province, s)
} else if a.Type.Equal(oidStreetAddress) {
aux.StreetAddress = append(aux.StreetAddress, s)
} else if a.Type.Equal(oidOrganization) {
aux.Organization = append(aux.Organization, s)
} else if a.Type.Equal(oidGivenName) {
aux.GivenName = append(aux.GivenName, s)
} else if a.Type.Equal(oidOrganizationalUnit) {
aux.OrganizationalUnit = append(aux.OrganizationalUnit, s)
} else if a.Type.Equal(oidPostalCode) {
aux.PostalCode = append(aux.PostalCode, s)
} else if a.Type.Equal(oidDomainComponent) {
aux.DomainComponent = append(aux.DomainComponent, s)
} else if a.Type.Equal(oidDNEmailAddress) {
aux.EmailAddress = append(aux.EmailAddress, s)
// EV
} else if a.Type.Equal(oidJurisdictionCountry) {
aux.JurisdictionCountry = append(aux.JurisdictionCountry, s)
} else if a.Type.Equal(oidJurisdictionLocality) {
aux.JurisdictionLocality = append(aux.JurisdictionLocality, s)
} else if a.Type.Equal(oidJurisdictionProvince) {
aux.JurisdictionProvince = append(aux.JurisdictionProvince, s)
} else {
aux.UnknownAttributes = append(aux.UnknownAttributes, a)
}
}
}
return json.Marshal(&aux)
}
func appendATV(names []AttributeTypeAndValue, fieldVals []string, asn1Id asn1.ObjectIdentifier) []AttributeTypeAndValue {
if len(fieldVals) == 0 {
return names
}
for _, val := range fieldVals {
names = append(names, AttributeTypeAndValue{Type: asn1Id, Value: val})
}
return names
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (n *Name) UnmarshalJSON(b []byte) error {
aux := auxName{}
if err := json.Unmarshal(b, &aux); err != nil {
return err
}
// Populate Names as []AttributeTypeAndValue
n.Names = appendATV(n.Names, aux.Country, oidCountry)
n.Names = appendATV(n.Names, aux.Organization, oidOrganization)
n.Names = appendATV(n.Names, aux.OrganizationalUnit, oidOrganizationalUnit)
n.Names = appendATV(n.Names, aux.Locality, oidLocality)
n.Names = appendATV(n.Names, aux.Province, oidProvince)
n.Names = appendATV(n.Names, aux.StreetAddress, oidStreetAddress)
n.Names = appendATV(n.Names, aux.PostalCode, oidPostalCode)
n.Names = appendATV(n.Names, aux.DomainComponent, oidDomainComponent)
n.Names = appendATV(n.Names, aux.EmailAddress, oidDNEmailAddress)
// EV
n.Names = appendATV(n.Names, aux.JurisdictionCountry, oidJurisdictionCountry)
n.Names = appendATV(n.Names, aux.JurisdictionLocality, oidJurisdictionLocality)
n.Names = appendATV(n.Names, aux.JurisdictionProvince, oidJurisdictionProvince)
n.Names = appendATV(n.Names, aux.CommonName, oidCommonName)
n.Names = appendATV(n.Names, aux.SerialNumber, oidSerialNumber)
// Populate specific fields as []string
n.Country = aux.Country
n.Organization = aux.Organization
n.OrganizationalUnit = aux.OrganizationalUnit
n.Locality = aux.Locality
n.Province = aux.Province
n.StreetAddress = aux.StreetAddress
n.PostalCode = aux.PostalCode
n.DomainComponent = aux.DomainComponent
// EV
n.JurisdictionCountry = aux.JurisdictionCountry
n.JurisdictionLocality = aux.JurisdictionLocality
n.JurisdictionProvince = aux.JurisdictionProvince
// CommonName and SerialNumber are not arrays.
if len(aux.CommonName) > 0 {
n.CommonName = aux.CommonName[0]
}
if len(aux.SerialNumber) > 0 {
n.SerialNumber = aux.SerialNumber[0]
}
// Add "extra" commonNames and serialNumbers to ExtraNames.
if len(aux.CommonName) > 1 {
n.ExtraNames = appendATV(n.ExtraNames, aux.CommonName[1:], oidCommonName)
}
if len(aux.SerialNumber) > 1 {
n.ExtraNames = appendATV(n.ExtraNames, aux.SerialNumber[1:], oidSerialNumber)
}
return nil
}

74
vendor/github.com/zmap/zcrypto/x509/pkix/oid.go generated vendored Normal file
View File

@ -0,0 +1,74 @@
// 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 pkix
import (
"encoding/asn1"
"encoding/json"
"fmt"
"strconv"
"strings"
)
// AuxOID behaves similar to asn1.ObjectIdentifier, except encodes to JSON as a
// string in dot notation. It is a type synonym for []int, and can be converted
// to an asn1.ObjectIdentifier by going through []int and back.
type AuxOID []int
// AsSlice returns a slice over the inner-representation
func (aux *AuxOID) AsSlice() []int {
return *aux
}
// CopyAsSlice returns a copy of the inter-representation as a slice
func (aux *AuxOID) CopyAsSlice() []int {
out := make([]int, len(*aux))
copy(out, *aux)
return out
}
// Equal tests (deep) equality of two AuxOIDs
func (aux *AuxOID) Equal(other *AuxOID) bool {
var a []int = *aux
var b []int = *other
if len(a) != len(b) {
return false
}
for idx := range a {
if a[idx] != b[idx] {
return false
}
}
return true
}
// MarshalJSON implements the json.Marshaler interface
func (aux *AuxOID) MarshalJSON() ([]byte, error) {
var oid asn1.ObjectIdentifier
oid = []int(*aux)
return json.Marshal(oid.String())
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (aux *AuxOID) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
parts := strings.Split(s, ".")
if len(parts) < 1 {
return fmt.Errorf("Invalid OID string %s", s)
}
slice := make([]int, len(parts))
for idx := range parts {
n, err := strconv.Atoi(parts[idx])
if err != nil || n < 0 {
return fmt.Errorf("Invalid OID integer %s", parts[idx])
}
slice[idx] = n
}
*aux = slice
return nil
}

1013
vendor/github.com/zmap/zcrypto/x509/pkix/oid_names.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

197
vendor/github.com/zmap/zcrypto/x509/pkix/pkix.go generated vendored Normal file
View File

@ -0,0 +1,197 @@
// 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 (
"encoding/asn1"
"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
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] == 2 && t[1] == 5 && t[2] == 4 {
// switch t[3] {
// case 3:
// n.CommonName = value
// case 5:
// n.SerialNumber = value
// case 6:
// n.Country = append(n.Country, value)
// case 7:
// n.Locality = append(n.Locality, value)
// case 8:
// n.Province = append(n.Province, value)
// case 9:
// n.StreetAddress = append(n.StreetAddress, value)
// case 10:
// n.Organization = append(n.Organization, value)
// case 11:
// n.OrganizationalUnit = append(n.OrganizationalUnit, value)
// case 17:
// n.PostalCode = append(n.PostalCode, value)
// }
// }
// }
// }
//}
//var (
// oidCountry = []int{2, 5, 4, 6}
// oidOrganization = []int{2, 5, 4, 10}
// oidOrganizationalUnit = []int{2, 5, 4, 11}
// oidCommonName = []int{2, 5, 4, 3}
// oidSerialNumber = []int{2, 5, 4, 5}
// oidLocality = []int{2, 5, 4, 7}
// oidProvince = []int{2, 5, 4, 8}
// oidStreetAddress = []int{2, 5, 4, 9}
// oidPostalCode = []int{2, 5, 4, 17}
//)
//// 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
//}
// 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 now is past the expiry time of certList.
func (certList *CertificateList) HasExpired(now time.Time) bool {
return now.After(certList.TBSCertList.NextUpdate)
}
// TBSCertificateList represents the ASN.1 structure of the same name. 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 ASN.1 structure of the same name. See RFC
// 5280, section 5.1.
type RevokedCertificate struct {
SerialNumber *big.Int
RevocationTime time.Time
Extensions []Extension `asn1:"optional"`
}

View File

@ -0,0 +1,215 @@
// 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 (
"encoding/asn1"
"strings"
)
// 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 `json:"type"`
Value interface{} `json:"value"`
}
// Name represents an X.509 distinguished name. This only includes the common
// elements of a DN. Additional elements in the name are ignored.
type Name struct {
Country, Organization, OrganizationalUnit []string
Locality, Province []string
StreetAddress, PostalCode, DomainComponent []string
EmailAddress []string
SerialNumber, CommonName string
GivenName, Surname []string
// EV Components
JurisdictionLocality, JurisdictionProvince, JurisdictionCountry []string
Names []AttributeTypeAndValue
ExtraNames []AttributeTypeAndValue
// OriginalRDNS is saved if the name is populated using FillFromRDNSequence.
// Additionally, if OriginalRDNS is non-nil, the String and ToRDNSequence
// methods will simply use this.
OriginalRDNS RDNSequence
}
// FillFromRDNSequence populates n based on the AttributeTypeAndValueSETs in the
// RDNSequence. It save the sequence as OriginalRDNS.
func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
n.OriginalRDNS = *rdns
for _, rdn := range *rdns {
if len(rdn) == 0 {
continue
}
atv := rdn[0]
n.Names = append(n.Names, atv)
value, ok := atv.Value.(string)
if !ok {
continue
}
t := atv.Type
if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 {
switch t[3] {
case 3:
n.CommonName = value
case 4:
n.Surname = append(n.Surname, value)
case 5:
n.SerialNumber = value
case 6:
n.Country = append(n.Country, value)
case 7:
n.Locality = append(n.Locality, value)
case 8:
n.Province = append(n.Province, value)
case 9:
n.StreetAddress = append(n.StreetAddress, value)
case 10:
n.Organization = append(n.Organization, value)
case 11:
n.OrganizationalUnit = append(n.OrganizationalUnit, value)
case 17:
n.PostalCode = append(n.PostalCode, value)
case 42:
n.GivenName = append(n.GivenName, value)
}
} else if t.Equal(oidDomainComponent) {
n.DomainComponent = append(n.DomainComponent, value)
} else if t.Equal(oidDNEmailAddress) {
// Deprecated, see RFC 5280 Section 4.1.2.6
n.EmailAddress = append(n.EmailAddress, value)
} else if t.Equal(oidJurisdictionLocality) {
n.JurisdictionLocality = append(n.JurisdictionLocality, value)
} else if t.Equal(oidJurisdictionProvince) {
n.JurisdictionProvince = append(n.JurisdictionProvince, value)
} else if t.Equal(oidJurisdictionCountry) {
n.JurisdictionCountry = append(n.JurisdictionCountry, value)
}
}
}
var (
oidCountry = []int{2, 5, 4, 6}
oidOrganization = []int{2, 5, 4, 10}
oidOrganizationalUnit = []int{2, 5, 4, 11}
oidCommonName = []int{2, 5, 4, 3}
oidSurname = []int{2, 5, 4, 4}
oidSerialNumber = []int{2, 5, 4, 5}
oidLocality = []int{2, 5, 4, 7}
oidProvince = []int{2, 5, 4, 8}
oidStreetAddress = []int{2, 5, 4, 9}
oidPostalCode = []int{2, 5, 4, 17}
oidGivenName = []int{2, 5, 4, 42}
oidDomainComponent = []int{0, 9, 2342, 19200300, 100, 1, 25}
oidDNEmailAddress = []int{1, 2, 840, 113549, 1, 9, 1}
// EV
oidJurisdictionLocality = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 1}
oidJurisdictionProvince = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 2}
oidJurisdictionCountry = []int{1, 3, 6, 1, 4, 1, 311, 60, 2, 1, 3}
)
// 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 {
// NOTE: stdlib prevents adding if the oid is already present in n.ExtraNames
//if len(values) == 0 || oidInAttributeTypeAndValue(oid, n.ExtraNames) {
if len(values) == 0 {
return in
}
s := make([]AttributeTypeAndValue, len(values))
for i, value := range values {
s[i].Type = oid
s[i].Value = value
}
return append(in, s)
}
// String returns an RDNSequence as comma seperated list of
// AttributeTypeAndValues in canonical form.
func (seq RDNSequence) String() string {
out := make([]string, 0, len(seq))
// An RDNSequence is effectively an [][]AttributeTypeAndValue
for _, atvSet := range seq {
for _, atv := range atvSet {
// Convert each individual AttributeTypeAndValue to X=Y
attrParts := make([]string, 0, 2)
oidString := atv.Type.String()
oidName, ok := oidDotNotationToNames[oidString]
if ok {
attrParts = append(attrParts, oidName.ShortName)
} else {
attrParts = append(attrParts, oidString)
}
switch value := atv.Value.(type) {
case string:
attrParts = append(attrParts, value)
case []byte:
attrParts = append(attrParts, string(value))
default:
continue
}
attrString := strings.Join(attrParts, "=")
out = append(out, attrString)
}
}
return strings.Join(out, ", ")
}
// ToRDNSequence returns OriginalRDNS is populated. Otherwise, it builds an
// RDNSequence in canonical order.
func (n Name) ToRDNSequence() (ret RDNSequence) {
if n.OriginalRDNS != nil {
return n.OriginalRDNS
}
if len(n.CommonName) > 0 {
ret = n.appendRDNs(ret, []string{n.CommonName}, oidCommonName)
}
ret = n.appendRDNs(ret, n.OrganizationalUnit, oidOrganizationalUnit)
ret = n.appendRDNs(ret, n.Organization, oidOrganization)
ret = n.appendRDNs(ret, n.StreetAddress, oidStreetAddress)
ret = n.appendRDNs(ret, n.Locality, oidLocality)
ret = n.appendRDNs(ret, n.Province, oidProvince)
ret = n.appendRDNs(ret, n.PostalCode, oidPostalCode)
ret = n.appendRDNs(ret, n.Country, oidCountry)
ret = n.appendRDNs(ret, n.DomainComponent, oidDomainComponent)
// EV Components
ret = n.appendRDNs(ret, n.JurisdictionLocality, oidJurisdictionLocality)
ret = n.appendRDNs(ret, n.JurisdictionProvince, oidJurisdictionProvince)
ret = n.appendRDNs(ret, n.JurisdictionCountry, oidJurisdictionCountry)
if len(n.SerialNumber) > 0 {
ret = n.appendRDNs(ret, []string{n.SerialNumber}, oidSerialNumber)
}
ret = append(ret, n.ExtraNames)
return ret
}
// String returns a canonical representation of a DistinguishedName
func (n *Name) String() string {
seq := n.ToRDNSequence()
return seq.String()
}
// OtherName represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.2.1.6.
type OtherName struct {
TypeID asn1.ObjectIdentifier
Value asn1.RawValue `asn1:"explicit"`
}
// EDIPartyName represents the ASN.1 structure of the same name. See RFC
// 5280, section 4.2.1.6.
type EDIPartyName struct {
NameAssigner string `asn1:"tag:0,optional,explicit" json:"name_assigner,omitempty"`
PartyName string `asn1:"tag:1,explicit" json:"party_name"`
}

22
vendor/github.com/zmap/zcrypto/x509/root.go generated vendored Normal file
View 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/zmap/zcrypto/x509/root_bsd.go generated vendored Normal file
View 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
}

238
vendor/github.com/zmap/zcrypto/x509/root_cgo_darwin.go generated vendored Normal file
View File

@ -0,0 +1,238 @@
// 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
// Use non-cgo on Darwin to prevent duplicate symbols on cgo
//
///*
//#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>
//
//// FetchPEMRoots_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 FetchPEMRoots_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;
//}
//
//// useOldCode 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 useOldCode() {
// 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;
//}
//
//// FetchPEMRoots 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 FetchPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots) {
// if (useOldCode()) {
// return FetchPEMRoots_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;
// if (i != 0) {
// // 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 = 1; 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;
// }
// }
// }
// CFRelease(trustSettings);
// }
// // 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) {
// 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 = nil
// var untrustedData C.CFDataRef = nil
// err := C.FetchPEMRoots(&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 untrustedData == nil {
// 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/zmap/zcrypto/x509/root_darwin.go generated vendored Normal file
View 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
}

View File

@ -0,0 +1,192 @@
// 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/x509"
"encoding/pem"
"flag"
"fmt"
"go/format"
"io/ioutil"
"log"
"math/big"
"net/http"
"os/exec"
"strings"
)
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, "// Created 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 {
sn, ok := big.NewInt(0).SetString(id.serialNumber, 0) // 0x prefix selects hex
if !ok {
return nil, fmt.Errorf("invalid serial number: %q", id.serialNumber)
}
ski, ok := big.NewInt(0).SetString(id.subjectKeyID, 0)
if !ok {
return nil, fmt.Errorf("invalid Subject Key ID: %q", id.subjectKeyID)
}
for _, cert := range scerts {
if sn.Cmp(cert.SerialNumber) != 0 {
continue
}
cski := big.NewInt(0).SetBytes(cert.SubjectKeyId)
if ski.Cmp(cski) != 0 {
continue
}
certs = append(certs, cert)
break
}
}
return certs, nil
}
func sysCerts() (certs []*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
}
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
}
certs = append(certs, cert)
}
return certs, nil
}
type certID struct {
serialNumber string
subjectKeyID string
}
// fetchCertIDs fetches IDs of iOS X509 certificates from apple.com.
func fetchCertIDs() ([]certID, error) {
resp, err := http.Get("https://support.apple.com/en-us/HT204132")
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, "<section id=trusted"):]
text = text[:strings.Index(text, "</section>")]
lines := strings.Split(text, "\n")
var ids []certID
var id certID
for i, ln := range lines {
if i == len(lines)-1 {
break
}
const sn = "Serial Number:"
if ln == sn {
id.serialNumber = "0x" + strings.Replace(strings.TrimSpace(lines[i+1]), ":", "", -1)
continue
}
if strings.HasPrefix(ln, sn) {
// extract hex value from parentheses.
id.serialNumber = ln[strings.Index(ln, "(")+1 : len(ln)-1]
continue
}
if strings.TrimSpace(ln) == "X509v3 Subject Key Identifier:" {
id.subjectKeyID = "0x" + strings.Replace(strings.TrimSpace(lines[i+1]), ":", "", -1)
ids = append(ids, id)
id = certID{}
}
}
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
package x509
func loadSystemRoots() (*CertPool, error) {
p := NewCertPool()
p.AppendCertsFromPEM([]byte(systemRootsPEM))
return p, nil
}
`

Some files were not shown because too many files have changed in this diff Show More