Vendor cfssl and cfssljson

This commit is contained in:
Christoph Blecker
2018-08-06 16:30:17 -07:00
parent 1c5b968152
commit 952fc9f6f8
245 changed files with 251725 additions and 4 deletions

33
vendor/github.com/cloudflare/cfssl/ubiquity/BUILD generated vendored Normal file
View File

@@ -0,0 +1,33 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"filter.go",
"performance.go",
"sha1.go",
"ubiquity_crypto.go",
"ubiquity_platform.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/ubiquity",
importpath = "github.com/cloudflare/cfssl/ubiquity",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

36
vendor/github.com/cloudflare/cfssl/ubiquity/filter.go generated vendored Normal file
View File

@@ -0,0 +1,36 @@
// Package ubiquity contains the ubiquity scoring logic for CFSSL bundling.
package ubiquity
// Ubiquity is addressed as selecting the chains that are most likely being accepted for different client systems.
// To select, we decide to do multi-round filtering from different ranking perpectives.
import (
"crypto/x509"
)
// RankingFunc returns the relative rank between chain1 and chain2.
// Return value:
// positive integer if rank(chain1) > rank(chain2),
// negative integer if rank(chain1) < rank(chain2),
// 0 if rank(chain1) == (chain2).
type RankingFunc func(chain1, chain2 []*x509.Certificate) int
// Filter filters out the chains with highest rank according to the ranking function f.
func Filter(chains [][]*x509.Certificate, f RankingFunc) [][]*x509.Certificate {
// If there are no chain or only 1 chain, we are done.
if len(chains) <= 1 {
return chains
}
bestChain := chains[0]
var candidateChains [][]*x509.Certificate
for _, chain := range chains {
r := f(bestChain, chain)
if r < 0 {
bestChain = chain
candidateChains = [][]*x509.Certificate{chain}
} else if r == 0 {
candidateChains = append(candidateChains, chain)
}
}
return candidateChains
}

View File

@@ -0,0 +1,126 @@
package ubiquity
// In this file, we include chain ranking functions based on security and performance
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
"crypto/x509"
"time"
"github.com/cloudflare/cfssl/helpers"
)
// Compute the priority of different hash algorithm based on security
// SHA2 > SHA1 >> MD = Others = Unknown
func hashPriority(cert *x509.Certificate) int {
switch cert.SignatureAlgorithm {
case x509.ECDSAWithSHA1, x509.DSAWithSHA1, x509.SHA1WithRSA:
return 10
case x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512,
x509.DSAWithSHA256, x509.SHA256WithRSA, x509.SHA384WithRSA,
x509.SHA512WithRSA:
return 100
default:
return 0
}
}
// Compute the priority of different key algorithm based performance and security
// ECDSA>RSA>DSA>Unknown
func keyAlgoPriority(cert *x509.Certificate) int {
switch cert.PublicKeyAlgorithm {
case x509.ECDSA:
switch cert.PublicKey.(*ecdsa.PublicKey).Curve {
case elliptic.P256():
return 100
case elliptic.P384():
return 120
case elliptic.P521():
return 140
default:
return 100
}
case x509.RSA:
switch cert.PublicKey.(*rsa.PublicKey).N.BitLen() {
case 4096:
return 70
case 3072:
return 50
case 2048:
return 30
// key size <= 1024 are discouraged.
default:
return 0
}
// we do not want to bundle a DSA cert.
case x509.DSA:
return 0
default:
return 0
}
}
// HashPriority returns the hash priority of the chain as the average of hash priority of certs in it.
func HashPriority(certs []*x509.Certificate) int {
ret := 0.0
for i, cert := range certs {
f1 := 1.0 / (float64(i) + 1.0)
f2 := 1.0 - f1
ret = ret*f2 + float64(hashPriority(cert))*f1
}
return int(ret)
}
// KeyAlgoPriority returns the key algorithm priority of the chain as the average of key algorithm priority of certs in it.
func KeyAlgoPriority(certs []*x509.Certificate) int {
ret := 0.0
for i, cert := range certs {
f1 := 1.0 / (float64(i) + 1.0)
f2 := 1.0 - f1
ret = float64(keyAlgoPriority(cert))*f1 + ret*f2
}
return int(ret)
}
// CompareChainHashPriority ranks chains with more current hash functions higher.
func CompareChainHashPriority(chain1, chain2 []*x509.Certificate) int {
hp1 := HashPriority(chain1)
hp2 := HashPriority(chain2)
return hp1 - hp2
}
// CompareChainKeyAlgoPriority ranks chains with more current key algorithm higher.
func CompareChainKeyAlgoPriority(chain1, chain2 []*x509.Certificate) int {
kap1 := KeyAlgoPriority(chain1)
kap2 := KeyAlgoPriority(chain2)
return kap1 - kap2
}
// CompareChainCryptoSuite ranks chains with more current crypto suite higher.
func CompareChainCryptoSuite(chain1, chain2 []*x509.Certificate) int {
cs1 := HashPriority(chain1) + KeyAlgoPriority(chain1)
cs2 := HashPriority(chain2) + KeyAlgoPriority(chain2)
return cs1 - cs2
}
// CompareChainLength ranks shorter chain higher.
func CompareChainLength(chain1, chain2 []*x509.Certificate) int {
return len(chain2) - len(chain1)
}
func compareTime(t1, t2 time.Time) int {
if t1.After(t2) {
return 1
} else if t1.Before(t2) {
return -1
}
return 0
}
// CompareChainExpiry ranks chain that lasts longer higher.
func CompareChainExpiry(chain1, chain2 []*x509.Certificate) int {
t1 := helpers.ExpiryTime(chain1)
t2 := helpers.ExpiryTime(chain2)
return compareTime(t1, t2)
}

153
vendor/github.com/cloudflare/cfssl/ubiquity/sha1.go generated vendored Normal file
View File

@@ -0,0 +1,153 @@
package ubiquity
import (
"crypto/x509"
"fmt"
"time"
"github.com/cloudflare/cfssl/helpers"
)
// DeprecationSeverity encodes the severity of a deprecation policy
type DeprecationSeverity int
const (
// None indicates there is no deprecation
None DeprecationSeverity = iota
// Low indicates the deprecation policy won't affect user experience
Low
// Medium indicates the deprecation policy will affect user experience
// either in a minor way or for a limited scope of users.
Medium
// High indicates the deprecation policy will strongly affect user experience
High
)
// SHA1DeprecationPolicy encodes how a platform deprecates the support of SHA1
type SHA1DeprecationPolicy struct {
// the name of platform
Platform string `json:"platform"`
// policy severity, policies of the same platform will only trigger the one of highest severity
Severity DeprecationSeverity `json:"severity"`
// a human readable message describing the deprecation effects
Description string `json:"description"`
// the date when the policy is effective. zero value means effective immediately
EffectiveDate time.Time `json:"effective_date"`
// the expiry deadline indicates the latest date which a end-entity
// certificate with SHA1 can be valid through.
ExpiryDeadline time.Time `json:"expiry_deadline"`
// the date beyond which SHA1 cert should not be issued.
NeverIssueAfter time.Time `json:"never_issue_after"`
}
// SHA1DeprecationPolicys ia a list of various SHA1DeprecationPolicy's
// proposed by major browser producers
var SHA1DeprecationPolicys = []SHA1DeprecationPolicy{
// Chrome:
// if the leaf certificate expires between 01-01-2016 and 01-01-2017
// and the chain (excluding root) contains SHA-1 cert, show "minor errors".
{
Platform: "Google Chrome",
Description: "shows the SSL connection has minor problems",
Severity: Medium,
ExpiryDeadline: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
},
// Chrome:
// if the leaf certificate expires after Jan. 1st 2017
// and the chain (excluding root) contains SHA-1 cert, show "untrusted SSL".
{
Platform: "Google Chrome",
Description: "shows the SSL connection is untrusted",
Severity: High,
ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
},
// Mozilla Firefox:
// if the leaf certificate expires after Jan. 1st 2017, and
// the chain (excluding root) contains SHA-1 cert, show a warning in the developer console.
{
Platform: "Mozilla Firefox",
Description: "gives warning in the developer console",
Severity: Low,
ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
},
// Mozilla Firefox:
// if a new certificate is issued after Jan. 1st 2016, and
// it is a SHA-1 cert, reject it.
{
Platform: "Mozilla Firefox",
Description: "shows the SSL connection is untrusted",
Severity: Medium,
EffectiveDate: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
NeverIssueAfter: time.Date(2016, time.January, 1, 0, 0, 0, 0, time.UTC),
},
// Mozilla Firefox:
// deprecate all valid SHA-1 cert chain on Jan. 1st 2017
{
Platform: "Mozilla Firefox",
Description: "shows the SSL connection is untrusted",
Severity: High,
EffectiveDate: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
},
// Microsoft Windows:
// deprecate all valid SHA-1 cert chain on Jan. 1st 2017
{
Platform: "Microsoft Windows Vista and later",
Description: "shows the SSL connection is untrusted",
Severity: High,
EffectiveDate: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
ExpiryDeadline: time.Date(2017, time.January, 1, 0, 0, 0, 0, time.UTC),
},
}
// Flag returns whether the policy flags the cert chain as deprecated for matching its deprecation criteria
func (p SHA1DeprecationPolicy) Flag(chain []*x509.Certificate) bool {
leaf := chain[0]
if time.Now().After(p.EffectiveDate) {
// Reject newly issued leaf certificate with SHA-1 after the specified deadline.
if !p.NeverIssueAfter.IsZero() && leaf.NotBefore.After(p.NeverIssueAfter) {
// Check hash algorithm of non-root leaf cert.
if len(chain) > 1 && helpers.HashAlgoString(leaf.SignatureAlgorithm) == "SHA1" {
return true
}
}
// Reject certificate chain with SHA-1 that are still valid after expiry deadline.
if !p.ExpiryDeadline.IsZero() && leaf.NotAfter.After(p.ExpiryDeadline) {
// Check hash algorithm of non-root certs.
for i, cert := range chain {
if i < len(chain)-1 {
if helpers.HashAlgoString(cert.SignatureAlgorithm) == "SHA1" {
return true
}
}
}
}
}
return false
}
// SHA1DeprecationMessages returns a list of human-readable messages. Each message describes
// how one platform rejects the chain based on SHA1 deprecation policies.
func SHA1DeprecationMessages(chain []*x509.Certificate) []string {
// record the most severe deprecation policy by each platform
selectedPolicies := map[string]SHA1DeprecationPolicy{}
for _, policy := range SHA1DeprecationPolicys {
if policy.Flag(chain) {
// only keep the policy with highest severity
if selectedPolicies[policy.Platform].Severity < policy.Severity {
selectedPolicies[policy.Platform] = policy
}
}
}
// build the message list
list := []string{}
for _, policy := range selectedPolicies {
if policy.Severity > None {
list = append(list, fmt.Sprintf("%s %s due to SHA-1 deprecation", policy.Platform, policy.Description))
}
}
return list
}

View File

@@ -0,0 +1,166 @@
package ubiquity
// In this file, we mainly cover crypto ubiquity.
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rsa"
"crypto/x509"
"github.com/cloudflare/cfssl/helpers"
"math"
)
// HashUbiquity represents a score for how ubiquitous a given hash
// algorithm is; the higher the score, the more preferable the algorithm
// is.
type HashUbiquity int
// KeyAlgoUbiquity represents a score for how ubiquitous a given
// public-key algorithm is; the higher the score, the more preferable
// the algorithm is.
type KeyAlgoUbiquity int
// SHA1 is ubiquitous. SHA2 is not supported on some legacy platforms.
// We consider MD2/MD5 is harmful and thus assign them lowest ubiquity.
const (
UnknownHashUbiquity HashUbiquity = 0
SHA2Ubiquity HashUbiquity = 70
SHA1Ubiquity HashUbiquity = 100
MD5Ubiquity HashUbiquity = 0
MD2Ubiquity HashUbiquity = 0
)
// RSA and DSA are considered ubiquitous. ECDSA256 and ECDSA384 should be
// supported by TLS 1.2 and have limited support from TLS 1.0 and
// 1.1, based on RFC6460, but ECDSA521 is less well-supported as
// a standard.
const (
RSAUbiquity KeyAlgoUbiquity = 100
DSAUbiquity KeyAlgoUbiquity = 100
ECDSA256Ubiquity KeyAlgoUbiquity = 70
ECDSA384Ubiquity KeyAlgoUbiquity = 70
ECDSA521Ubiquity KeyAlgoUbiquity = 30
UnknownAlgoUbiquity KeyAlgoUbiquity = 0
)
// hashUbiquity computes the ubiquity of the hash algorithm in the
// signature algorithm of a cert.
// SHA1 > SHA2 > MD > Others
func hashUbiquity(cert *x509.Certificate) HashUbiquity {
switch cert.SignatureAlgorithm {
case x509.ECDSAWithSHA1, x509.DSAWithSHA1, x509.SHA1WithRSA:
return SHA1Ubiquity
case x509.ECDSAWithSHA256, x509.ECDSAWithSHA384, x509.ECDSAWithSHA512,
x509.DSAWithSHA256, x509.SHA256WithRSA, x509.SHA384WithRSA,
x509.SHA512WithRSA:
return SHA2Ubiquity
case x509.MD5WithRSA, x509.MD2WithRSA:
return MD5Ubiquity
default:
return UnknownHashUbiquity
}
}
// keyAlgoUbiquity compute the ubiquity of the cert's public key algorithm
// RSA, DSA>ECDSA>Unknown
func keyAlgoUbiquity(cert *x509.Certificate) KeyAlgoUbiquity {
switch cert.PublicKeyAlgorithm {
case x509.ECDSA:
switch cert.PublicKey.(*ecdsa.PublicKey).Curve {
case elliptic.P256():
return ECDSA256Ubiquity
case elliptic.P384():
return ECDSA384Ubiquity
case elliptic.P521():
return ECDSA521Ubiquity
default:
return UnknownAlgoUbiquity
}
case x509.RSA:
if cert.PublicKey.(*rsa.PublicKey).N.BitLen() >= 1024 {
return RSAUbiquity
}
return UnknownAlgoUbiquity
case x509.DSA:
return DSAUbiquity
default:
return UnknownAlgoUbiquity
}
}
// ChainHashUbiquity scores a chain based on the hash algorithms used
// by the certificates in the chain.
func ChainHashUbiquity(chain []*x509.Certificate) HashUbiquity {
ret := math.MaxInt32
for _, cert := range chain {
uscore := int(hashUbiquity(cert))
if ret > uscore {
ret = uscore
}
}
return HashUbiquity(ret)
}
// ChainKeyAlgoUbiquity scores a chain based on the public-key algorithms
// used by the certificates in the chain.
func ChainKeyAlgoUbiquity(chain []*x509.Certificate) KeyAlgoUbiquity {
ret := math.MaxInt32
for _, cert := range chain {
uscore := int(keyAlgoUbiquity(cert))
if ret > uscore {
ret = uscore
}
}
return KeyAlgoUbiquity(ret)
}
// CompareChainHashUbiquity returns a positive, zero, or negative value
// if the hash ubiquity of the first chain is greater, equal, or less
// than the second chain.
func CompareChainHashUbiquity(chain1, chain2 []*x509.Certificate) int {
hu1 := ChainHashUbiquity(chain1)
hu2 := ChainHashUbiquity(chain2)
return int(hu1) - int(hu2)
}
// CompareChainKeyAlgoUbiquity returns a positive, zero, or negative value
// if the public-key ubiquity of the first chain is greater, equal,
// or less than the second chain.
func CompareChainKeyAlgoUbiquity(chain1, chain2 []*x509.Certificate) int {
kau1 := ChainKeyAlgoUbiquity(chain1)
kau2 := ChainKeyAlgoUbiquity(chain2)
return int(kau1) - int(kau2)
}
// CompareExpiryUbiquity ranks two certificate chains based on the exiry dates of intermediates and roots.
// Certs expire later are ranked higher than ones expire earlier. The ranking between chains are determined by
// the first pair of intermediates, scanned from the root level, that ar ranked differently.
func CompareExpiryUbiquity(chain1, chain2 []*x509.Certificate) int {
for i := 0; ; i++ {
if i >= len(chain1) || i >= len(chain2) {
break
}
c1 := chain1[len(chain1)-1-i]
c2 := chain2[len(chain2)-1-i]
t1 := c1.NotAfter
t2 := c2.NotAfter
// Check if expiry dates valid. Return if one or other is invalid.
// Otherwise rank by expiry date. Later is ranked higher.
c1Valid := helpers.ValidExpiry(c1)
c2Valid := helpers.ValidExpiry(c2)
if c1Valid && !c2Valid {
return 1
}
if !c1Valid && c2Valid {
return -1
}
r := compareTime(t1, t2)
// Return when we find rank difference.
if r != 0 {
return r
}
}
return 0
}

View File

@@ -0,0 +1,230 @@
package ubiquity
// This is for cross-platform ubiquity. Basically, here we deal with issues about whether a cert chain
// is acceptable for different platforms, including desktop and mobile ones., and about how to compare
// two chains under the context of cross-platform ubiquity.
import (
"crypto/sha1"
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
"path"
"path/filepath"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
)
// SHA1RawPublicKey returns a SHA1 hash of the raw certificate public key
func SHA1RawPublicKey(cert *x509.Certificate) string {
return fmt.Sprintf("%x", sha1.Sum(cert.RawSubjectPublicKeyInfo))
}
// CertSet is a succint set of x509 certificates which only stores certificates' SHA1 hashes.
type CertSet map[string]bool
// Lookup returns whether a certificate is stored in the set.
func (s CertSet) Lookup(cert *x509.Certificate) bool {
return s[SHA1RawPublicKey(cert)]
}
// Add adds a certificate to the set.
func (s CertSet) Add(cert *x509.Certificate) {
s[SHA1RawPublicKey(cert)] = true
}
// A Platform contains ubiquity information on supported crypto algorithms and root certificate store name.
type Platform struct {
Name string `json:"name"`
Weight int `json:"weight"`
HashAlgo string `json:"hash_algo"`
KeyAlgo string `json:"key_algo"`
KeyStoreFile string `json:"keystore"`
KeyStore CertSet
HashUbiquity HashUbiquity
KeyAlgoUbiquity KeyAlgoUbiquity
}
// Trust returns whether the platform has the root cert in the trusted store.
func (p Platform) Trust(root *x509.Certificate) bool {
// the key store is empty iff the platform doesn't carry a root store and trust whatever root store
// is supplied. An example is Chrome. Such platforms should not show up in the untrusted platform
// list. So always return true here. Also this won't hurt ubiquity scoring because such platforms give
// no differentiation on root cert selection.
if len(p.KeyStore) == 0 {
return true
}
return p.KeyStore.Lookup(root)
}
func (p Platform) hashUbiquity() HashUbiquity {
switch p.HashAlgo {
case "SHA1":
return SHA1Ubiquity
case "SHA2":
return SHA2Ubiquity
default:
return UnknownHashUbiquity
}
}
func (p Platform) keyAlgoUbiquity() KeyAlgoUbiquity {
switch p.KeyAlgo {
case "RSA":
return RSAUbiquity
case "ECDSA256":
return ECDSA256Ubiquity
case "ECDSA384":
return ECDSA384Ubiquity
case "ECDSA521":
return ECDSA521Ubiquity
default:
return UnknownAlgoUbiquity
}
}
// ParseAndLoad converts HashAlgo and KeyAlgo to corresponding ubiquity value and load
// certificates into internal KeyStore from KeyStoreFiles
func (p *Platform) ParseAndLoad() (ok bool) {
p.HashUbiquity = p.hashUbiquity()
p.KeyAlgoUbiquity = p.keyAlgoUbiquity()
p.KeyStore = map[string]bool{}
if p.KeyStoreFile != "" {
pemBytes, err := ioutil.ReadFile(p.KeyStoreFile)
if err != nil {
log.Error(err)
return false
}
// Best effort parsing the PEMs such that ignore all borken pem,
// since some of CA certs have negative serial number which trigger errors.
for len(pemBytes) > 0 {
var certs []*x509.Certificate
certs, rest, err := helpers.ParseOneCertificateFromPEM(pemBytes)
// If one certificate object is parsed, possibly a PKCS#7
// structure containing multiple certs, record the raw SHA1 hash(es).
if err == nil && certs != nil {
for _, cert := range certs {
p.KeyStore.Add(cert)
}
}
if len(rest) < len(pemBytes) {
pemBytes = rest
} else {
// No progress in bytes parsing, bail out.
break
}
}
}
if p.HashUbiquity <= UnknownHashUbiquity ||
p.KeyAlgoUbiquity <= UnknownAlgoUbiquity {
return false
}
return true
}
// Platforms is the list of platforms against which ubiquity bundling will be optimized.
var Platforms []Platform
// LoadPlatforms reads the file content as a json object array and convert it
// to Platforms.
func LoadPlatforms(filename string) error {
// if filename is empty, skip the metadata loading
if filename == "" {
return nil
}
relativePath := filepath.Dir(filename)
// Attempt to load root certificate metadata
log.Debug("Loading platform metadata: ", filename)
bytes, err := ioutil.ReadFile(filename)
if err != nil {
return fmt.Errorf("platform metadata failed to load: %v", err)
}
var rawPlatforms []Platform
if bytes != nil {
err = json.Unmarshal(bytes, &rawPlatforms)
if err != nil {
return fmt.Errorf("platform metadata failed to parse: %v", err)
}
}
for _, platform := range rawPlatforms {
if platform.KeyStoreFile != "" {
platform.KeyStoreFile = path.Join(relativePath, platform.KeyStoreFile)
}
ok := platform.ParseAndLoad()
if !ok {
// erase all loaded platforms
Platforms = nil
return fmt.Errorf("fail to finalize the parsing of platform metadata: %v", platform)
}
log.Infof("Platform metadata is loaded: %v %v", platform.Name, len(platform.KeyStore))
Platforms = append(Platforms, platform)
}
return nil
}
// UntrustedPlatforms returns a list of platforms which don't trust the root certificate.
func UntrustedPlatforms(root *x509.Certificate) []string {
ret := []string{}
for _, platform := range Platforms {
if !platform.Trust(root) {
ret = append(ret, platform.Name)
}
}
return ret
}
// CrossPlatformUbiquity returns a ubiquity score (persumably relecting the market share in percentage)
// based on whether the given chain can be verified with the different platforms' root certificate stores.
func CrossPlatformUbiquity(chain []*x509.Certificate) int {
// There is no root store info, every chain is equal weighted as 0.
if len(Platforms) == 0 {
return 0
}
totalWeight := 0
// A chain is viable with the platform if
// 1. the root is in the platform's root store
// 2. the chain satisfy the minimal constraints on hash function and key algorithm.
root := chain[len(chain)-1]
for _, platform := range Platforms {
if platform.Trust(root) {
switch {
case platform.HashUbiquity <= ChainHashUbiquity(chain) && platform.KeyAlgoUbiquity <= ChainKeyAlgoUbiquity(chain):
totalWeight += platform.Weight
}
}
}
return totalWeight
}
// ComparePlatformUbiquity compares the cross-platform ubiquity between chain1 and chain2.
func ComparePlatformUbiquity(chain1, chain2 []*x509.Certificate) int {
w1 := CrossPlatformUbiquity(chain1)
w2 := CrossPlatformUbiquity(chain2)
return w1 - w2
}
// SHA2Homogeneity returns 1 if the chain contains only SHA-2 certs (excluding root). Otherwise it returns 0.
func SHA2Homogeneity(chain []*x509.Certificate) int {
for i := 0; i < len(chain)-1; i++ {
if hashUbiquity(chain[i]) != SHA2Ubiquity {
return 0
}
}
return 1
}
// CompareSHA2Homogeneity compares the chains based on SHA2 homogeneity. Full SHA-2 chain (excluding root) is rated higher that the rest.
func CompareSHA2Homogeneity(chain1, chain2 []*x509.Certificate) int {
w1 := SHA2Homogeneity(chain1)
w2 := SHA2Homogeneity(chain2)
return w1 - w2
}