diff --git a/lib/go-tc/enum.go b/lib/go-tc/enum.go index de7a4add7c..ce1e4fb893 100644 --- a/lib/go-tc/enum.go +++ b/lib/go-tc/enum.go @@ -495,8 +495,6 @@ func (t DSType) IsHTTP() bool { // IsDNS returns whether the DSType is a DNS category. func (t DSType) IsDNS() bool { switch t { - case DSTypeHTTPNoCache: - fallthrough case DSTypeDNS: fallthrough case DSTypeDNSLive: diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go index 7a820146ea..2923b41845 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go @@ -20,15 +20,20 @@ package deliveryservice */ import ( + "bytes" + "crypto/ecdsa" + "crypto/rsa" "crypto/x509" "database/sql" "encoding/base64" "encoding/pem" "errors" + "fmt" "net/http" "strings" "github.com/apache/trafficcontrol/lib/go-tc" + "github.com/apache/trafficcontrol/lib/go-util" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc" "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant" @@ -59,12 +64,23 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr) return } - certChain, isUnknownAuth, err := verifyCertificate(req.Certificate.Crt, "") + + // ECDSA keys support is only permitted for DNS delivery services + // Traffic Router (HTTP* delivery service types) do not support ECDSA keys + dsType, dsFound, err := getDSType(inf.Tx.Tx, *req.Key) + allowEC := false + if err == nil && dsFound && dsType.IsDNS() { + allowEC = true + } + + certChain, certPrivateKey, isUnknownAuth, isVerifiedChainNotEqual, err := verifyCertKeyPair(req.Certificate.Crt, req.Certificate.Key, "", allowEC) if err != nil { api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("verifying certificate: "+err.Error()), nil) return } req.Certificate.Crt = certChain + req.Certificate.Key = certPrivateKey + base64EncodeCertificate(req.Certificate) dsSSLKeys := tc.DeliveryServiceSSLKeys{ CDN: *req.CDN, @@ -83,7 +99,11 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) { return } if isUnknownAuth { - api.WriteRespAlert(w, r, tc.WarnLevel, "WARNING: SSL keys were successfully added for '"+*req.DeliveryService+"', but the certificate is signed by an unknown authority and may be invalid") + api.WriteRespAlert(w, r, tc.WarnLevel, "WARNING: SSL keys were successfully added for '"+*req.DeliveryService+"', but the input certificate may be invalid (certificate is signed by an unknown authority)") + return + } + if isVerifiedChainNotEqual { + api.WriteRespAlert(w, r, tc.WarnLevel, "WARNING: SSL keys were successfully added for '"+*req.DeliveryService+"', but the input certificate may be invalid (certificate verification produced a different chain)") return } api.WriteResp(w, r, "Successfully added ssl keys for "+*req.DeliveryService) @@ -272,26 +292,111 @@ WHERE r.pattern = $2 // certificate and its chain in the proper order. Returns a verified // and ordered certificate and CA chain. // If the cert verification returns UnknownAuthorityError, return true to -// indicate that the certs are signed by an unknown authority (e.g. self-signed). -func verifyCertificate(certificate string, rootCA string) (string, bool, error) { +// indicate that the certs are signed by an unknown authority (e.g. self-signed). Otherwise, return false. +// If the chain returned from Certificate.Verify() does not match the input chain, +// return true. Otherwise, return false. +func verifyCertKeyPair(pemCertificate string, pemPrivateKey string, rootCA string, allowEC bool) (string, string, bool, bool, error) { // decode, verify, and order certs for storage - certs := strings.SplitAfter(certificate, PemCertEndMarker) + cleanPemPrivateKey := "" + certs := strings.SplitAfter(pemCertificate, PemCertEndMarker) if len(certs) <= 1 { - return "", false, errors.New("no certificate chain to verify") + return "", "", false, false, errors.New("no certificate chain to verify") } // decode and verify the server certificate block, _ := pem.Decode([]byte(certs[0])) if block == nil { - return "", false, errors.New("could not decode pem-encoded server certificate") + return "", "", false, false, errors.New("could not decode pem-encoded server certificate") } cert, err := x509.ParseCertificate(block.Bytes) if err != nil { - return "", false, errors.New("could not parse the server certificate: " + err.Error()) + return "", "", false, false, errors.New("could not parse the server certificate: " + err.Error()) } - if !(cert.KeyUsage&x509.KeyUsageKeyEncipherment > 0) { - return "", false, errors.New("no key encipherment usage for the server certificate") + + // Common x509 certificate validation + err = commonX509CertificateValidation(cert) + if err != nil { + return "", "", false, false, err } + + switch cert.PublicKeyAlgorithm { + case x509.RSA: + var rsaPrivateKey *rsa.PrivateKey + + // RSA is both a digital signature and encryption algorithm, hence the key encipherment + // usage must be indicated in the certificate. + // The keyUsage and extended Key Usage does not exist in version 1 of the x509 specificication. + if cert.Version > 1 && !(cert.KeyUsage&x509.KeyUsageKeyEncipherment > 0) { + return "", "", false, false, errors.New("cert/key (rsa) validation: no keyEncipherment keyUsage extension present in x509v3 server certificate") + } + + // Extract the RSA public key from the x509 certificate + certPublicKey, ok := cert.PublicKey.(*rsa.PublicKey) + if !ok || certPublicKey == nil { + return "", "", false, false, errors.New("cert/key (rsa) validation error: could not extract public RSA key from certificate") + } + + // Attempt to decode the RSA private key + rsaPrivateKey, cleanPemPrivateKey, err = decodeRSAPrivateKey(pemPrivateKey) + if err != nil { + return "", "", false, false, err + } + + // Check RSA private key modulus against the x509 RSA public key modulus + if rsaPrivateKey != nil && certPublicKey != nil && !bytes.Equal(rsaPrivateKey.N.Bytes(), certPublicKey.N.Bytes()) { + return "", "", false, false, errors.New("cert/key (rsa) mismatch error: RSA public N modulus value mismatch") + } + + case x509.ECDSA: + var ecdsaPrivateKey *ecdsa.PrivateKey + + // Only permit ECDSA support for DNS* DSTypes until the Traffic Router can support it + if !allowEC { + return "", "", false, false, errors.New("cert/key validation error: ECDSA public key algorithm unsupported for non-DNS delivery service type") + } + + // DSA and ECDSA is not an encryption algorithm and only a signing algorithm, hence the + // certificate only needs to have the DigitalSignature KeyUsage indicated. + if cert.Version > 1 && !(cert.KeyUsage&x509.KeyUsageDigitalSignature > 0) { + return "", "", false, false, errors.New("cert/key (ecdsa) validation error: no digitalSignature keyUsage extension present in x509v3 server certificate") + } + + // Attempt to decode the ECDSA private key + ecdsaPrivateKey, cleanPemPrivateKey, err = decodeECDSAPrivateKey(pemPrivateKey) + if err != nil { + return "", "", false, false, err + } + + // Extract the ECDSA public key from the x509 certificate + certPublicKey, ok := cert.PublicKey.(*ecdsa.PublicKey) + if !ok || certPublicKey == nil { + return "", "", false, false, errors.New("cert/key (ecdsa) validation error: could not get extract public ECDSA key from certificate") + } + + // Compare the ECDSA curve name contained within the x509.PublicKey against the curve name indicated in the private key + if certPublicKey.Params().Name != ecdsaPrivateKey.Params().Name { + return "", "", false, false, errors.New("cert/key (ecdsa) mismatch error: ECDSA curve name in cert does not match curve name in private key") + } + + // Verify that ECDSA public value X matches in both the cert.PublicKey and the private key. + if !bytes.Equal(certPublicKey.X.Bytes(), ecdsaPrivateKey.X.Bytes()) { + return "", "", false, false, errors.New("cert/key (ecdsa) mismatch error: ECDSA public X value mismatch") + } + + // Verify that ECDSA public value Y matches in both the cert.PublicKey and the private key. + if !bytes.Equal(certPublicKey.Y.Bytes(), ecdsaPrivateKey.Y.Bytes()) { + return "", "", false, false, errors.New("cert/key (ecdsa) mismatch error: ECDSA public Y value mismatch") + } + + case x509.DSA: + return "", "", false, false, errors.New("cert/key validation error: DSA public key algorithm unsupported") + + case x509.UnknownPublicKeyAlgorithm: + fallthrough + default: + return "", "", false, false, errors.New("cert/key validation error: Unknown public key algorithm") + } + bundle := "" for i := 0; i < len(certs)-1; i++ { bundle += certs[i] @@ -299,17 +404,18 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, error) intermediatePool := x509.NewCertPool() if !intermediatePool.AppendCertsFromPEM([]byte(bundle)) { - return "", false, errors.New("certificate CA bundle is empty") + return "", "", false, false, errors.New("certificate CA bundle is empty") } opts := x509.VerifyOptions{ Intermediates: intermediatePool, } + if rootCA != "" { // verify the certificate chain. rootPool := x509.NewCertPool() if !rootPool.AppendCertsFromPEM([]byte(rootCA)) { - return "", false, errors.New("unable to parse root CA certificate") + return "", "", false, false, errors.New("unable to parse root CA certificate") } opts.Roots = rootPool } @@ -317,12 +423,12 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, error) chain, err := cert.Verify(opts) if err != nil { if _, ok := err.(x509.UnknownAuthorityError); ok { - return certificate, true, nil + return pemCertificate, cleanPemPrivateKey, true, false, nil } - return "", false, errors.New("could not verify the certificate chain: " + err.Error()) + return "", "", false, false, errors.New("could not verify the certificate chain: " + err.Error()) } if len(chain) < 1 { - return "", false, errors.New("can't find valid chain for cert in file in request") + return "", "", false, false, errors.New("can't find valid chain for cert in file in request") } pemEncodedChain := "" for _, link := range chain[0] { @@ -332,8 +438,211 @@ func verifyCertificate(certificate string, rootCA string) (string, bool, error) } if len(pemEncodedChain) < 1 { - return "", false, errors.New("Invalid empty certicate chain in request") + return "", "", false, false, errors.New("invalid empty certificate chain in request") + } + + if pemEncodedChain != pemCertificate { + return pemCertificate, cleanPemPrivateKey, false, true, nil + } + + return pemCertificate, cleanPemPrivateKey, false, false, nil +} + +func commonX509CertificateValidation(cert *x509.Certificate) error { + + // validate certificate is a server auth certificate if the extension is present + if cert.Version > 1 { + serverAuthExtKeyUsageFound := false + for _, certExtKeyUsage := range cert.ExtKeyUsage { + if certExtKeyUsage == x509.ExtKeyUsageServerAuth { + serverAuthExtKeyUsageFound = true + break + } + } + + if !serverAuthExtKeyUsageFound { + return errors.New("certificate (x509v3) validation error: server certificate missing 'serverAuth' extended key usage") + } + } + + // ensure that the certificate uses a supported PKI algorithm and a public key is present. + if cert.PublicKey == nil { + return errors.New("certificate validation error: no PKI public key found") + } + if cert.PublicKeyAlgorithm == x509.UnknownPublicKeyAlgorithm { + return errors.New("certificate validation error: unknown PKI algorithm") + } + + // ensure that the certificate is signed with supported algorithm + if len(cert.Signature) == 0 { + return errors.New("certificate validation error: no signature found") + } + if cert.SignatureAlgorithm == x509.UnknownSignatureAlgorithm { + return errors.New("certificate validation error: unknown signature algorithm") + } + + return nil +} + +// Common privateKey validation logic. +// Reject unsupported encrypted private keys +func commonPrivateKeyValidation(block *pem.Block) error { + + if block == nil { + return errors.New("private key validation error: could not decode pem-encoded private key") + } + + // Check for encrypted keys or other unsupported key types + if strings.Contains(block.Type, "ENCRYPTED") { + return errors.New("private key validation error: encrypted private key not supported - block type: " + block.Type) + } + + // Check block headers for encryption. + for _, value := range block.Headers { + if strings.Contains(value, "ENCRYPTED") { + return errors.New("private key validation error: encrypted private key not supported - header: " + value) + } + } + + return nil +} + +// decode the private key +// check for proper algorithm. +// check for correct number of keys +// return private key object, cleaned private key PEM, or any errors. +func decodeRSAPrivateKey(pemPrivateKey string) (*rsa.PrivateKey, string, error) { + + // Remove any white space before decoding + var trimmedPrivateKey = strings.TrimSpace(pemPrivateKey) + + // Capture all key decode errors and collapse them at the end + var decodeErrors = make([]error, 0) + + // RSA Private Key + var rsaPrivateKey *rsa.PrivateKey = nil + + // Check for proper key count before attempting to decode. + blockCount := strings.Count(trimmedPrivateKey, "\n-----END") + if blockCount < 1 { + return nil, "", errors.New("private key validation error: no RSA private key PEM blocks found") + } + if blockCount > 1 { + return nil, "", errors.New("private key validation error: multiple private key PEM blocks found") + } + + // Attempt to decode pem encoded text into PEM block. + block, _ := pem.Decode([]byte(trimmedPrivateKey)) + + // Check that the key was decoded and validate key isn't encrypted and + // other common validation shared between PKI algorithms + err := commonPrivateKeyValidation(block) + if err != nil { + return nil, "", err + } + + // Decode PKCS#8 - RSA Private Key + privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + decodeErrors = append(decodeErrors, errors.New("private key validation error: parse pkcs#8 error: "+err.Error())) + } + + // Determine if the privateKey is of the correct type + rsaPrivateKey, ok := privateKey.(*rsa.PrivateKey) + if !ok || rsaPrivateKey == nil { + decodeErrors = append(decodeErrors, fmt.Errorf("private key validation error: incorrect private key type: %T", privateKey)) + } else { + return rsaPrivateKey, trimmedPrivateKey, nil + } + + // Decode PKCS#1 - RSA Private Key + rsaPrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) + if err != nil || rsaPrivateKey == nil { + decodeErrors = append(decodeErrors, errors.New("private key validation error: parse pkcs#1 error: "+err.Error())) + return nil, "", util.JoinErrsSep(decodeErrors, ", ") + } + + return rsaPrivateKey, trimmedPrivateKey, nil +} + +// decode the private key +// check for proper algorithm. +// check for correct number of keys +// return private key object, cleaned private key PEM, or any errors. +func decodeECDSAPrivateKey(pemPrivateKey string) (*ecdsa.PrivateKey, string, error) { + + var ecdsaPrivateKey *ecdsa.PrivateKey = nil + + // Remove any white space before decoding + var trimmedPrivateKey = strings.TrimSpace(pemPrivateKey) + + // Capture all key decode errors and collapse them at the end + var decodeErrors = make([]error, 0) + + // Check for proper key count before attempting to decode. + // ECDSA keys can have 1 or 2 PEM blocks if the 'EC PARAM' block is included. + var blockCount = strings.Count(trimmedPrivateKey, "\n-----END") + + if blockCount < 1 { + return nil, "", errors.New("private key validation error: no EC private key PEM blocks found") + } + + if blockCount > 2 { + return nil, "", errors.New("private key validation error: too many EC related PEM blocks found") + } + + // Attempt to decode pem encoded text into PEM block. + var pemData = []byte(trimmedPrivateKey) + for len(pemData) > 0 { + var block *pem.Block = nil + + // Check for at least one END marker + if strings.Count(string(pemData), "\n-----END") == 0 { + break + } + + // Attempt to decode the first PEM Block + block, pemData = pem.Decode(pemData) + if block == nil { + return nil, "", errors.New("private key validation error: could not decode pem-encoded block") + } + + // Check that the key was decoded and validate key isn't encrypted and + // other common validation shared between PKI algorithms + err := commonPrivateKeyValidation(block) + if err != nil { + return nil, "", err + } + + // Check if this pem block has 'KEY' contained in the type and try to decode it. + if !strings.Contains(block.Type, "KEY") { + continue + } + + // First try to parse an EC key the normal way, before attempting PKCS8 + ecdsaPrivateKey, err = x509.ParseECPrivateKey(block.Bytes) + if ecdsaPrivateKey == nil || err != nil { + decodeErrors = append(decodeErrors, errors.New("private key validation error: failed to parse EC ANSI X9.62: "+err.Error())) + } else { + return ecdsaPrivateKey, trimmedPrivateKey, nil + } + + // Second, try to parse PEM block as a PKCS#8 formatted RSA Private Key. + privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + decodeErrors = append(decodeErrors, errors.New("private key validation error: parse pkcs#8 error: %s"+err.Error())) + return nil, "", util.JoinErrsSep(decodeErrors, ", ") + } + + // Make sure the privateKey is of the correct type (ecdsa.PrivateKey) + ecdsaPrivateKey, ok := privateKey.(*ecdsa.PrivateKey) + if !ok || ecdsaPrivateKey == nil { + decodeErrors = append(decodeErrors, fmt.Errorf("private key validation error: incorrect private key type: %T", privateKey)) + return nil, "", util.JoinErrsSep(decodeErrors, ", ") + } + + return ecdsaPrivateKey, trimmedPrivateKey, nil } - return pemEncodedChain, false, nil + return nil, "", errors.New("private key validation error: no ECDSA private keys found") } diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go index 659d221814..096a414dff 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys_test.go @@ -1,5 +1,11 @@ package deliveryservice +import ( + "encoding/pem" + "strings" + "testing" +) + /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -19,215 +25,1289 @@ package deliveryservice * under the License. */ -import ( - "strings" - "testing" -) - const ( - BadData = "This is bad data and it is not pem encoded" + BadCertData = "This is bad cert data and it is not pem encoded" + BadKeyData = "This is bad private key data and it is not pem encoded" - SelfSignedCertOnly = ` + PrivateKeyPKCS1RSA2048 = ` +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEApIye2g6c0irFgoMAztPeEuV4ZX8NdORRsV2Ddi4kV9gKYiDk +xQ9eOal3Nea9kDEaUpRvk2nuVl5jbFG3sOore9Vs6YUsCvICDKCUPl5OrxURJ6BS +iC2l0jVE6FVhXf9pLX+OR8lZmMZ9GKbw1nlGGKwdF3T76gOZFSHQfT57vNFsI0Q+ +8NhWbDclNo/AnPpQuBs6ocah83BAVQk3gTRMHO3+rMLuvXVppBBqD+P5OU+LRROr +joDulub2QUPiR0Q5DczqMCjDIQB96LReryN4dx/p4x4P62SLQB6dd2vHvJNmpfl/ +CBzAdSLBRna9mSV6xw429tu5b9Z48Da5gp9igQIDAQABAoIBABoepDyS4zvNREri +RqeOJAs117WsxFMQxxLzeCGzU1uKVKOc+xN4zAk1KFIrDV4tHTOMkmWBBC87jmas +Vg9ELKDckQxEcmhOYBrnBoEb8TuDiZSTs2YgcNj8UbLbkrgcCfMJ82jbwlgo8cSP +A13YJFNYRsnpbO+JoKwlEPZAi92901MrwH5r6kf/D+q6SwLpABVvVux9UzlhKh/G +hGUcB1GhLIq1axwAtlKahkutxyUWabiTu2hGlaY8Q7JGid0t4GZHCvZ0cqQbS/bE +M2x8zskgWQrOPLneuxCYVLtpMaPdrJFSghcD39/Qw5kDiSw83m3VjrlluZG868+X +aooOOBECgYEA0YmSG09MppC2fQlmwZzbiZreygiKkrSwDvYwOwbn2z0DYwSqnJ3V +bHI0MIX4479s+1Lt3Rsr308GRIDmnx/u0gDlrAIZqh5Xoy3p2azQzCEUghr4csIp +sGEPE1FKzFL7UdQvJ3K/QeM2Xux11aF5B+jZh+2LrN3GStpZLyhyUdUCgYEAyQlK +5BzfUC6+c1Kuv6EO4YhlDy23AnTBoeGNEMOe8SQ3h4Fcz2TaOpWs2zXOLGoSoIHs +OTN5VYq3R8AQL4w75OS1Au9+nr4m0o7ix1YI3cBMwseMqQtR0OvrzOSZSm2fQZtO +SBeLPnLNg+XsR6Adxy7r2qSz9aYbXQA0WvHw9/0CgYEAxDbpJL27b3awDKKTINb8 +Ff16hwI8kWi2PSx4ua2bzIdz9nNWONbsFmNTT+UEznBhY2+i4pwhFznvCpMSYwwK +HYlNiSdmVRGYy2uhQn87/wszIyqSYRRE6a/Z6CMFwhQq19O0XGJtiwtzzKvtJCHT +Ln7zxP/C/hunJk0Vmr1rYAkCgYEAkPvCpwCrjIgpkcHvhQQCV2SmfWvasErD2ptv +wMdTuVUFNxR0ep2hRN7s6qrDJgTZqigI1LfqqWaBB53cDm50Q38tjBBsoM9B8Fhb +9KZ3fnVQ5qhDKSaguqtqQzoZ0zN7xzTaH+Pa6A6jaJxI6t7umtecAPMHVgGVelzL +ZUtXHYECgYEAyOZQ9HevD5jaWE//wXggjdASE3CFu5QkKJ1MEhEz3O9DconflKh0 +e2TVphH64nagLC8G3ta9aSHch56r4frnZ7wc6xX2sORP/PCg3iAmvEtzaevQHQue +T5BkD3zmC6RQIDOYN5DzpokgXZLuTCUl95evqAsIZ6Cd3tqNCqrJIfg= +-----END RSA PRIVATE KEY----- +` + PrivateKeyPKCS8RSA2048 = ` +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCkjJ7aDpzSKsWC +gwDO094S5Xhlfw105FGxXYN2LiRX2ApiIOTFD145qXc15r2QMRpSlG+Tae5WXmNs +Ubew6it71WzphSwK8gIMoJQ+Xk6vFREnoFKILaXSNUToVWFd/2ktf45HyVmYxn0Y +pvDWeUYYrB0XdPvqA5kVIdB9Pnu80WwjRD7w2FZsNyU2j8Cc+lC4GzqhxqHzcEBV +CTeBNEwc7f6swu69dWmkEGoP4/k5T4tFE6uOgO6W5vZBQ+JHRDkNzOowKMMhAH3o +tF6vI3h3H+njHg/rZItAHp13a8e8k2al+X8IHMB1IsFGdr2ZJXrHDjb227lv1njw +NrmCn2KBAgMBAAECggEAGh6kPJLjO81ESuJGp44kCzXXtazEUxDHEvN4IbNTW4pU +o5z7E3jMCTUoUisNXi0dM4ySZYEELzuOZqxWD0QsoNyRDERyaE5gGucGgRvxO4OJ +lJOzZiBw2PxRstuSuBwJ8wnzaNvCWCjxxI8DXdgkU1hGyels74mgrCUQ9kCL3b3T +UyvAfmvqR/8P6rpLAukAFW9W7H1TOWEqH8aEZRwHUaEsirVrHAC2UpqGS63HJRZp +uJO7aEaVpjxDskaJ3S3gZkcK9nRypBtL9sQzbHzOySBZCs48ud67EJhUu2kxo92s +kVKCFwPf39DDmQOJLDzebdWOuWW5kbzrz5dqig44EQKBgQDRiZIbT0ymkLZ9CWbB +nNuJmt7KCIqStLAO9jA7BufbPQNjBKqcndVscjQwhfjjv2z7Uu3dGyvfTwZEgOaf +H+7SAOWsAhmqHlejLenZrNDMIRSCGvhywimwYQ8TUUrMUvtR1C8ncr9B4zZe7HXV +oXkH6NmH7Yus3cZK2lkvKHJR1QKBgQDJCUrkHN9QLr5zUq6/oQ7hiGUPLbcCdMGh +4Y0Qw57xJDeHgVzPZNo6lazbNc4sahKggew5M3lVirdHwBAvjDvk5LUC736evibS +juLHVgjdwEzCx4ypC1HQ6+vM5JlKbZ9Bm05IF4s+cs2D5exHoB3HLuvapLP1phtd +ADRa8fD3/QKBgQDENukkvbtvdrAMopMg1vwV/XqHAjyRaLY9LHi5rZvMh3P2c1Y4 +1uwWY1NP5QTOcGFjb6LinCEXOe8KkxJjDAodiU2JJ2ZVEZjLa6FCfzv/CzMjKpJh +FETpr9noIwXCFCrX07RcYm2LC3PMq+0kIdMufvPE/8L+G6cmTRWavWtgCQKBgQCQ ++8KnAKuMiCmRwe+FBAJXZKZ9a9qwSsPam2/Ax1O5VQU3FHR6naFE3uzqqsMmBNmq +KAjUt+qpZoEHndwObnRDfy2MEGygz0HwWFv0pnd+dVDmqEMpJqC6q2pDOhnTM3vH +NNof49roDqNonEjq3u6a15wA8wdWAZV6XMtlS1cdgQKBgQDI5lD0d68PmNpYT//B +eCCN0BITcIW7lCQonUwSETPc70Nyid+UqHR7ZNWmEfridqAsLwbe1r1pIdyHnqvh ++udnvBzrFfaw5E/88KDeICa8S3Np69AdC55PkGQPfOYLpFAgM5g3kPOmiSBdku5M +JSX3l6+oCwhnoJ3e2o0Kqskh+A== +-----END PRIVATE KEY----- +` + PrivateKeyEncryptedRSA2048 = ` +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,A6E695C7D7038524 + +YMB2rcNobMEfCRzLcGV5uSF5g1hMIuHlJjZHG0QYNpeFdP2pONtgGLH+NIVWbb7B +2dYHUbofywcJTGPigSIm0RUEHquz/+seauRXs0jvN0cEKgEyWVaQZB9yem+V5sJx +guicvKmbWfiV9u004n9G4ue9IxpWwoZp1KixOrJ7GOmRhJsNL8E9MUpJ8kD1eOIY +n8RBuo/sQMyDKinL7npk5IYE3N1tQuVAxpEn2KVXjDIIrl0SeCO5pfJdXA40Sw8Q +6bEF8GogDuEaibw2XzOfqzJsmQRks1STtCqKVnN7b7HjpY3pPgYqMqc9BVKWL3PF +a8G5BSGjjosu3SPuzIIlADlQm65O8Qi/6eZ9thByfGBtXcanSdYZtoprreEikhgC +MYnID949McXvnJTjB1snWni2FYhrWuH6iK4/7/UevFg74She5qKfwuw/YXe+p2pP +Z0ON4olUgG68/aReRoICqDurDW88zklbq8c18ECI8ppBy3tDB85Sey+ybwTliSd7 +FLBhwk/vLuhBlX6kVba8CkBUHqu8T9zECyLK2f7geDUjsw6EVXYy7whJE9LL1Sq0 +cSUpyMb5I6RXOe90zj59sBJddEsllSn2KTMhrJa2LPj+j6Df4PuwmsKdPz+DWo5r +TTAvc3iN9sZbXGjwbjiJulzapNPsfOYXrSlN9KrlkHxvmJQq0Y83ZZqmGE+Z54Z4 +TMfA/rKULJ60BSaBIwVb/NyQC+6iKUpiLDMdWhVEqKXtes7fpHnrHwHYPtTMRc6S +EG+txT5gtUKKuddBTx01UZA67L40RyC6gwbg3zipOY5XFChLQ8O4hjSaDZuQEgik +ewZhJ4ExH17+f3GaNAgPE8OtafSF86jcqt2lowrXbPi1CV9BHSriD/2G1WQycjma +Z8tFSb40fxvWHTiuDs9AyymN3OKpVX/IBm8gFxeitryxSYZ4ZOtsI7fTH+hH74C9 +ceKwu/3iPednzj1NvTpBdQvuEHRzgN/YfABXdJ71WiYRwVtE+hsdPJkKAdNYRXVs +YWJU5Ry5CAyaKZ//XsqqXM6PeACbRfWt6lqHSxnuaJuuh6dn2btJj4hX4Do81bh/ +qwKUwzIVmJCtyEaO1VsslQk7CnLZ2dErIWGnRVkeLY0wMW4qspIZUx7ikgJZZ0sz +XFMwByTkVOtzz24nX3DdhxXfClqk1wrUI50erG6XbCjbuN/XEWbKZNLKUrfxkNys +1GjCXr1qagz6s8igxAHNmK2I9N8lyZSLrqKZf6m5CjyLMHSqj95jEeXL8pw29FLs +0BQnpfuqqTQfonYDSxdHgMPZfT2y+iX5LyIaozTJuQjsDAKXhFbytrSZ9as/kmtB +ne8L04gDLiHcX3K0anLSZN/0N06LiIa9O3qygfBHdtB3iIlBnE+yuGMZGPo2KXSe +4HnU/9E6Sayh3hHEqYtDnfVtNSQhJEwGr+HgX2+wvfQYJCUX/x+2gSN40/aYQ1jI +h9gynY7NK8WybupP8JsjJ8t0UOaFwfXC2har1kq/uChOGnsBI+E+Lkx9mOPkpQ0M ++NkN+HYuZC6dqUJAUZmHdzGPgh5MPZiIwusaW7frswmKko32y9VDfg== +-----END RSA PRIVATE KEY----- +` + PrivateKeyECDSANISTPrime256V1 = ` +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIM1u5X+fmuna0jK5NoBO8CRWJiTzopg9xzqjs34dB3osoAoGCCqGSM49 +AwEHoUQDQgAEq0gH7B1q2cWMDvYTmFr+xNmbrJBMK9ERmZkSfRfaDmzxqvE56FrB +p3aue/xDiaFp9yniuM8lqbTWHwyopraMlA== +-----END EC PRIVATE KEY----- +` + PrivateKeyECDSANISTPrime256V1WithoutParams = ` +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIM1u5X+fmuna0jK5NoBO8CRWJiTzopg9xzqjs34dB3osoAoGCCqGSM49 +AwEHoUQDQgAEq0gH7B1q2cWMDvYTmFr+xNmbrJBMK9ERmZkSfRfaDmzxqvE56FrB +p3aue/xDiaFp9yniuM8lqbTWHwyopraMlA== +-----END EC PRIVATE KEY----- +` + PrivateKeyECDSANISTSecP384R1 = ` +-----BEGIN EC PARAMETERS----- +BgUrgQQAIg== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDB563eEBAdLcLBpgUi3WOszJS6JOHkAcAePAWX/fvguKP56brbIsZnl +/IlujyM6RACgBwYFK4EEACKhZANiAAStW0BfZ2KCkmBQv9Cc8GT9hoGDRuJvfbj0 +cmgIRz1yhqHy1Psw3/z8FhhBkhm1Y0InJ7xxt0CsOYs2/faAOmNcKt3mwwthLcEy +9XVZrwbog5s76datlz/7iVd4Jo7vS88= +-----END EC PRIVATE KEY----- +` + PrivateKeyECDSANISTSecP384R1WithoutParams = ` +-----BEGIN EC PRIVATE KEY----- +MIGkAgEBBDB563eEBAdLcLBpgUi3WOszJS6JOHkAcAePAWX/fvguKP56brbIsZnl +/IlujyM6RACgBwYFK4EEACKhZANiAAStW0BfZ2KCkmBQv9Cc8GT9hoGDRuJvfbj0 +cmgIRz1yhqHy1Psw3/z8FhhBkhm1Y0InJ7xxt0CsOYs2/faAOmNcKt3mwwthLcEy +9XVZrwbog5s76datlz/7iVd4Jo7vS88= +-----END EC PRIVATE KEY----- +` + PrivateKeyECDSANISTSecP384R1Encrypted = ` +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,0B0F937007A25C35FBB3DEC9F09C0343 + +KIRWqbmNfP3xnnDE8f9Ndx/aaNvQBPCucQrVHc6ZYpImPnVmIzH/eOZMyio7HQkZ +tH2ggwwI+zSg3cJWTehJaR9j9qiFtPH+UDEA03co2QyIyERk1wI5ev4hv822tmtl +/TrYpdjqNkfDZUcZscuf1VHkjSrAwn+3K0NV5hUGfdhWryZ7B16iKyCJrSrbde4x +E34vrABCPJZtg/O7SbXQL8cURtVoEdbT+AveW3qoh5g= +-----END EC PRIVATE KEY----- +` + SelfSignedRSACertificate = ` +-----BEGIN CERTIFICATE----- +MIIEIjCCAwqgAwIBAgIJAKfsBagyQeuuMA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCQ08xHzAdBgNVBAcMFkFwYWNoZSBUcmFmZmljIENv +bnRyb2wxFDASBgNVBAoMC1RyYWZmaWMgT3BzMRUwEwYDVQQLDAxVbml0IFRlc3Rp +bmcxGzAZBgNVBAMMEiouaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxNzA4NDRa +Fw0zOTAzMDExNzA4NDRaMIGFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ08xHzAd +BgNVBAcMFkFwYWNoZSBUcmFmZmljIENvbnRyb2wxFDASBgNVBAoMC1RyYWZmaWMg +T3BzMRUwEwYDVQQLDAxVbml0IFRlc3RpbmcxGzAZBgNVBAMMEiouaW52YWxpZDIu +aW52YWxpZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMOXU/IY3uIA +Kb0QjlWC0eEEGQAVBTOWqXclb+Ov2fZbJ+DGfrRmmBRk4Sz3H5p/l79mVDd5+Npm +UchWSut9o/lYm9zbZ6HDAyE7O9vtO7uNGq+Odg3lUzh3QSZzh+vaMeYRMzodGK+7 +6vkZ6jxGJRMazZO2LghuLH7g3ft0Dbd/QFGOQHkP/y2KeNt7jeuE4OT6jjA6OdSG ++q/gXAtFADQKkx814pEAyp1T4K59rteN2KoCbRiNrgxuewgkeu3VOGTagkwbyav1 +o3uxE+wfc3r0TOdW+2xLUO9KlaG3pioT8Vh1YcwZvghe+mkueyod1VldKl4vgH0N +sUEMpi5zB68CAwEAAaOBkjCBjzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQEAwIEMDAT +BgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUJguFG8ibiS0+orhtIBPDUPAT +jL4wHwYDVR0jBBgwFoAUJguFG8ibiS0+orhtIBPDUPATjL4wHQYDVR0RBBYwFIIS +Ki5pbnZhbGlkMi5pbnZhbGlkMA0GCSqGSIb3DQEBCwUAA4IBAQB1th3ZUxczr5ZS +5Yem4KGLAAQck0o71cvmIMLXs4u0ioehM6UDxNrOwy5XaxLweZebIuUgZ44+KZU/ +UerqSinWE3zsNpHbV+7j60aFjuCKAj+9WtJVVa/A2KLPVMYaoGITgdohHeYLKqWO +6io1VvLiahXa6G1nElPhRwdBU5qnJ651I821xf9TKeIUZM+bmYyqDE2FKHbZ+hBB +AGrT265gN3/aZKi5C5s2YFZ3Oc7dlZ1ZUhZqiLeTr8cmc9bZAdNY9ppDn3xs8ThI +GQlQzUI4o2FE3OdwA28PO78/DvnZ8oVeF/KD19oExJ9tj6dzLZIrkxaRDu7CD70S +41PQLy8Q +-----END CERTIFICATE----- +` + SelfSignedRSAPrivateKey = ` +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDl1PyGN7iACm9 +EI5VgtHhBBkAFQUzlql3JW/jr9n2Wyfgxn60ZpgUZOEs9x+af5e/ZlQ3efjaZlHI +VkrrfaP5WJvc22ehwwMhOzvb7Tu7jRqvjnYN5VM4d0Emc4fr2jHmETM6HRivu+r5 +Geo8RiUTGs2Tti4Ibix+4N37dA23f0BRjkB5D/8tinjbe43rhODk+o4wOjnUhvqv +4FwLRQA0CpMfNeKRAMqdU+Cufa7XjdiqAm0Yja4MbnsIJHrt1Thk2oJMG8mr9aN7 +sRPsH3N69EznVvtsS1DvSpWht6YqE/FYdWHMGb4IXvppLnsqHdVZXSpeL4B9DbFB +DKYucwevAgMBAAECggEBAIwTGVx9sUmbokizzaux58tFmv3zD+mVUcJxfkNK0kdb +myCgJ2fdPbcFVDpWtTx5elzp1RBx+uW2d4WJP1iNf1x4uA8g1oQD3H71I/ZqXOgB +swXdefCTttjulysJfGNNvYSt9sj8w4w/gZVqmNUXyz92Z5oM08TX2mf3dSK7R4OM +jk3hgGYXbgLg9ZMy3DuiZlkzIUY5sk/574j3pYaSaA+ufeIINzovod7zfqIT+5HY +nmoHKJqEjd7gZ2U0EVn3n39NXV9+eBsjuqC5aFB/oGYvH6rkXa+10vILImNoJEl2 +PRMIWggvKyG+rFn714Y5QnPwLP/So71Hq00XSMTOCUECgYEA8MVfyRuA8/d0Jyas +NZv0lbtsN1XyZ5MRsNND4DkZR4Gz3Z5JT6mXwlzTLFMl6RKxPwkxLowYGeJQnEnK +5navmcvjr9EbMrAiebmCam1PWfUKxvLVWgw4sLrscD2YlB/ylm3CugLB6p2eS5HV +7bqGhrS56PtjibZbU0dBHIc7Ek8CgYEAz/Zjw8GBV4bh9dqpKB0Kv9VF05d8maLH +X6ybRSacJ24u/icYijq1vIlz5P7fM1enVkIKF3K8V2aToMjFShnAkdWxk1Ss6UrA +DsuRq1WAf9vSIsSDao8Cl4We7M9mbnGj3pEmxdN+Fh5l9Gs09cb8v75UacDrQ3AA +x/izdR9ePKECgYA5uCdZT9WfJuBajmPUSjndN1we++Srvc8M4+iutSGBSe+znkGW +7mIqPxSE2L4K3OdO5EY9EWqpsd5/SRVyIFvCc+V2fZuWkDEDm1xPZTsTprHZtdc9 +yhZBD96kna+ZOvtt4ow/CXAxbW3IUgLGBeRAIM08tB9NoUDNexR54VVg8wKBgAhU +ZSCVIpof4/MWBAqAR0rxvu8/tRTuSTAS2NFHP5/wsN8rL7dxrI/VrZexgb0ruJ8i +3AaeaN7TU/xvrj9OksEEny04igh6HwE4tCf5r8DvTBZqap0dB0yMZJY1pHOuB5NF +mxj3ZKh8JTdKCAAELWF8vSLTQFkeJlncI0wAqqShAoGAR/iDslDHU0M/CjvqN+le +m91MxJsaFi3FZ2Pv60ghqG27X8uPbgvGXkTmmcqgAaR/Fh8b1UH+yqOnPUiremxO +oIuOOmvkBAyy0cHT/BSunqxiFOWcu9yb+2MfSWaHHxNj3kteif8Oai1lL84JOucC +/FZTue8KxnrjBcbGYYtwPCU= +-----END PRIVATE KEY----- +` + SelfSignedRSACertificateNoServerAuthExtKeyUsage = ` +-----BEGIN CERTIFICATE----- +MIIEiTCCA3GgAwIBAgIUK/LEzHDA/Hf2aGdnDSka1jov0uswDQYJKoZIhvcNAQEL +BQAwgbExCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMG +RGVudmVyMRUwEwYDVQQKEwxDRE4taW4tYS1Cb3gxFTATBgNVBAsTDENETi1pbi1h +LUJveDEnMCUGA1UEAxQeKi5ub3NlcnZlcmF1dGgubXljZG4uY2lhYi50ZXN0MScw +JQYJKoZIhvcNAQkBFhhuby1yZXBseUBpbmZyYS5jaWFiLnRlc3QwHhcNMTkwMzMw +MTkyNDMwWhcNMTkwNDI5MTkyNDMwWjCBsTELMAkGA1UEBhMCVVMxETAPBgNVBAgT +CENvbG9yYWRvMQ8wDQYDVQQHEwZEZW52ZXIxFTATBgNVBAoTDENETi1pbi1hLUJv +eDEVMBMGA1UECxMMQ0ROLWluLWEtQm94MScwJQYDVQQDFB4qLm5vc2VydmVyYXV0 +aC5teWNkbi5jaWFiLnRlc3QxJzAlBgkqhkiG9w0BCQEWGG5vLXJlcGx5QGluZnJh +LmNpYWIudGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKfcO00F +XWEnW9cWYSvw/SzmFB02q8ILFyfbFmkxbDDIZyCmiZIoc5xQdgOU9ZcwwS4Xc6Ae +mVbvLn+L/nw50/w7+cX7BSAwMbcANKrgr0OSqHrmvXSZ7xpn7DWb3nrbphnIzRMf +CiQs76cygXV23u8NO4Qed/mlapUYux+SA4t8wVr3ZN8gcoal4f4kv2dZ/nZAXjPY +EAugZxP+hsKF6IhlADOFDssOBUWXB+TE54z9wdUVwovOSOQoPOpoVsc8rcVGHkGm +pjXnd5CcgLv9M1k7gS7nEElUwNWGAY4e0RJqDy32ft9PlGaTVLNxAKzSC49GQBWu +hJGZ7AmgyRIqfB8CAwEAAaOBljCBkzAMBgNVHRMEBTADAQH/MBEGCWCGSAGG+EIB +AQQEAwIGQDAOBgNVHQ8BAf8EBAMCAiQwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwMw +HQYDVR0OBBYEFGGKXpBZaG8HuUnjoI6cqZenJdwVMCkGA1UdEQQiMCCCHioubm9z +ZXJ2ZXJhdXRoLm15Y2RuLmNpYWIudGVzdDANBgkqhkiG9w0BAQsFAAOCAQEAU99E +B0FUyyB90tlGQuMcl3FPRGXwfzSZgqTzdVDAtYNoYO0iqUgzjPhdZyV8Ai8zXbzI +qBiJfqbfu9hsR3l7snjxgXgEXhfYpZO1xyA0TJNrWWmcw/HRTndBclzhBgo8qunF +euO8CSUuZ1QY+cjptM8AQFlgj3PYNOEN2horwCl08Z3K858kOaH8CQ1mHBEonlaj +mGCqKyoQftLi8bmA/PZMOQoIGdgsIsGtt0p4cOJ2+fEwJ1Y0uGT84cOtq8zcHaRl +xqG7Q0ClQAeUC8PuCOZ37tRDdSJ+P/7RGJsiXCA3U8mRJg7nv4pCMEwJUkbhMoXz +RW/yw0YwdzYB21veHQ== +-----END CERTIFICATE----- +` + SelfSignedRSAPrivateKeyNoServerAuthExtKeyUsage = ` +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAp9w7TQVdYSdb1xZhK/D9LOYUHTarwgsXJ9sWaTFsMMhnIKaJ +kihznFB2A5T1lzDBLhdzoB6ZVu8uf4v+fDnT/Dv5xfsFIDAxtwA0quCvQ5Koeua9 +dJnvGmfsNZveetumGcjNEx8KJCzvpzKBdXbe7w07hB53+aVqlRi7H5IDi3zBWvdk +3yByhqXh/iS/Z1n+dkBeM9gQC6BnE/6GwoXoiGUAM4UOyw4FRZcH5MTnjP3B1RXC +i85I5Cg86mhWxzytxUYeQaamNed3kJyAu/0zWTuBLucQSVTA1YYBjh7REmoPLfZ+ +30+UZpNUs3EArNILj0ZAFa6EkZnsCaDJEip8HwIDAQABAoIBAGWau9ZaGfS1szSV +GkpTu5uSxLgOIJb6yZBZX85amQdKNoof5AOxMpF6boSqhKF4ZGY20cko3F4vtrCD +l42wHy19TCnXUHn0UhNYL4kDKXM4cXy68BCFIKKWJvcoGtm43GidD+y0DBprjMBi +pNPqGPUPyGenXa2hv8rxxkpMwpKJ/JHdONq0m+eTu3lCRdxhVVHbOn1xQmJTgP2B +CyrtmBD7rJ5AhDNYQ7GfL9WwVf1UeFNaOuAOEK9T7Weqm3Ak5Pd1dJUwukXk/vND +Rcu+cWhklNTVIUw9XwXawPpFm03iZiTcFurAcrShXrtW7aY38S1e7w1fRSSxhrfQ +GroShXECgYEA3rjHANz5dx/Z0EUQ3rK6MgOuKpsS4rAmpydqY7PFfNkSgQzsUwot +o4VRIiKd16voodvT9CZausgCut6ZqCpVgwZY0Mg9FBEBXfxPIOg5oRNmje7RHAfD +Q9I2yiEgBZ6exi3m4lZKgWSNvKkocY/HLIwsDz4kEq4ux3Gr2+zkIacCgYEAwPD5 +N0R25aO06gI/eeYOV0P0Y0h3OKCtF0b/PwU4tKSuqQiojeIvmoJspbCZJbg+D6Da +0kXgEhybchVBSzgeOggZb+sZl0Odg1eqJea/kbz7JyO0NcZu3t7wg5AVynssF6s0 +JUcDFxELfW9GYLtdzR8LeWvgaezSwZBeYmV1cMkCgYBtri1CPZAUm/jV2c1O/lE3 +ZByXGrsYK4s9cemwo80ziGrWZpjS5AZJqtOjrcxxc1UisHEWoPS5WtoNUKX27LIj +zjJazuFVSnKT6DbHi9Ulf7pXVy5fUWtVsOYOcHWmjtC948j52Wjjg7NRHzStiBKb +24OvFfkJwgGDcnUh3u0RrQKBgG7ZxAVp03nKXYXY9sk9UN34T+++0ah6QBhQlROL +F3JJ74N0Uwr5eeompu9nEAYo3ZczDqWiucMOJo0cAyCJRGyI/LxdcZ2Dnnq4oiwW +b9f2oMFy9PW0ZTytD7g2zx4/OCz9Ev+b1f2psFVH2kJ3Q8Q24uvG++8/vjKxlFip +/BhpAoGAJmo5n5fR9+q1Zwb4Gs9i/gquxcJsWo9eaCgQpt+IK0oqqgi/8xx61PCW +Xeg+Gf0gAv5J/WfbYpBCLD4K8o1COm7ZqZGqG3kFTWYjh0jRm8hLQF+8kkn0Fby5 +ohq7Fw9P96opYCnxqau5nfiHExfyfLNQZlj7dPHZZPCEhUFYSSo= +-----END RSA PRIVATE KEY----- +` + SelfSignedRSACertificateNoKeyEnciphermentKeyUsage = ` +-----BEGIN CERTIFICATE----- +MIIEojCCA4qgAwIBAgIUXy/RKN+PEOQwwlsQYJ4FR7HUZn0wDQYJKoZIhvcNAQEL +BQAwgbYxCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMG +RGVudmVyMRUwEwYDVQQKEwxDRE4taW4tYS1Cb3gxFTATBgNVBAsTDENETi1pbi1h +LUJveDEsMCoGA1UEAxQjKi5ub2tleWVuY2lwaGVybWVudC5teWNkbi5jaWFiLnRl +c3QxJzAlBgkqhkiG9w0BCQEWGG5vLXJlcGx5QGluZnJhLmNpYWIudGVzdDAeFw0x +OTAzMzAxOTI5MTZaFw0xOTA0MjkxOTI5MTZaMIG2MQswCQYDVQQGEwJVUzERMA8G +A1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRlbnZlcjEVMBMGA1UEChMMQ0ROLWlu +LWEtQm94MRUwEwYDVQQLEwxDRE4taW4tYS1Cb3gxLDAqBgNVBAMUIyoubm9rZXll +bmNpcGhlcm1lbnQubXljZG4uY2lhYi50ZXN0MScwJQYJKoZIhvcNAQkBFhhuby1y +ZXBseUBpbmZyYS5jaWFiLnRlc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCiOfGhT8EgpDoMLq088R5HR0MXfgwc9XoFZmB5oyZvTDcQkGJH48Z2tFFt +d3qoa5sbyiu5/I8j/J4+NXvYBLLaTNMTz4fFknFmlssyR3CXUjvh3wlzWVJ0SkA+ +GLfnZdX1zJ+35Grf/bILeV0kl/WKoFEyI9CZW7VbTaRluoCxrINlGtLzi+K+kHRc +lxv4EZ6TcgJZ0lT47OSxUTTTDKH4L2rF6dOltmGiGdsMyhZsIswKbM+eEliEYA6Q +3CT5s/3FwihS27gWJq+ORAKuz77Rl+n3epzWaAfD0M/P+eCPNFEqJgMVw72x7SlD +9eyiNns0iq2OvevjMdiBvy+34jNbAgMBAAGjgaUwgaIwDAYDVR0TBAUwAwEB/zAR +BglghkgBhvhCAQEEBAMCBkAwDgYDVR0PAQH/BAQDAgIEMCAGA1UdJQEB/wQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAzAdBgNVHQ4EFgQUtUhWjz+wVZTK5DXkyiqEGVp4 +tvgwLgYDVR0RBCcwJYIjKi5ub2tleWVuY2lwaGVybWVudC5teWNkbi5jaWFiLnRl +c3QwDQYJKoZIhvcNAQELBQADggEBAFClaIKSL0wdeXP94UAcsruRaQyQiOxcx8uu +k3MvMyUXyyTZIMUkKdIetc9uDfcEELJ0QfAKQPNzSEDHniq7b/Tlp5BnmfhMcWFQ +zmegfM/J3xAsJE02IHEKOuyUw9Vm96mzVQ2QfoHcJaBRpl62oHr0PD6R168aSqTe +eqnBe9O03+2WA99Fr6SZDVsOoZFoWYiMBqphKtLDEBvc40v0Tk9oSjOnRNnvPEW2 +JLO38D82IakS2TNQh49tYGwZmLqbXzqLCJ4hqMHsk5lgOzXwc20wM5864fpb+fp0 +eO1J8sGqqiTmh8bnyo6O3Ru4qIs16LXpW8KLgAohSQej0p6tzlo= +-----END CERTIFICATE----- +` + SelfSignedRSAPrivateKeyNoKeyEnciphermentKeyUsage = ` +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAojnxoU/BIKQ6DC6tPPEeR0dDF34MHPV6BWZgeaMmb0w3EJBi +R+PGdrRRbXd6qGubG8orufyPI/yePjV72ASy2kzTE8+HxZJxZpbLMkdwl1I74d8J +c1lSdEpAPhi352XV9cyft+Rq3/2yC3ldJJf1iqBRMiPQmVu1W02kZbqAsayDZRrS +84vivpB0XJcb+BGek3ICWdJU+OzksVE00wyh+C9qxenTpbZhohnbDMoWbCLMCmzP +nhJYhGAOkNwk+bP9xcIoUtu4FiavjkQCrs++0Zfp93qc1mgHw9DPz/ngjzRRKiYD +FcO9se0pQ/XsojZ7NIqtjr3r4zHYgb8vt+IzWwIDAQABAoIBAEm+Kz+XwIO1A4oM +IcXFGW1vUGk6bAkx8TDJM+u3JT6Ml69Y4sQpH0tQdn9bQ4+RsqV0RmI6E1tZdxly +OISexiqDp6Omv+IoypHG1EFbxiuTPxNSzrn3jYq9Qey4UcjHOvaL+MKf+5EsgqXC +mnuK9Bv6+k3fh/BehtclOSjhGaUpvBj4FFpVm5aQT1PlrfsSJsY8AhAsqyO3mO0Z +ndfSd2u3/T795h7XVyarJlZquaExlAe+rsrmdCciU+0l27Wh9HzY145sDtuzSPGm +A8hWredHQ6qVwz4EpVZUj3HDowHi3krqlQitc144CBA/PejTV7jby0piKAZ8agKK +pCiRvxECgYEAzvBKma1oJWVa3oM1sYsan8RcquqHRQoE2q0xDmKgQPa4mihyXfCV +iPDPc2jw+0/M6fNgFlhVppMVqJyvScIELKH0HsRtoZyDiaoVkmQY/EG4xkS9N3zK +6OXs9y/1nHHFwsKe3EDHuPKWJAHDAx+x9OrQ5o67Vc9MDwmwt4bJiDkCgYEAyK/u +3UNWrBVQuT4k8klI485HCJCV6AO2egONw/dGFeZJ9W20Uw/eWAAuphT6HKqwSlBt +0EwTpjL9dnuoTrS2TcTLq7UwTN9Gw/1VhE1of+nbsa0kWAqDqhpCFMZQ2/X9ehDv +cqFemW4HE1la3E9izwlKGU3ehpHwWjRhJbH8kDMCgYB+uS2l4EgHpoK4AneuCrY6 +ImBxFf/SKmmAlFCXM5RZU/0GAkDPABZCbt1LGneAHoUouy4bYOrKgAXiZFj/fP1b +a6337WgJcLQoaGyfYgbe60xAtjV9NkF3z92GHet1a0KkmtP3ov/rZTrGQAHw9sbe +abGVjtBvous7xj5elP7zGQKBgQC2TtRwHi8LLmXhkemgTCCyCX6P8kCrv0uyNa5A +Gk6JsGT5VopcdmrmiGvYJfA7wHdbWwsXETU8Ys/MJXN05EdECIV426UgACjZ/DYG +dQd8Q+Z21rHQZOTMzwO+uZVU7Hcyv1W2TY+RU9mLoz2eK2O4bljo+csvdj3gw/qI +ctLb7wKBgFOwu2jZJE66DJ2AUz5XgeY0EOSH8ZIpdEtRQriE8R397KHb8Pmt75fJ +F+nJV58mV+vR/r3qlMViq8Cfb8cZz47Dn00Q2udMoOLKLiKgu1yP2pdCs24VbwLF +7FDXBcacw5kMQfw5DxWDqgXqbwl4cdS62m8kRA/idZNqdHtCmICA +-----END RSA PRIVATE KEY----- +` + SelfSignedNOSKIAKIRSACertificate = ` +-----BEGIN CERTIFICATE----- +MIID4DCCAsigAwIBAgIJAI84W5tsR3z4MA0GCSqGSIb3DQEBCwUAMIGFMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCQ08xHzAdBgNVBAcMFkFwYWNoZSBUcmFmZmljIENv +bnRyb2wxFDASBgNVBAoMC1RyYWZmaWMgT3BzMRUwEwYDVQQLDAxVbml0IFRlc3Rp +bmcxGzAZBgNVBAMMEiouaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxNzExMTZa +Fw0zOTAzMDExNzExMTZaMIGFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ08xHzAd +BgNVBAcMFkFwYWNoZSBUcmFmZmljIENvbnRyb2wxFDASBgNVBAoMC1RyYWZmaWMg +T3BzMRUwEwYDVQQLDAxVbml0IFRlc3RpbmcxGzAZBgNVBAMMEiouaW52YWxpZDIu +aW52YWxpZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2yyphDlkc0 +AmpxPAp0GZkPiGM5PgkahtafnIMCWXC5JkWz1Qk7dSgKUNl6hXg3I1dBJ/Kej461 +XwRSPNVFp1ehUsl7+D6QJy7+WEuk4Ea3s6/btMByH6+7S5EvJJGivavXlaLfqXnD +2vRKW+6EuabNpeNVplYrZQYQ2aHYIsY+HYInzqdpb/qx6BSbuvuV74N6KcI7dbpC +551y87hq2U/Mftka1TmfT/ll7bKdZ4q192ME14/USGqmyy8HHAiFvsgRjmqUUe3N +6+O0VOjjTDByL1naMw5MlSIhcIOM4O+rklAiKVzL9ONc1rz1U38JrNeUjD6pEleD +cPPBR1ge8DcCAwEAAaNRME8wDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBDAwEwYD +VR0lBAwwCgYIKwYBBQUHAwEwHQYDVR0RBBYwFIISKi5pbnZhbGlkMi5pbnZhbGlk +MA0GCSqGSIb3DQEBCwUAA4IBAQBtkA0rtyLblXFDOntBY68gpcgaa1KjUo9YNfku +VywCVan7ZoxiJkCsirIonugJDan1Q+meMsA2tO9UXoxShXSyh6pEcqEa4uSelj1M +IysFFdtCwcUOzL3OwAY1TecC3rRadJD/hWM1F3iHPpG3BGB1LDkEZVCQdi+Gtq/C +UCHb6g1lluLt/pxHuicS4etEd1zTb1oh2CbcijMLFSGimPqkqmSBOkgO6/283xA3 +MOSm/w7yrLylq/N7/g5c6kLZSWkYpoxA5PgImJEsOwoFF9VrMzC4JPLdR3zjLq/T +wBmyIzcVFJ2g4V0iS5Ufi6uHwc7A03PVA50g7p7JUVRx5q/B +-----END CERTIFICATE----- +` + SelfSignedNOSKIAKIRSAPrivateKey = ` +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC9ssqYQ5ZHNAJq +cTwKdBmZD4hjOT4JGobWn5yDAllwuSZFs9UJO3UoClDZeoV4NyNXQSfyno+OtV8E +UjzVRadXoVLJe/g+kCcu/lhLpOBGt7Ov27TAch+vu0uRLySRor2r15Wi36l5w9r0 +SlvuhLmmzaXjVaZWK2UGENmh2CLGPh2CJ86naW/6segUm7r7le+DeinCO3W6Qued +cvO4atlPzH7ZGtU5n0/5Ze2ynWeKtfdjBNeP1EhqpssvBxwIhb7IEY5qlFHtzevj +tFTo40wwci9Z2jMOTJUiIXCDjODvq5JQIilcy/TjXNa89VN/CazXlIw+qRJXg3Dz +wUdYHvA3AgMBAAECggEBALZkgyEV0xdRLYV0rJsMeFRPt/5XWotcQwt3WgApMSAO +FXttZkdDMOk3yfbhNBWbRlKt5iAETtmTD/HStIUHPNgn17a8iLp21gX8LZ9FvxKf +rJhI8ikbUdYgio7kug+BX0cruMdqr8PRCeRa3rueR/bWwkqr3ov5m1/Ssb5IV18t +UFj7c2nV9JMB0Wq30Awa2RcAFwC2zBkNcyZ72bR6x2DxV+QHG+xDzLO5y/PTuLEF +GBc3a9ExByC8RtUlC1n2YCwe6HSZBPALoaCIloo2isEpLpAy2ihxxaJ+tJh6iScB +t9RAvffPNN6AgRIM5qfWaoGR8E60yFBPrkHPTgCiICkCgYEA30yqVmU3zxbTvNQH +gmRCJrUW++ReLsa7xnaZmN4Pn72tGzdpmhajUWgw7LXdZ6TtHQ3UzZzt4pU5NoXa +BgE+4XKewW90GoCW66yQpg80OD0UUl5JNT/GM2cVYqROEioFg+7/rEzhF1tv2JAe ++I2uxMJoMlA82giwLJ2qDqctDZsCgYEA2XpyRHVk3GZnQ/q9tK1VyVfUkFJh0FnQ +q7uzWysi3UCOzuJYauM300LhkP5gWsB0J3osBlreNMg9MTOIy1xi7tNXdOq07Hhr +4KsP8TkDhCmQDepx1V++qVBDTlAofCO5V530Ut1+wWDBlcycAz5MIy6j5TeAWrjm +s0sisOrk35UCgYEAlQyWcn6zht6kzNj2fjmv0ih0RATGPRDYS/vkQJ6Q7T5taspN +CdZsgy054vbt53216/vMfMZwHxseCl/EDNgOAexBPbrIU9xbYMpZ7w4c/CEBDI30 +7b847By1sJcdqZA1CECiln7mjHGzMWnZ0my4KIvfgx390EeWWOGQnqFGOFsCgYBs +OEZMUq6SDlMsvMVR9z9NJeuctaH+7/KqwoiJwXlj6BAoWvHsnozVD973K93+yu4C +BwWJVAZm9Y2dwis8JwkEFx7aC0FkurfT4MvaGajqR1Rr2FI0/6P81PfpLHI48/3y +36MI6Td+OwuZ42tvIbz5dOgR1ACHJKOIbMciioDB0QKBgCtqIx4aMteQEOvXlx8E +mmD5qNBhcWUgxexqdqrvyqLScGHuhuUHny4ytTzNMulG3S8DEC2ULrq64OZuIdyT +XkhQHb96BsPSpUioe5MLzr5EnDLLV8Hptf4mmJctkd0eczgvtlX9QyFp9LpeqAMQ +FA21NyLKatm942vrWMsBGrcS +-----END PRIVATE KEY----- +` + SelfSignedECDSACertificateNoDigitalSignatureKeyUsage = ` +-----BEGIN CERTIFICATE----- +MIICiTCCAi+gAwIBAgIJAKVi77tebfBPMAoGCCqGSM49BAMCMIGFMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ08xHzAdBgNVBAcMFkFwYWNoZSBUcmFmZmljIENvbnRy +b2wxFDASBgNVBAoMC1RyYWZmaWMgT3BzMRUwEwYDVQQLDAxVbml0IFRlc3Rpbmcx +GzAZBgNVBAMMEiouaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxNzM3MjNaFw0z +OTAzMDExNzM3MjNaMIGFMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ08xHzAdBgNV +BAcMFkFwYWNoZSBUcmFmZmljIENvbnRyb2wxFDASBgNVBAoMC1RyYWZmaWMgT3Bz +MRUwEwYDVQQLDAxVbml0IFRlc3RpbmcxGzAZBgNVBAMMEiouaW52YWxpZDIuaW52 +YWxpZDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIOpnfYOa2+Fxhxl996A5cvU +OUrpY1/oy6uUdBmgo0Rfal9lv5NiMRhgg7s++jr2yf8ls2zLIosNPShIVLJl9Sej +gYUwgYIwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4E +FgQUcjdTM122v7VK7gWXexBLg+1fCu0wHwYDVR0jBBgwFoAUcjdTM122v7VK7gWX +exBLg+1fCu0wHQYDVR0RBBYwFIISKi5pbnZhbGlkMi5pbnZhbGlkMAoGCCqGSM49 +BAMCA0gAMEUCIDybXtWSTIeyETgLBGitveWAYh8dmBK/Wt3+Jdj/5GF6AiEA95I8 +96/cXDmduClIg4CnYLGbkDPsC+3nENEIr92WqgE= +-----END CERTIFICATE----- +` + SelfSignedECDSAPrivateKeyNoDigitalSignatureKeyUsage = ` +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPrjdSmSp6D/M6KBOwwz7u/NzO70nBT0U74QSCBWmwAOoAoGCCqGSM49 +AwEHoUQDQgAEg6md9g5rb4XGHGX33oDly9Q5SuljX+jLq5R0GaCjRF9qX2W/k2Ix +GGCDuz76OvbJ/yWzbMsiiw09KEhUsmX1Jw== +-----END EC PRIVATE KEY----- +` + SelfSignedECDSACertificate = ` +-----BEGIN CERTIFICATE----- +MIIC/jCCAqSgAwIBAgIUXHzSgl46W/BuBZ+Vf8qyBa/qVZwwCgYIKoZIzj0EAwIw +ga4xCzAJBgNVBAYTAlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVu +dmVyMRUwEwYDVQQKEwxDRE4taW4tYS1Cb3gxFTATBgNVBAsTDENETi1pbi1hLUJv +eDEkMCIGA1UEAxQbKi5lY2RzYXRlc3QubXljZG4uY2lhYi50ZXN0MScwJQYJKoZI +hvcNAQkBFhhuby1yZXBseUBpbmZyYS5jaWFiLnRlc3QwHhcNMTkwMzMwMTgyMTIx +WhcNMTkwNDI5MTgyMTIxWjCBrjELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9y +YWRvMQ8wDQYDVQQHEwZEZW52ZXIxFTATBgNVBAoTDENETi1pbi1hLUJveDEVMBMG +A1UECxMMQ0ROLWluLWEtQm94MSQwIgYDVQQDFBsqLmVjZHNhdGVzdC5teWNkbi5j +aWFiLnRlc3QxJzAlBgkqhkiG9w0BCQEWGG5vLXJlcGx5QGluZnJhLmNpYWIudGVz +dDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABB1UpeDr4LCoxdYwziBAWpNJGeUK +3ikfqHn9dFr/p9I3j24yo9lJcvjGB7LP0euKr0Qjnsgm1cq6xR2meFEfutGjgZ0w +gZowDAYDVR0TBAUwAwEB/zARBglghkgBhvhCAQEEBAMCBkAwDgYDVR0PAQH/BAQD +AgKEMCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAzAdBgNVHQ4EFgQU +ASswQL7PBDEAWVySy/6K3UBrP8owJgYDVR0RBB8wHYIbKi5lY2RzYXRlc3QubXlj +ZG4uY2lhYi50ZXN0MAoGCCqGSM49BAMCA0gAMEUCIFS0uTwkNybSS/m+DbkDAi0j +FueoHu2+4E9uF4iy6g9jAiEA5IQfSN4S4Oyr6fQkFZx7OrymvechwOXjHcxa7BmB +zo8= +-----END CERTIFICATE----- +` + SelfSignedECDSAPrivateKey = ` +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINVb8yaaCT14CVhYVaOv3fmGpEVuXvTclOQYIZq793svoAoGCCqGSM49 +AwEHoUQDQgAEHVSl4OvgsKjF1jDOIEBak0kZ5QreKR+oef10Wv+n0jePbjKj2Uly ++MYHss/R64qvRCOeyCbVyrrFHaZ4UR+60Q== +-----END EC PRIVATE KEY----- +` + SelfSignedECDSAPrivateKeyWithoutParams = ` +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINVb8yaaCT14CVhYVaOv3fmGpEVuXvTclOQYIZq793svoAoGCCqGSM49 +AwEHoUQDQgAEHVSl4OvgsKjF1jDOIEBak0kZ5QreKR+oef10Wv+n0jePbjKj2Uly ++MYHss/R64qvRCOeyCbVyrrFHaZ4UR+60Q== +-----END EC PRIVATE KEY----- +` + SelfSignedDSACertificate = ` -----BEGIN CERTIFICATE----- -MIIDkjCCAnoCCQCfwd219JKpUDANBgkqhkiG9w0BAQsFADCBijELMAkGA1UEBhMC -VVMxETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYDVQQHDAZEZW52ZXIxEDAOBgNVBAoM -B0NvbWNhc3QxDjAMBgNVBAsMBXZpcGVyMRUwEwYDVQQDDAx3d3cudGVzdC5vcmcx -HjAcBgkqhkiG9w0BCQEWD21pY2tleUB0ZXN0Lm9yZzAeFw0xNzExMTYxNjM5MTNa -Fw0yNzExMTQxNjM5MTNaMIGKMQswCQYDVQQGEwJVUzERMA8GA1UECAwIQ29sb3Jh -ZG8xDzANBgNVBAcMBkRlbnZlcjEQMA4GA1UECgwHQ29tY2FzdDEOMAwGA1UECwwF -dmlwZXIxFTATBgNVBAMMDHd3dy50ZXN0Lm9yZzEeMBwGCSqGSIb3DQEJARYPbWlj -a2V5QHRlc3Qub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6m6j -iAMJpLMxZhIUE9DrPvni06NebLRah1RS8+R3J3PN1XCcgwwUZifZBpPgaSapFXbv -ZdjlrfZFpkAfgFQXlyGae6BU+n4CwNlDdgo1XbEc8qoGIds7aYHEkrQZtZyh+XFY -2BRvS6cbGGEc2x0w5IkXa136WCJcLtBzdT7FAVQJVhu9xPPnXk8igTZg6tFt27Eb -ebHCUeDArGURFiFWdXm8dGCPUVCZxSCvxuXlI15ddgfp9GbFXxCUP5VR9Pj6Btqe -7QymFROsIklpCw46ea0A87ikVMadPC21TubfayUAMQ8xl60iox5Y89g4XFrEgkyd -WxhmPWrVpVQrPDWKgwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCZZW6rln/KbGVn -UZ+7DV9PUB4r25B9wrRALy8rQw3UAePHRqZiAOVNWxrr3967zdPMc8d1kYckt+cG -G1PU5BcbUVnS2qE0Tkfvqj6r+Oickru6tKfXDaqMOEtfNanwT9uDZCTeOaiSHBzx -FpP/9TD05gEYbd1W4RRzT6/S7yLY0uYhVAHFdl2e7zOjhty4iDPF04fd+XyZ+3WS -IxSgaMrTp00maFtbpPnhTaxIGzMYtodi6FaUcOmBfMlpRGKyksN0Z3eJ6R6nhMb3 -RGJ9nuGLKvqS5u9BggcDwo1qv2k8McdSg6plK6XodLyMdBVTB6K7hwSz1uVp3mX1 -HVGE4+ou +MIIF6TCCBY6gAwIBAgIUHRv+ycqq+/HTUnXc3uMefnW3qrowCwYJYIZIAWUDBAMC +MIGsMQswCQYDVQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRl +bnZlcjEVMBMGA1UEChMMQ0ROLWluLWEtQm94MRUwEwYDVQQLEwxDRE4taW4tYS1C +b3gxIjAgBgNVBAMUGSouZHNhdGVzdC5teWNkbi5jaWFiLnRlc3QxJzAlBgkqhkiG +9w0BCQEWGG5vLXJlcGx5QGluZnJhLmNpYWIudGVzdDAeFw0xOTAzMzAwNDUxMzha +Fw0xOTA0MjkwNDUxMzhaMIGsMQswCQYDVQQGEwJVUzERMA8GA1UECBMIQ29sb3Jh +ZG8xDzANBgNVBAcTBkRlbnZlcjEVMBMGA1UEChMMQ0ROLWluLWEtQm94MRUwEwYD +VQQLEwxDRE4taW4tYS1Cb3gxIjAgBgNVBAMUGSouZHNhdGVzdC5teWNkbi5jaWFi +LnRlc3QxJzAlBgkqhkiG9w0BCQEWGG5vLXJlcGx5QGluZnJhLmNpYWIudGVzdDCC +A0YwggI5BgcqhkjOOAQBMIICLAKCAQEAkypAr0SzwNcEKDm2kiAx7joazQBU1thr +8eIUZAiMpSnpUH6svCPUilYjqhQVIR2F5Pekh/NcnuGGHkZyCKGbS9xKZnndZ2V4 +TA3HDyvTBv8jnfSfah7QYD77E5ju9A050KVxTZpYhNfboRv0PWg1x/WCzqWtYWPP +s7DFEBPhKZcMRTmnELwbM94pPIyFEEDJLL50k1sqbK35mOc+APDioly1EyUGXj/8 +qsCnFDv8EKH6UG5bO9Q1fGEPTqgCcQKWFrbdc6UYZKu+gScMEyax4YktirTEeX46 +o3VnGKXUwslEZhj+HdAnhJzKOUs3xdwzqVjZ4xxh6oY3oEuxarcXmwIhAMYi2lmV ++b4aP6cuzi3dHEKzm/Z70yQi5F+w5S/g2IvxAoIBAEUB1+oPc59wsNjx7NhmlxXx +IR5Hya+6KHlOP/lK1/s/kcCzDvf7uAMFepgKL2geA1y36fllGPL9wImFh9uZprtK +WA1n6Xt1bTsrfoEdrYhYyo5zSliGVuiZ6VLA3egb8WAoyGe8js8Qd+NWkJrjoQfn +QymLv2Q9rFYpzc73OVMuNJfYmbkCOwqx4NxXuR41tV4o4WFpp+2h4VtES69FdT/y +GAFgYm62qnqgjTvR6/8Pi0mjjps6RBlK6NucKwbd2E3wI/2lIfImEaRANMhbpUaa +grrqTsDBsxRykKS1UdjyZniV4TOV4Xjdc0RF8w9JbvRyKbA+KAgv9p4qGxexrDcD +ggEFAAKCAQA8/GqhpKc6AX1ssmo1EQcMWQo+od7LbVEXYRwi/L6BU3CPUIHSz4bw +AtzlwDvSLI8Tbp1Qzs2VBkcT4KbOiIRw4xAsuW+hHBJast2cA7grCP2c0aTe81FU +Kz7KMoH4Xu/cYgd9TOCvLUT5fqJzjI8Sk5z/eJ0q/3kO57GDNgLi/WHFY9Abn7yb +6MpkNc53mi6glMRc0D0d/W5MrSIrq/w+7lwM685pQ9TbPR0Xoimm4rur4/w92P9Z +ydMp9uDeijwl+qFiUBzne66IWx5GH88FQtuWL4cDuyfxRPs4E2vC3pk37zi1b6qJ +1pmcYSbUKMbENbqLuW9jfNdisVUQByPQo4GbMIGYMAwGA1UdEwQFMAMBAf8wEQYJ +YIZIAYb4QgEBBAQDAgZAMA4GA1UdDwEB/wQEAwIChDAgBgNVHSUBAf8EFjAUBggr +BgEFBQcDAQYIKwYBBQUHAwMwHQYDVR0OBBYEFJ5U5dSqX0eUO8VuLqSYRtvQbMs/ +MCQGA1UdEQQdMBuCGSouZHNhdGVzdC5teWNkbi5jaWFiLnRlc3QwCwYJYIZIAWUD +BAMCA0gAMEUCIBCA3RYYn4DK/nzKK4cTbtmj6V72Ywoh6YJ3taZ18iYIAiEAxV5u +qL6kmx7XWFAhA3NKMW79Cz6hmhDo0ZFPf1G258Q= -----END CERTIFICATE----- ` - GoodTLSKeys = ` + SelfSignedDSAPrivateKey = ` +-----BEGIN DSA PARAMETERS----- +MIICLAKCAQEAkypAr0SzwNcEKDm2kiAx7joazQBU1thr8eIUZAiMpSnpUH6svCPU +ilYjqhQVIR2F5Pekh/NcnuGGHkZyCKGbS9xKZnndZ2V4TA3HDyvTBv8jnfSfah7Q +YD77E5ju9A050KVxTZpYhNfboRv0PWg1x/WCzqWtYWPPs7DFEBPhKZcMRTmnELwb +M94pPIyFEEDJLL50k1sqbK35mOc+APDioly1EyUGXj/8qsCnFDv8EKH6UG5bO9Q1 +fGEPTqgCcQKWFrbdc6UYZKu+gScMEyax4YktirTEeX46o3VnGKXUwslEZhj+HdAn +hJzKOUs3xdwzqVjZ4xxh6oY3oEuxarcXmwIhAMYi2lmV+b4aP6cuzi3dHEKzm/Z7 +0yQi5F+w5S/g2IvxAoIBAEUB1+oPc59wsNjx7NhmlxXxIR5Hya+6KHlOP/lK1/s/ +kcCzDvf7uAMFepgKL2geA1y36fllGPL9wImFh9uZprtKWA1n6Xt1bTsrfoEdrYhY +yo5zSliGVuiZ6VLA3egb8WAoyGe8js8Qd+NWkJrjoQfnQymLv2Q9rFYpzc73OVMu +NJfYmbkCOwqx4NxXuR41tV4o4WFpp+2h4VtES69FdT/yGAFgYm62qnqgjTvR6/8P +i0mjjps6RBlK6NucKwbd2E3wI/2lIfImEaRANMhbpUaagrrqTsDBsxRykKS1Udjy +ZniV4TOV4Xjdc0RF8w9JbvRyKbA+KAgv9p4qGxexrDc= +-----END DSA PARAMETERS----- +-----BEGIN DSA PRIVATE KEY----- +MIIDVQIBAAKCAQEAkypAr0SzwNcEKDm2kiAx7joazQBU1thr8eIUZAiMpSnpUH6s +vCPUilYjqhQVIR2F5Pekh/NcnuGGHkZyCKGbS9xKZnndZ2V4TA3HDyvTBv8jnfSf +ah7QYD77E5ju9A050KVxTZpYhNfboRv0PWg1x/WCzqWtYWPPs7DFEBPhKZcMRTmn +ELwbM94pPIyFEEDJLL50k1sqbK35mOc+APDioly1EyUGXj/8qsCnFDv8EKH6UG5b +O9Q1fGEPTqgCcQKWFrbdc6UYZKu+gScMEyax4YktirTEeX46o3VnGKXUwslEZhj+ +HdAnhJzKOUs3xdwzqVjZ4xxh6oY3oEuxarcXmwIhAMYi2lmV+b4aP6cuzi3dHEKz +m/Z70yQi5F+w5S/g2IvxAoIBAEUB1+oPc59wsNjx7NhmlxXxIR5Hya+6KHlOP/lK +1/s/kcCzDvf7uAMFepgKL2geA1y36fllGPL9wImFh9uZprtKWA1n6Xt1bTsrfoEd +rYhYyo5zSliGVuiZ6VLA3egb8WAoyGe8js8Qd+NWkJrjoQfnQymLv2Q9rFYpzc73 +OVMuNJfYmbkCOwqx4NxXuR41tV4o4WFpp+2h4VtES69FdT/yGAFgYm62qnqgjTvR +6/8Pi0mjjps6RBlK6NucKwbd2E3wI/2lIfImEaRANMhbpUaagrrqTsDBsxRykKS1 +UdjyZniV4TOV4Xjdc0RF8w9JbvRyKbA+KAgv9p4qGxexrDcCggEAPPxqoaSnOgF9 +bLJqNREHDFkKPqHey21RF2EcIvy+gVNwj1CB0s+G8ALc5cA70iyPE26dUM7NlQZH +E+CmzoiEcOMQLLlvoRwSWrLdnAO4Kwj9nNGk3vNRVCs+yjKB+F7v3GIHfUzgry1E ++X6ic4yPEpOc/3idKv95DuexgzYC4v1hxWPQG5+8m+jKZDXOd5ouoJTEXNA9Hf1u +TK0iK6v8Pu5cDOvOaUPU2z0dF6IppuK7q+P8Pdj/WcnTKfbg3oo8JfqhYlAc53uu +iFseRh/PBULbli+HA7sn8UT7OBNrwt6ZN+84tW+qidaZnGEm1CjGxDW6i7lvY3zX +YrFVEAcj0AIgQGLEWrKD5SwnFfhG5QNOjFO6RN/bNB8SanXrnzDUnkE= +-----END DSA PRIVATE KEY----- +` + SelfSignedX509v1Certificate = ` -----BEGIN CERTIFICATE----- -MIIF3DCCA8SgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYwxCzAJBgNVBAYTAlVT -MREwDwYDVQQIDAhDb2xvcmFkbzEkMCIGA1UECgwbSXBjZG4gQ2VydGlmaWNhdGUg -QXV0aG9yaXR5MSQwIgYDVQQLDBtJcGNkbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkx -HjAcBgNVBAMMFUlwY2RuIEludGVybWVkaWF0ZSBDQTAeFw0xNzExMTYyMDUwMTla -Fw0yNjAyMDIyMDUwMTlaMHAxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFk -bzEPMA0GA1UEBwwGRGVudmVyMQ8wDQYDVQQKDAZJcGNkbiAxEjAQBgNVBAsMCUlw -Y2RuIGRldjEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIIBIjANBgkqhkiG9w0B -AQEFAAOCAQ8AMIIBCgKCAQEA1h9fXwJ17QYNMXM5jEgHecVxWm+CNPQbi2O0aLm5 -laEuoctl/xnclDgkOcV50sIgURSnaRXHCMa93zb95xQefTIvRF/1kU9e68mmFjz8 -frAdOaM90TdUf1yv26W37nT9Dx26CAiSwALXVdx+4oPorNHv20x3qPbs+3cDunAf -/XVZ+6txn9Vsg00odHZofqZbmGTvG/ybQcGPjRPaWYHaLafjpDB3wPsDDu0L0bXT -HNQ8VWzKwk8UQtzgtKxXAE2ZwLSdQWsWEKHFFNkaOqwfq21UYvct4q2rq91tDnba -fqMjNNsqVkXdR24WcP8mgV1csVNLuZhmQaBNZ6w+hGitiQIDAQABo4IBYTCCAV0w -CQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9w -ZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUiZeZ -5UmwFF1VCgpwXf3g+q1FS6MwgcMGA1UdIwSBuzCBuIAUIV7iqt3+xYa1Fx/nYzxd -1hxvNw2hgZukgZgwgZUxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEP -MA0GA1UEBwwGRGVudmVyMSQwIgYDVQQKDBtJcGNkbiBDZXJ0aWZpY2F0ZSBBdXRo -b3JpdHkxJDAiBgNVBAsMG0lwY2RuIENlcnRpZmljYXRlIGF1dGhvcml0eTEWMBQG -A1UEAwwNSXBjZG4gUm9vdCBDQYICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQM -MAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQBHX+YmO6TLbMTZByuwrgiH -uy7rPzpXTXSJvUM+upxSenrmz8H5fBzypLfKE1NOK58Rr25OyAd1IqgG1Id+8ycg -atetjI1poaNCZvKPRr48wjcTVsfgx7HXW0fykI0KT239Ok4usEM3uqmbkn7Annf7 -dby8BKz4p9n1ye7eHpipu1A5WxjBQeDymlPw/CM9E0v5F/hgiWxW+e8l5u7h43bP -1BNO6PJXJ/GONiQh4bcL0R763tNIKGVNYHSffW71vyoY6reXdKBNnk91OgjFwHTN -ALJtr9jy5xy9vKATY7gThVWDhW/uiv8LUICxxZWnCucKvhgB2bLWaHxIOr9YyjaX -hEVdHgTVXPl5cMXBw+UZLn3vw5EQHuMFAIWR2ZNIhrEvjaPon5qaEveQCDsda39w -rTr3lheyBGMhTnmA4wNV+lNSLImAc2o78aete0cTsJ619snGODUo9QO2YZ/k7vPS -mHeK0VrZvnE8uklFJUTDayLoD+SnsxztRITvk/EuRay2P1fG1/qZn7QUIg+ZM4aV -S8vPrfI9rwu8CRgxmTTtX5ZMez89fy6FlVDITjVNhRrVIc2m3xL03ASTb6NankJo -En+MLQpCFVKyQy9N72RZNz68KiPH/fraAdq4mL5NAcR4P/6Gg7Sn+qjnf/4l43zZ -+7uzqjwhdtU/YHJ9j8/cow== +MIID6TCCAtECFCs7N+H5AQ4SN7lVyK+bHTrKgwOGMA0GCSqGSIb3DQEBCwUAMIGw +MQswCQYDVQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRlbnZl +cjEVMBMGA1UEChMMQ0ROLWluLWEtQm94MRUwEwYDVQQLEwxDRE4taW4tYS1Cb3gx +JjAkBgNVBAMUHSoueDUwOXYxLXRlc3QubXljZG4uY2lhYi50ZXN0MScwJQYJKoZI +hvcNAQkBFhhuby1yZXBseUBpbmZyYS5jaWFiLnRlc3QwHhcNMTkwMzMxMDM1MDU4 +WhcNMTkwNDMwMDM1MDU4WjCBsDELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9y +YWRvMQ8wDQYDVQQHEwZEZW52ZXIxFTATBgNVBAoTDENETi1pbi1hLUJveDEVMBMG +A1UECxMMQ0ROLWluLWEtQm94MSYwJAYDVQQDFB0qLng1MDl2MS10ZXN0Lm15Y2Ru +LmNpYWIudGVzdDEnMCUGCSqGSIb3DQEJARYYbm8tcmVwbHlAaW5mcmEuY2lhYi50 +ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzXMtRmZ4SVYpO4yf +00kKJD7MKCVzjTOKJNiOyJn++RYNX64gZU7a8LRefvruv6wO1Ic4IR7xvZ58t/sg +He6AoHW3Uz9XJ4knZ1BHNFHYsaELSDUkPNRowQprzJmAf3yDrn6kWrLVgX0iWrQh +T5UJxgS7L1iNibqAKFGkr0tRMk0rwjBzm5CGGyt1WS/J1W3h/R05BaDXukSCoSlo +cx1XgmldCQE27de+WXusITZse5h+Giei/hGkHdJJr1aROP3y+czeOF1YOr24p/0T +HPrir0iesWV2+bA/Tdj5hVWipt1OJBwOvfull9fZTvC1RRdhIyUJauWr4iwD2gpn +UI8OywIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBaEUQcKbLhlcyEE0OfcKTmHdwl +uhUpE55FkVJP9TN5nNAziYW+KRWiSyRdn/35s5Z+bFplbzT7Au5tZw6kTtkmtim3 +i6v7nNLES0hnj+zRybut4yEw9Ma0p/exiT0+qqVynBdgtpVwOcYIvgYlGgVUttNN +b/nKxOXZ9qDkqBDgMbXmYHCI5txFnqblLP8dW0CeFYIL0RuBx2qS5edYw8oTZPOL +b/CpL85+xi6pd+bOQ3UXbTaa78HEwcP1nX3IKzuMjtxUmZ5d2Gbo6TihuXiWCJHW +i/LiVIfp1/TNdiOvLRXYZV5itIKpgmr8nYCX8QRUewtP9Ex4RRcoEKQdVRpI -----END CERTIFICATE----- +` + SelfSignedX509v1PrivateKey = ` +- +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNcy1GZnhJVik7 +jJ/TSQokPswoJXONM4ok2I7Imf75Fg1friBlTtrwtF5++u6/rA7UhzghHvG9nny3 ++yAd7oCgdbdTP1cniSdnUEc0UdixoQtINSQ81GjBCmvMmYB/fIOufqRastWBfSJa +tCFPlQnGBLsvWI2JuoAoUaSvS1EyTSvCMHObkIYbK3VZL8nVbeH9HTkFoNe6RIKh +KWhzHVeCaV0JATbt175Ze6whNmx7mH4aJ6L+EaQd0kmvVpE4/fL5zN44XVg6vbin +/RMc+uKvSJ6xZXb5sD9N2PmFVaKm3U4kHA69+6WX19lO8LVFF2EjJQlq5aviLAPa +CmdQjw7LAgMBAAECggEAQUsFbIZMXCJB4GcEtEVWL8a1Y1zjqFBk6ujYF/C5E7hq +b6oLKacx9aWdEoX1Mn0gCXMf54bKFRU1VdM9lcWio1xF8vMCY9I276KXvoz0bR9d +UolxBtQKpq8FK3TtXZbY0q/0085aBFkcfe8ZVw1qmcAPLTDbapYW/LlVuVAacf16 +Ism+oVlpGosrG8pVe2nkxRLkA+FBsFNeliX8YucgvOcQWMjcJ1VPYgfA/7b8q4b7 +cVxfs7l+SrtMMYNNOM695b3AEW2Tve5JwNGEvaOJsHqS+VNHZ9T4NAr+ZAU6C237 +rM6dfPMqb/177Yvz32Bq6vbYVoeb2iDnMVbjgRQvYQKBgQD8nkXLguq+MkkhhW4c +xPYIHxZBQ948fFn1O2JKgmDR5bjQPbbXA/0Ko/l/yJ0ikNKeLC0/wXvUcQiuurIh +gFGgOU9uzaXgThZUsv35S9fiTuT4VamcQKOA42LTbxCk9O80fz4qR/mkMFz1KtoD +4cghfFRG/ZWpZ8ESSHOz8jzmJwKBgQDQM0HoBXkPZURj90jpg+oO4SD2ZTeAIfpM +YiHxI/jNV8Np8DLDne0a9ncsG1cCmPekVoEV5kliekak4H211CgWIERVOOSJumH5 +VHuqLK2BoUiEiMpAKQrG3Bc7MNK1BY8G4MUu//Sj508WJzyU1OBOHRVzc6fJ0bmK +o8EFYBg8vQKBgCufVSQYflrLqi88sFANfwLWA2zPwG+ndY1QbN+69ecpCSoEji9B +BBAzUqFLTj8qzQP9Uu8AhVahEkPB/4KjevT1EI9suakrMtX7drn269erkgSEHl7a +FqHqIiWqtzAVD717/4sjlKtSoqq/dJhZA8ssgg0kOxTe0stKcZhwSy3fAoGBAMxs +R53lIcR4DfqJZtHBcCND8PV81E2/Dt/IysLWKwiTz49JBM8FVTVQIhrwjTJDt4No +XD6AajWDEbH5qfTKZsGy1OVIgzyoAGKrDPE+BO5uyaE4Hj15DtfKahT4DysmVhTO +xU0si6wTBZge1mDb05FfBRzixjBm9+KkfnUksSeRAoGAfVxTz3PDE3oigzh3uOtu +3vB0xiUVGLsw6ZN1MJj/tkx631ejPV512uwMMTiP36zvYRgzbtNsFolz+jnfsZjp +JebgC1b0m89GkINe4oO3WGhIi7hsGGFP+CvWwQnALLX0aT+05OEbfBgoVm0ywTCf ++AQpUpVQ/mLB6W1mx9AuMeY= +-----END PRIVATE KEY----- +` + CASignedRSACertificateChain = ` -----BEGIN CERTIFICATE----- -MIIGBTCCA+2gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZUxCzAJBgNVBAYTAlVT -MREwDwYDVQQIDAhDb2xvcmFkbzEPMA0GA1UEBwwGRGVudmVyMSQwIgYDVQQKDBtJ -cGNkbiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxJDAiBgNVBAsMG0lwY2RuIENlcnRp -ZmljYXRlIGF1dGhvcml0eTEWMBQGA1UEAwwNSXBjZG4gUm9vdCBDQTAeFw0xNzEx -MTYyMDM4MTVaFw0yNzExMTQyMDM4MTVaMIGMMQswCQYDVQQGEwJVUzERMA8GA1UE -CAwIQ29sb3JhZG8xJDAiBgNVBAoMG0lwY2RuIENlcnRpZmljYXRlIEF1dGhvcml0 -eTEkMCIGA1UECwwbSXBjZG4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR4wHAYDVQQD -DBVJcGNkbiBJbnRlcm1lZGlhdGUgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw -ggIKAoICAQDKkxQ9hdMtSwfNEBqGPAKzu7CPhH+xu3kL4e+rJ09EB++fxG905mwM -Ym8s1GC/i1V1hPbOk+zLWXccZhtC49BttsDBVRmagt4q6eeD12AxzVBozWj4YnFy -ZE04CiZlAIN3qN4TnNT/O3iyvmj58QDIFVO51YNSrr7j2dQRLpoyS6s87kpw9A6T -24L1pLkmFuAgCLMFPG5HZWyZSStpXOzOc7LITZQXQzunwLazN9Z4Az8zYC9ilO6V -tNNNc+Y7MpFrTaEFFSsM2+REexuPtCOtT/ZEcOwP884T6ACcUSTv86iE/EFOPgZh -vTK2D0Nzat3ZTsc5N2vvN0eZm6COnVAvYNwrTWG4v3YUtLr/PEoFm9mtPdSA+Tsi -LkGFRjwAoAnhVieFAFulQnswbZAaJRc/xS7BJvts/3J9i7l1opqu0Ebm6L8jLeHv -p/op1TD8LIQkcp7GdsXk4LYH6VopaNOi8yoaEfKWwrXhxBdChHHlYCcfecyD8O39 -8euoGQ0zi/eaCr3MHYU1+a2+5TRPdzHx/l/3V1wxX9hmOGcrwTCtcYRzRjza2UlE -UacmwBqGyfa1Gn/iOto9yqtRvWlPGq9zJNQzNBJ6iWR7gyb0t820jpdtmFyNB5Pv -JceHyVyix/7sBUB5GwMO0iGnLPpY9Ix87nYP3itN3jkqahTrT7tHuwIDAQABo2Yw -ZDAdBgNVHQ4EFgQUIV7iqt3+xYa1Fx/nYzxd1hxvNw0wHwYDVR0jBBgwFoAUWcdI -BR6t3N8w7yUt/TOfXwmubAgwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E -BAMCAYYwDQYJKoZIhvcNAQELBQADggIBAKbd8nKA1hlxCTczTg9PHSdqHVEYWqRD -dzroOnz0KcIgJF4ncRaN3nna74wIm3nJD/WuwdF8dVbpD4YaeZKhQgmXmYggVH0l -8IIkdC3qYNTDj4xhg7qZC3pzKuNIg7yHv3Axr/rb9BvpUJxbKo/aln/G6PrbNoQx -4xb6xlK6WcYORB/UgzF6jKM5CBXaUt2QQmWts7MgnoNzZ4kxsYbuwj3rOPzHIgRY -YwJt+kh5tlyhHPkgjwUTbMg/Mv/omfzZ3+XMBD2Z69eNd9RHE9XS6AdMKtDiprhg -TLu+9tOVlydQjZk3KsqFv57/1TwKrt9JFjXk/PPQalXoP3oykoiviacd4MyiBmaW -i5WbtcxGP5vwaNn267OGlibfQmQgA1VIgDqftrQwe6T/ZwOKXqFqb56gqdW4VdOU -5bGN0uLXemriuNQolTpVmhNu0bNI5WCiY7c30XN2M5ebcBWDHOr4DOCg+mmX+tJT -Gi1jvfmA6LOYnyQ8xAV080uVe35NQ10e9my6LuXMiQ7ubvHUS5NwaQCFpLDIvbhf -2XVc46Nd0V/bolM23AQRlzuo0ISsDSeWSQVM+uQZ+pLe9G5n2MxqFd84Vu489auc -02I9cHiNahWyXPtvnvMWwImIB30CYhh5ByGWneDo3d5Zj2HAA6FwO67LlIhSe7qz -axDtcM4nO3QH +MIIE+zCCA+OgAwIBAgIFFVGJEGcwDQYJKoZIhvcNAQELBQAwga0xCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxJDAiBgNVBAMTG1Ry +YWZmaWMgT3BzIEludGVybWVkaWF0ZSBDQTEoMCYGCSqGSIb3DQEJARYZbm8tcmVw +bHlAaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxNjUxMTNaFw0zOTAzMDExNjUx +MTNaMGkxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEPMA0GA1UEBwwG +RGVudmVyMRQwEgYDVQQKDAtUcmFmZmljIE9wczEgMB4GA1UEAwwXKi50ZXN0Lmlu +dmFsaWQyLmludmFsaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDE +oCEYaEl1mrEOJy6jO8+QXXmlb8mYAWQL+lSOPYRvzuPWOvnfvW/BkDYpvzosfDZg +HNS106ROtWFe+kQZTTrm+xPTWMl/JIyn5ka1ZnJMAey0Oxyn2PgSmly++6esOiKH +CZm9Zhx2p7/d/fkYhu6G0X08SKVwZdtkerfKHqPEuEEcWm1H+IbMVweKDjiAqrEe +pcWKr/+i8NmOERCYvPFL6/Kf8/U4MrDM/3vh70DFKWZ3x5xWG7TWl3vCS4I+y/m7 +xEEQgF2vofcQO0CD09s4iRKCqbVM2vofWZVhYj63BgfbIXHYCFPyIpaTwc3u4fRW +pnWIUp9BFUy8PqXjh9vfAgMBAAGjggFjMIIBXzAJBgNVHRMEAjAAMBEGCWCGSAGG ++EIBAQQEAwIGQDAdBgNVHQ4EFgQU8RrF6qwRsTAtsdHUDUe//WnjNskwgdYGA1Ud +IwSBzjCBy4AUwVR9U/f9JDLi179Jc1qudzjYjhehgaukgagwgaUxCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxHDAaBgNVBAMTE1Ry +YWZmaWMgT3BzIFJvb3QgQ0ExKDAmBgkqhkiG9w0BCQEWGW5vLXJlcGx5QGludmFs +aWQyLmludmFsaWSCBRVRiRBmMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr +BgEFBQcDATAiBgNVHREEGzAZghcqLnRlc3QuaW52YWxpZDIuaW52YWxpZDANBgkq +hkiG9w0BAQsFAAOCAQEAbcOigHR11zFrPXHS7ZGG6Dro708QVrECofZJkVAKOUbZ +kWP2h4T+xSS6WEqk/1hKKo2RhiL7UlGwdtqNZ6lk9cwQORmeuIXEgy2BsbR5H4vy +L/2LhZzCSDYfeSbByhFdvLCNJMSGK+o49NUESD1zEJFPDDtMj/NLAgkLCSGi/8iF +VVJpJT3zP1I/C9Zmt8eFf6sjEdoIg6PPReJzu1hcEJLz/jqLuzoGasxea/k2k06k +Rj3GV8f3BZryN3+TKa7IiNsT7SGiZMiPWUvML/dp8aTgCNA/GlhGqzQPnDXBvgTN +JfDXiQDnR1svJZNHEfQDPIEeY6ECBAEaU0rgH9/iZg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIGEjCCA/qgAwIBAgIJAL2V1hnLWuzgMA0GCSqGSIb3DQEBCwUAMIGVMQswCQYD -VQQGEwJVUzERMA8GA1UECAwIQ29sb3JhZG8xDzANBgNVBAcMBkRlbnZlcjEkMCIG -A1UECgwbSXBjZG4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSQwIgYDVQQLDBtJcGNk -biBDZXJ0aWZpY2F0ZSBhdXRob3JpdHkxFjAUBgNVBAMMDUlwY2RuIFJvb3QgQ0Ew -HhcNMTcxMTE2MjAxOTI0WhcNMjcxMTE0MjAxOTI0WjCBlTELMAkGA1UEBhMCVVMx -ETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYDVQQHDAZEZW52ZXIxJDAiBgNVBAoMG0lw -Y2RuIENlcnRpZmljYXRlIEF1dGhvcml0eTEkMCIGA1UECwwbSXBjZG4gQ2VydGlm -aWNhdGUgYXV0aG9yaXR5MRYwFAYDVQQDDA1JcGNkbiBSb290IENBMIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2HsLknm9wx1V33zttMWn1sFEJyLNMeeW -hA0dweKChqDVw5lAyIid0lqjnjIEivlAM8zd2NAPZTHFG9BT3unduNcDcWuRgh33 -mlyssEharWtE6U7lzw8RMGWkyWQkJ2E0SxjE/VmKQjH3/4Ak8ShhTZFKEZuweRdg -j218qUemsOV+ENTsnGUxoAPpr5cGGo4igfO9tpI1g7PWnkYrVFtwsPoy2CKxqh/I -3F67EZq2yROBy9gBhC5FuZhuvgptvSakNQy/w+9buRffshb69wLsbqQayhjlLqcQ -Xkch4y6cG8Ylg+hrqzmG3vG4q03YFz8PuMd/uNxeJQAbZJ/sXh7jVQNJitgi6oOy -j1xVzNKUqb1Mx25DhBy125/l8wGBdsCRUYR6r70NAZRndjkQKV4l3tTQ4+o2rdjd -C/2Sk2/bHVbytMq4Iz+1sOsIUV3La+R+DWcLA6UonpEocNb8bt5bu4JhRDrnJwPi -4jRaH+KgxpBTIlZ3aFnSs0I3wkPOgA3DrI6LWxgt3BfPuK9DPma1rc4B1cwSQTNk -yyUY2boXsnLMMPebF3djwbtYEdqAaixxzzQCVYlhfCEQjqceSd6TJ2SdzH4I3J7x -OsLz1Lj/92aDeeq77q/c9FidnfNe75zB7gXN/bTtb55ZcTTO8XAEvegxcrw5CnO1 -MnFw6xDf++UCAwEAAaNjMGEwHQYDVR0OBBYEFFnHSAUerdzfMO8lLf0zn18JrmwI -MB8GA1UdIwQYMBaAFFnHSAUerdzfMO8lLf0zn18JrmwIMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQB+aYWZh+/gCmFy -oI582AC5+54c7xeLRmtQPmFpAA2Y4iTSeGyjv2g5M9agQ4Ixwue5DluQlsDcDsJw -lsXVHyAlCf6nDbJOpf5m6ixfvBF+QzEeXjUG74iSCWrApYFmsNsCrlsM/EPJogqu -7cgGvHwWYNjPzuwoU0AWHO9FgIbDz3Mc15ZlHIQ2T/ixxyBfpIPc5D91k4u/ZWSb -hO6lsM1iEAvv9ToUXkKttCQ0fN34BwYX47AxC71tSt9/VKIDIEXjzqJJpbJdBGSm -WuiZHWwBzVw7k5y+S+wM5vZ/OMw0thL+I53zmkxGEf3tMH4POeKvX/u19n0TFk/1 -96cztVmTB6W67mb9zZ8ySeJtD9uXE44ycxk93gTnarkIGdTf8XonCVlkHGpb6TWM -5E7aWCoVbqQRkF1rqPza8hRJGH1EGkmdbkuyUMLmQ1FJK9f/xFIcrdBGpMlxyOoL -MSeFeagoSLNq5xzjucF/6mkAUJ8UZAxrSGmaDEaSt1/qJRHovHct2b5FWZLuRt0g -fDsGoKT8IFuapSsmFEInvD0WKXDSPlU8rTy1ZBDlCqp3eNH4tCfLahk7vLA0Jbf7 -ULrtDnrNfjxUYFcF0RcauR1dlrQQRAs31QOzX+JOr4gUG7yXa3j64nx2G5MpLgSo -OEUjfakK71+V/HbQt477zR4k7cRbiA== +MIIEOTCCAyGgAwIBAgIFFVGJEGYwDQYJKoZIhvcNAQELBQAwgaUxCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxHDAaBgNVBAMTE1Ry +YWZmaWMgT3BzIFJvb3QgQ0ExKDAmBgkqhkiG9w0BCQEWGW5vLXJlcGx5QGludmFs +aWQyLmludmFsaWQwHhcNMTkwMzA2MTY1MTEwWhcNMzkwMzAxMTY1MTEwWjCBrTEL +MAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMQ8wDQYDVQQHEwZEZW52ZXIx +FDASBgNVBAoTC1RyYWZmaWMgT3BzMRQwEgYDVQQLEwtUcmFmZmljIE9wczEkMCIG +A1UEAxMbVHJhZmZpYyBPcHMgSW50ZXJtZWRpYXRlIENBMSgwJgYJKoZIhvcNAQkB +Fhluby1yZXBseUBpbnZhbGlkMi5pbnZhbGlkMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAsu3xVwphWUz/josArTjldncVgAZHVa+NVKgJpohoyJra7IgX +IpNY9dlMd4wydPc2/Y2yc6lcZ/XlfzWQS5hYsOqMoWsylC38ZeX9yminQ+Q0TFsz +EMK3v9aFV9kiFIKPh15wF1Iau1HMypN6e61rE8ThEixLU3gGLHhMvDuD+JIoIJzj +b9DvF0GU8kJr/ur4oJQDSnGiW4cg+IGsySH4y9e9NMZmwpnNprXVkP6Rr94UKAfB +KJDb683VeuuyyknwC6ZNmUYuSLIUxXi5UPbKQi20zwJkHbXui8aBMPvOIUKXSiCd +y5apfzZw22npUUbkarg6d26BU2hVjOd+6VyrqQIDAQABo2YwZDAdBgNVHQ4EFgQU +wVR9U/f9JDLi179Jc1qudzjYjhcwHwYDVR0jBBgwFoAUwYqnYixb6XZqbD7dpFMx +280Z+5YwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZI +hvcNAQELBQADggEBADiiT8vhjan43mJDv0kFS7xipePJeXbLGgAu3PocoR9qUbh+ +7Q2Zj5p1rCDaqUoUB8C5p1T3JjPxeGLQ3A9qjWP1FUhbsHTfJzcU989Q73Iomx3k +cmmQhWt+xvCpxGFmvjBpEyyIhCkgoGBUfHQFjcyrLWbaLRXOR1eF9B0YORbJmf10 +1lxg8PQ3LclCs9m4XSI2THiURDN4dFANRYqcWvg0ncej/SOXJQ+OZ5K1AJ9z/acB +GT/EpQ6YfSyxOsKVPAu3mrIxfOAqahKFJa4bgV+a5SmiENYEKYaWObAgMpO+Ud5F +kG5IVBDJicJm/kazyAs2f4NmW+8p8CKEdrB/6gI= -----END CERTIFICATE----- ` - rootCA = ` + CASignedRSACertificateChainPrivateKey = ` +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDEoCEYaEl1mrEO +Jy6jO8+QXXmlb8mYAWQL+lSOPYRvzuPWOvnfvW/BkDYpvzosfDZgHNS106ROtWFe ++kQZTTrm+xPTWMl/JIyn5ka1ZnJMAey0Oxyn2PgSmly++6esOiKHCZm9Zhx2p7/d +/fkYhu6G0X08SKVwZdtkerfKHqPEuEEcWm1H+IbMVweKDjiAqrEepcWKr/+i8NmO +ERCYvPFL6/Kf8/U4MrDM/3vh70DFKWZ3x5xWG7TWl3vCS4I+y/m7xEEQgF2vofcQ +O0CD09s4iRKCqbVM2vofWZVhYj63BgfbIXHYCFPyIpaTwc3u4fRWpnWIUp9BFUy8 +PqXjh9vfAgMBAAECggEARD43flsjs9eewATFYQ4vOjHXOJ4V39YLvUSC+GNNhejO +ltodQ5RiJ1JAGjkunaX20WDwSrNMAa1eQDKoVAfD+8sE1IOqW6B52QRJYkhOPycj +2mHxzie14e8FZZu+VD5RIYEphNzd4CjUpN2zCNo8CzrGNpgYI2yWuscE5ve/a1TT +/diQVMpnDQkOFbqAmGS70hAjcSJ1yW5nUSSXmjjlEkxOmWt4wqLUYTmrqcW5DKxv +jmxoRb1XdWzT+ryXOVX6ilvjlQVMi4k+ohvV6svFjkRiTdii16/YK9CbRaZvq8eU ++F53LF68Cv4YlX/5C4pcwyEf+I/UolDfyNE4NrY4kQKBgQDsvYpenMs80H14wd3r +O7QpaIvZe6u++nIa9Pa0n4gwsieBEHAhrvJvqln6h2mOuWL8I6cSERBVqqUD3F5w +HdNa8mStpIF+XlBmQW5UGZTqUk6KugJzIB6ZBXKOfW6g/+xaQmC0tFTzuvsV0pZ0 +X8EmsW9xbBe/+Y/zOgLXpsfgtQKBgQDUnyNz7Gaq2SldGEVMrI8eicfV8KcH0rK7 +ocUnESxL9zvNFkz9wz1t5/D4L/D3XuLAjXtKV1lUvbzVxHh46GQxvz0/5swYjL71 +rhEDqQF2t7PISxXFq9yMAg5iOxyLwBFGDcNsL6G5SdXpM/YWGo7wSwsWdYEzZULs +UZ/ZOQIqwwKBgQCfFh/NxH+utkwawexnDw/aY67Wzwxyocnb45GFf079qjpxuKIh +gHbaIxekCyscBehGl47FzUG0z59kIMo1fVVyYEDXjxyV1rsgfAev7CDt9bFh9+19 +f7AQFGEO76tP9arWXJSv2h7cSmJAH+uK+G3LmqDRD1pGX2YkhG80i5b1oQKBgQCo +GMypqJuetSObo0WekcpwxVNFVAZqC+0cpI+/DDeuM1+HC/uAoKvfSYFcZmKm39B7 +lR+FLbvFYGB7zOHGDUyxe9VLwQdY3WVXzO9MqoAqwJ+VWa9z4STzV+jRRpSR9B5z ++Quoa5v7ZmGFBnynCwY4+cthTTMBVCxtszaiQQzyiwKBgQDnJLZONi3IcsgGOuka +4qYVQl7sSIuBJ1gyZr44WjoUlykxLij59MEnAOolR86PWif6VgNfsJL4MqTkaX++ +PgH8k1z8wkIxUP94BXLfSHJyUriHMPX45T3Rr6uBrvtVujRNIHndGKDoa7P16Hzz +otCrxsW0tXSVJ1KfW1Cwb7jtHA== +-----END PRIVATE KEY----- +` + CASignedRSARootCA = ` -----BEGIN CERTIFICATE----- -MIIGEjCCA/qgAwIBAgIJAL2V1hnLWuzgMA0GCSqGSIb3DQEBCwUAMIGVMQswCQYD -VQQGEwJVUzERMA8GA1UECAwIQ29sb3JhZG8xDzANBgNVBAcMBkRlbnZlcjEkMCIG -A1UECgwbSXBjZG4gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSQwIgYDVQQLDBtJcGNk -biBDZXJ0aWZpY2F0ZSBhdXRob3JpdHkxFjAUBgNVBAMMDUlwY2RuIFJvb3QgQ0Ew -HhcNMTcxMTE2MjAxOTI0WhcNMjcxMTE0MjAxOTI0WjCBlTELMAkGA1UEBhMCVVMx -ETAPBgNVBAgMCENvbG9yYWRvMQ8wDQYDVQQHDAZEZW52ZXIxJDAiBgNVBAoMG0lw -Y2RuIENlcnRpZmljYXRlIEF1dGhvcml0eTEkMCIGA1UECwwbSXBjZG4gQ2VydGlm -aWNhdGUgYXV0aG9yaXR5MRYwFAYDVQQDDA1JcGNkbiBSb290IENBMIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA2HsLknm9wx1V33zttMWn1sFEJyLNMeeW -hA0dweKChqDVw5lAyIid0lqjnjIEivlAM8zd2NAPZTHFG9BT3unduNcDcWuRgh33 -mlyssEharWtE6U7lzw8RMGWkyWQkJ2E0SxjE/VmKQjH3/4Ak8ShhTZFKEZuweRdg -j218qUemsOV+ENTsnGUxoAPpr5cGGo4igfO9tpI1g7PWnkYrVFtwsPoy2CKxqh/I -3F67EZq2yROBy9gBhC5FuZhuvgptvSakNQy/w+9buRffshb69wLsbqQayhjlLqcQ -Xkch4y6cG8Ylg+hrqzmG3vG4q03YFz8PuMd/uNxeJQAbZJ/sXh7jVQNJitgi6oOy -j1xVzNKUqb1Mx25DhBy125/l8wGBdsCRUYR6r70NAZRndjkQKV4l3tTQ4+o2rdjd -C/2Sk2/bHVbytMq4Iz+1sOsIUV3La+R+DWcLA6UonpEocNb8bt5bu4JhRDrnJwPi -4jRaH+KgxpBTIlZ3aFnSs0I3wkPOgA3DrI6LWxgt3BfPuK9DPma1rc4B1cwSQTNk -yyUY2boXsnLMMPebF3djwbtYEdqAaixxzzQCVYlhfCEQjqceSd6TJ2SdzH4I3J7x -OsLz1Lj/92aDeeq77q/c9FidnfNe75zB7gXN/bTtb55ZcTTO8XAEvegxcrw5CnO1 -MnFw6xDf++UCAwEAAaNjMGEwHQYDVR0OBBYEFFnHSAUerdzfMO8lLf0zn18JrmwI -MB8GA1UdIwQYMBaAFFnHSAUerdzfMO8lLf0zn18JrmwIMA8GA1UdEwEB/wQFMAMB -Af8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQB+aYWZh+/gCmFy -oI582AC5+54c7xeLRmtQPmFpAA2Y4iTSeGyjv2g5M9agQ4Ixwue5DluQlsDcDsJw -lsXVHyAlCf6nDbJOpf5m6ixfvBF+QzEeXjUG74iSCWrApYFmsNsCrlsM/EPJogqu -7cgGvHwWYNjPzuwoU0AWHO9FgIbDz3Mc15ZlHIQ2T/ixxyBfpIPc5D91k4u/ZWSb -hO6lsM1iEAvv9ToUXkKttCQ0fN34BwYX47AxC71tSt9/VKIDIEXjzqJJpbJdBGSm -WuiZHWwBzVw7k5y+S+wM5vZ/OMw0thL+I53zmkxGEf3tMH4POeKvX/u19n0TFk/1 -96cztVmTB6W67mb9zZ8ySeJtD9uXE44ycxk93gTnarkIGdTf8XonCVlkHGpb6TWM -5E7aWCoVbqQRkF1rqPza8hRJGH1EGkmdbkuyUMLmQ1FJK9f/xFIcrdBGpMlxyOoL -MSeFeagoSLNq5xzjucF/6mkAUJ8UZAxrSGmaDEaSt1/qJRHovHct2b5FWZLuRt0g -fDsGoKT8IFuapSsmFEInvD0WKXDSPlU8rTy1ZBDlCqp3eNH4tCfLahk7vLA0Jbf7 -ULrtDnrNfjxUYFcF0RcauR1dlrQQRAs31QOzX+JOr4gUG7yXa3j64nx2G5MpLgSo -OEUjfakK71+V/HbQt477zR4k7cRbiA== +MIIENDCCAxygAwIBAgIJAKtfkOE64RynMA0GCSqGSIb3DQEBCwUAMIGlMQswCQYD +VQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRlbnZlcjEUMBIG +A1UEChMLVHJhZmZpYyBPcHMxFDASBgNVBAsTC1RyYWZmaWMgT3BzMRwwGgYDVQQD +ExNUcmFmZmljIE9wcyBSb290IENBMSgwJgYJKoZIhvcNAQkBFhluby1yZXBseUBp +bnZhbGlkMi5pbnZhbGlkMCAXDTE5MDMwNjE2NTEwN1oYDzIwNTkwMjI0MTY1MTA3 +WjCBpTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMQ8wDQYDVQQHEwZE +ZW52ZXIxFDASBgNVBAoTC1RyYWZmaWMgT3BzMRQwEgYDVQQLEwtUcmFmZmljIE9w +czEcMBoGA1UEAxMTVHJhZmZpYyBPcHMgUm9vdCBDQTEoMCYGCSqGSIb3DQEJARYZ +bm8tcmVwbHlAaW52YWxpZDIuaW52YWxpZDCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMi3d1btekZha72UWkdJvsuZenp8zNiQW7OaLLyZvLbvCncm6sNG +nZTVTkq5LZnrq2sOc04JIf7gFJc8vnJdBPEZEP5GRbWXmel4Q4qnoOcCr4/6UZ5I +1gG1JkGMsMWq83Zv/jqtjBSpIO9fQFEiv6h9jUAkzln7lfvpM892qCKZCFLh89TZ +5flSmwmNVOW5IFvUu9uFdKDBzOYaXpBXXhua3ewh9YqUtCfwBH/zz8bb3Shm9p55 +RhT0Rp4yQpFB4FwG0MxNNqjZ8BLuF9pleTcRlTrVwTLQ2sOq7HndvyyahxtSP3BF +plFrnnzmeOZjtr7RRPvG/22fHxb6lGxnXEkCAwEAAaNjMGEwHQYDVR0OBBYEFMGK +p2IsW+l2amw+3aRTMdvNGfuWMB8GA1UdIwQYMBaAFMGKp2IsW+l2amw+3aRTMdvN +GfuWMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgKEMA0GCSqGSIb3DQEB +CwUAA4IBAQCRtSa8H5mwNKT1SgSjEatLMLjzYk1jpfIns6hR2X5f+D/kZkpgPX/d +4dAke1DnMIyxE43t1RJJzoi1BhFg9YvEyNU5k5L7ECuYmgU5tbmeNx2cDu4Huy5k +6ZmQ4Amh01X3JY3MFARJyRi/+CvmT+SbwdKYs8fwhPbGcLRhlUC0tvFe6JfvceH/ +18TRlcDPC51+f+WidVkWC8Er7Mydv+bmNYqEgDEJ0UQWtI/j/hxYj1wuqvUaoN2A +GcDuf0HznG/JMOtoGmMELyxJlIHCBPG1h+myLON9/XuPHlhMQcIhmqNEBBGwSdwm +1Ybc3W8sUkBAEha1Nm4SGJOz2Lfk/rAZ -----END CERTIFICATE----- ` + CASignedNoSkiAkiRSACertificateChain = ` +-----BEGIN CERTIFICATE----- +MIID/zCCAuegAwIBAgIFFVGJhGIwDQYJKoZIhvcNAQELBQAwga0xCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxJDAiBgNVBAMTG1Ry +YWZmaWMgT3BzIEludGVybWVkaWF0ZSBDQTEoMCYGCSqGSIb3DQEJARYZbm8tcmVw +bHlAaW52YWxpZDIuaW52YWxpZDAeFw0xOTAzMDYxODU0MjVaFw0zOTAzMDExODU0 +MjVaMGkxCzAJBgNVBAYTAlVTMREwDwYDVQQIDAhDb2xvcmFkbzEPMA0GA1UEBwwG +RGVudmVyMRQwEgYDVQQKDAtUcmFmZmljIE9wczEgMB4GA1UEAwwXKi50ZXN0Lmlu +dmFsaWQyLmludmFsaWQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDS +Mski1L4DVQfYdwXBxBHAWD3ZdpoS+MZa3lJXPMecpNOQfZmFzI16l3oKaePK0t2a +2BmxPmueiQ4UD4n2x3Z4bV/sjz6W13ATZs+N3EZopkr5kjr5T4NxiHaWA2JCFBFF +aMhJwoX4g94pUuHKHm5iMr7mr6nJLKwXW1RrZ3hl8q3vBoo0DzyZ1lIo+s1MqMzG +G86Wdw49lNwgi4eCMBPnX+UOENij0Kl80KfoCsp9FOxbAtZIpP5cgmb8EQnmuaoV +wbetaz2sZ+S/qasSr1nlD9wuZ74dCTxnPzt+hguyhiSLra0sd48ie9QdCqSHyYAc +rmNtELNY3ytbEN2KG0xnAgMBAAGjaTBnMAkGA1UdEwQCMAAwEQYJYIZIAYb4QgEB +BAQDAgZAMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATAiBgNV +HREEGzAZghcqLnRlc3QuaW52YWxpZDIuaW52YWxpZDANBgkqhkiG9w0BAQsFAAOC +AQEAHkjRjqQSsLCJUQE6QNBcx5I+hle3InFiyvr5u2DAuL95GzA4LQbk1voYFj2h +fCgAE9ON2aViPjlqQcPYl+2Koyk0vkQwkSb8oJsEucAcAGk65BmlBVDbM9IgVC96 +ILYuk0kT+Y0CgvEWBftodYs8xKEAkNuopUTKZH1iPLIFghI3cxuU56G6A4XUFEbZ +Af5qM2UBxFnKPPm7HyKs7WPoud9/V4d7UaaspXwFdvA7f8bGJvgjHGYE8XBZONgQ +YJWLBgCfIKF0LqXAFwVrbbzJEshRT+WXCNvCCq5+AJK4gBaovzk7QkAREkwTe7Du +++NBiHeG0TrPN6tX7Ke7EUYcHg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID+TCCAuGgAwIBAgIFFVGJhGAwDQYJKoZIhvcNAQELBQAwgaUxCzAJBgNVBAYT +AlVTMREwDwYDVQQIEwhDb2xvcmFkbzEPMA0GA1UEBxMGRGVudmVyMRQwEgYDVQQK +EwtUcmFmZmljIE9wczEUMBIGA1UECxMLVHJhZmZpYyBPcHMxHDAaBgNVBAMTE1Ry +YWZmaWMgT3BzIFJvb3QgQ0ExKDAmBgkqhkiG9w0BCQEWGW5vLXJlcGx5QGludmFs +aWQyLmludmFsaWQwHhcNMTkwMzA2MTg1NDIyWhcNMzkwMzAxMTg1NDIyWjCBrTEL +MAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMQ8wDQYDVQQHEwZEZW52ZXIx +FDASBgNVBAoTC1RyYWZmaWMgT3BzMRQwEgYDVQQLEwtUcmFmZmljIE9wczEkMCIG +A1UEAxMbVHJhZmZpYyBPcHMgSW50ZXJtZWRpYXRlIENBMSgwJgYJKoZIhvcNAQkB +Fhluby1yZXBseUBpbnZhbGlkMi5pbnZhbGlkMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAtkDh9gusfqgvuTN/EYfiXS/JbnX34R9Kjau3JRqA+CttbY7i +5pYbb+xdVBiUSEO2hikIF9LbuCrEQUdwPbBdX5gratDcOquqwYj47uh9ii1UEsH+ +7Sa4aV2Tr1zOFLrdkuKdJIUk1Gwp6yfoLAsXDfmScIY61EMfEcau9zH/UlCNMbfT +UMYIkJJK8iPyFlS/EehhFuPd+0Mjd/qXPCBBD0bCcJLVka/mAjKyXZPJ6Vyh4/UD +5Ne+bVp7VatiWaiAf7wCF0pOr81yTdEYV7Sp53fXMUEuwACClV88YlET3eGwfSXd +j7ugKBnyDX3TlgOZix88qRhrJro+Zr9i4RMl8wIDAQABoyYwJDASBgNVHRMBAf8E +CDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIChDANBgkqhkiG9w0BAQsFAAOCAQEAWIM+ +R69UBhumUvzLsw2xXTPmHElzuM0w5BQMfJcvZ3gsdo0wvCXkKQPSu2yPBH0BuqRt +l29Ng3+ciuvRqk+wnDp8BH651U6U7oqSw2V7alOOy4ugPdQm7NNbJuOSYCCAngEh +ohEloW/4CGLyyY4ffNfoPySgl0xXL8B/QVuTuw/0IPK448ziUJ346sZf1oBQcM2y ++gHfbNp+jQM9lQeQhjv2TKFZKrfy6uS5hHQAlpo17e0oPZA+Yw6+hQ1n91CGZ/Xx +rWm+oBTAyZUuL0NgHBCwGzZMpqKk2hyevvOC3yWQsxhbh3Q92ucxx3ifQv+WsGu5 +e8Rwmr3/doh6voOnGQ== +-----END CERTIFICATE----- +` + CASignedNoSkiAkiRSAPrivateKey = ` +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSMski1L4DVQfY +dwXBxBHAWD3ZdpoS+MZa3lJXPMecpNOQfZmFzI16l3oKaePK0t2a2BmxPmueiQ4U +D4n2x3Z4bV/sjz6W13ATZs+N3EZopkr5kjr5T4NxiHaWA2JCFBFFaMhJwoX4g94p +UuHKHm5iMr7mr6nJLKwXW1RrZ3hl8q3vBoo0DzyZ1lIo+s1MqMzGG86Wdw49lNwg +i4eCMBPnX+UOENij0Kl80KfoCsp9FOxbAtZIpP5cgmb8EQnmuaoVwbetaz2sZ+S/ +qasSr1nlD9wuZ74dCTxnPzt+hguyhiSLra0sd48ie9QdCqSHyYAcrmNtELNY3ytb +EN2KG0xnAgMBAAECggEBAKyW3IXH7nin8bgwCj8OMZEgIzCSbHHVaHCmCS/uDOw2 +fiwupMayrRwSkjdIuKwJtcF1XKsm2JCkcjXQiHRjVIgPLmr7NuX94N1dVmBhlEJL +AFapVdjtC71F0jDceGpPNdsq7QF7QitKgzilABXIJNRmXE7nv14aWvcWm1tQ6w+w +1RkAEqmPcmEzGeOxWWMcaUFamEPI/SDGIDSYyeVW3qH2afqgm2B3WMU0A9hM2iDV +rTXYQpQCaTulSSCNYXCou+cOlvN+Jvf21OjxoZ0/UjGqeM42aCdyUU9K0Jc56Ps6 +RdW8rObTAYFQJj1wp9NB41QRh02HIBp7yhyyazJoXIkCgYEA8VbRqwNN7g3QmCp9 +gDxm/CQ+1tDFfbSteRnvcPwpQoLY8L+XOCws8VPP3IfKSwVU21CS+ji+0uk+x8nj +83iyFHK8K/ToAeijllftACcBgJDQOfRq9LrXwHBCIvTq4pwNoPiSVwtUotaZ5AQX +DMTOB9T6hnMu+YpaOtq84O2xHyMCgYEA3veuizIYnpi1QnTDB5zn08EWLWQYMjrq +K4SUqgL3Y81dls34bPHHAPqcK62pMRnK7qbgdJ7wjJiODC3ZZ7bjZHJFNFO7RzEA +ktFNCZ344CuX7vNR9NywathFA46mu/eCKWJLI/NrF1IclGG08ju+y8lrFm0UdxOe +9G228h30s+0CgYBHOCOvn84Djjgcb42RpkGN7vRMWFevfP4kWq76XK+gXRTAFwn9 +Haw1m1If9kKQWQZtoh19kfleLE7GjqGiW9/RgPpezmsZBRohZ9kczmX3FsUcFTDq +/6hjtb0Oq9AVB5BODIzC+ykC1OmdDEfxELLsRMGZo6wdH+L4s0xB5GL8mQKBgGMs +S6iCKc0xIz5h7PWP5tWbBqA96z08Uzf0CqPsGdl8WOpgxuS+TcOztI8A+UZrsIWi +GCgHIfuHR3dHVXH6OP5OjVWPALfTpeunyNpEN5SOD1ArTgLZvmZnt5qzcpocpvp9 +S+q7tKB0111wcClmRaEi/8zDy9yDD6qsujjK9jKpAoGAWQCY3cGmJD5tbt2FtHbb +hcAmRHPHGNps2rfW6JzQsLcb47Tp5iqt8aZYTtehnQyb7wyBdP68MGloenI6x3dQ +UjVsFHOBQq/cUVgoIlKcm9kmByjmGKcgWtPHi0lFT8u8kLvxf2NUiZyKDis+P2xq +0ojmGWKT22C4HUSsMTfq2Ew= +-----END PRIVATE KEY----- +` + CASignedNoSkiAkiRSARootCA = ` +-----BEGIN CERTIFICATE----- +MIID9DCCAtygAwIBAgIJAJSR9zIym8jSMA0GCSqGSIb3DQEBCwUAMIGlMQswCQYD +VQQGEwJVUzERMA8GA1UECBMIQ29sb3JhZG8xDzANBgNVBAcTBkRlbnZlcjEUMBIG +A1UEChMLVHJhZmZpYyBPcHMxFDASBgNVBAsTC1RyYWZmaWMgT3BzMRwwGgYDVQQD +ExNUcmFmZmljIE9wcyBSb290IENBMSgwJgYJKoZIhvcNAQkBFhluby1yZXBseUBp +bnZhbGlkMi5pbnZhbGlkMCAXDTE5MDMwNjE4NTQyMloYDzIwNTkwMjI0MTg1NDIy +WjCBpTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMQ8wDQYDVQQHEwZE +ZW52ZXIxFDASBgNVBAoTC1RyYWZmaWMgT3BzMRQwEgYDVQQLEwtUcmFmZmljIE9w +czEcMBoGA1UEAxMTVHJhZmZpYyBPcHMgUm9vdCBDQTEoMCYGCSqGSIb3DQEJARYZ +bm8tcmVwbHlAaW52YWxpZDIuaW52YWxpZDCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAKSMntoOnNIqxYKDAM7T3hLleGV/DXTkUbFdg3YuJFfYCmIg5MUP +XjmpdzXmvZAxGlKUb5Np7lZeY2xRt7DqK3vVbOmFLAryAgyglD5eTq8VESegUogt +pdI1ROhVYV3/aS1/jkfJWZjGfRim8NZ5RhisHRd0++oDmRUh0H0+e7zRbCNEPvDY +Vmw3JTaPwJz6ULgbOqHGofNwQFUJN4E0TBzt/qzC7r11aaQQag/j+TlPi0UTq46A +7pbm9kFD4kdEOQ3M6jAowyEAfei0Xq8jeHcf6eMeD+tki0AenXdrx7yTZqX5fwgc +wHUiwUZ2vZklescONvbbuW/WePA2uYKfYoECAwEAAaMjMCEwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAoQwDQYJKoZIhvcNAQELBQADggEBAAO2gylryjq2 +Ou+mm4E8On/Ecchci1FUlc8ZLAzxxTdtJDZQd4b6uEEOFnXyIDy1DU3CND3ieIa0 +EL12/dsGzzhI0mJEf+oes4aaa4l0znMA7WQ58CUdBWuGoGvUzLkE3TAFqLwKC79h +DARQQp0VaM01pZQd/Sh/3+V3ijEg3818VtTvKHm5t26ggIRhSSGMhEeqCoG+9EKL +igzzaBprKzbSuGpj9QKLO4P4vIvgt2RutfqYBNR6sdzKmQYyPCYshfsoQVWo9mmD +/LLpNoSwwXGgBhI7cprp0CsN5f5/mL2dDSQqEAOl8YitVa4nL44iFrL8d4d8OM7z +jI///X8MUJs= +-----END CERTIFICATE----- +` + CASignedECDSACertificateChain = `` + CASignedECDSACertificateChainPrivateKey = `` + CASignedECDSARootCA = `` + CASignedNoSkiAkiECDSACertificateChain = `` + CASignedNoSkiAkiECDSACertificateChainPrivateKey = `` + CASignedNoSkiAkiECDSARootCA = `` ) -func TestVerifyAndEncodeCertificate(t *testing.T) { +func TestDecodePrivateKeyPKCS8RSA2048(t *testing.T) { + + privateKey, cleanPemPrivateKey, err := decodeRSAPrivateKey(PrivateKeyPKCS8RSA2048) + + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) + + if pBlock == nil { + t.Fatal("can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("remaining bytes after decode > 0. expected: 0") + } + + if privateKey == nil { + t.Fatal("RSA private key is nil. expect: not nil") + } +} + +func TestDecodePrivateKeyPKCS1RSA2048(t *testing.T) { + + privateKey, cleanPemPrivateKey, err := decodeRSAPrivateKey(PrivateKeyPKCS1RSA2048) + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) + + if pBlock == nil { + t.Fatal("can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("remaining bytes after decode > 0. expected: 0") + } + + if privateKey == nil { + t.Fatal("RSA private key is nil") + } +} + +func TestDecodePrivateKeyECDSANISTPrime256V1(t *testing.T) { + + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTPrime256V1) + + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + var pemData = []byte(cleanPemPrivateKey) + var parsedBlocks = make([]*pem.Block, 0) + + for len(pemData) > 0 { + var block *pem.Block = nil + + // Check for at least one END marker + if strings.Count(string(pemData), "\n-----END") == 0 { + break + } + + block, pemData = pem.Decode(pemData) + + if block == nil { + t.Fatal("can't decode cleaned ecdsa private-key/param pem block") + } + + parsedBlocks = append(parsedBlocks, block) + } + + expectedParsedBlocks := 2 + if len(parsedBlocks) != expectedParsedBlocks { + t.Fatalf("incorrect number of parsed pem blocks - expected:%d actual:%d", expectedParsedBlocks, len(parsedBlocks)) + } + + if privateKey == nil { + t.Fatal("ECDSA private key is nil") + } +} + +func TestDecodePrivateKeyECDSANISTPrime256V1WithoutParams(t *testing.T) { + + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTPrime256V1WithoutParams) + + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) + + if pBlock == nil { + t.Fatal("can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("remaining bytes after decode > 0. expected: 0") + } + + if privateKey == nil { + t.Fatal("ECDSA private key is nil") + } +} + +func TestDecodePrivateKeyECDSANISTSecP384R1(t *testing.T) { + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1) + + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + var pemData = []byte(cleanPemPrivateKey) + var parsedBlocks = make([]*pem.Block, 0) + + for len(pemData) > 0 { + var block *pem.Block = nil + + // Check for at least one END marker + if strings.Count(string(pemData), "\n-----END") == 0 { + break + } + + block, pemData = pem.Decode(pemData) + + if block == nil { + t.Fatal("can't decode cleaned ecdsa private-key/param pem block") + } + + parsedBlocks = append(parsedBlocks, block) + } + + expectedParsedBlocks := 2 + if len(parsedBlocks) != expectedParsedBlocks { + t.Fatalf("incorrect number of parsed pem blocks - expected:%d actual:%d", expectedParsedBlocks, len(parsedBlocks)) + } + + if privateKey == nil { + t.Fatal("ECDSA private key is nil") + } +} + +func TestDecodePrivateKeyECDSANISTSecP384R1WithoutParams(t *testing.T) { + privateKey, cleanPemPrivateKey, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1WithoutParams) + + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + pBlock, remain := pem.Decode([]byte(cleanPemPrivateKey)) + + if pBlock == nil { + t.Fatal("can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("remaining bytes after decode > 0. expected: 0") + } + + if privateKey == nil { + t.Fatal("ECDSA private key is nil") + } +} + +func TestDecodeRSAPrivateKeyBadData(t *testing.T) { + + // Expected to fail. + privateKey, _, err := decodeRSAPrivateKey(BadKeyData) + if err == nil && privateKey != nil { + t.Fatal("unexpected result: decoding of bad private key data should have returned an error") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestDecodeECDSAPrivateKeyBadData(t *testing.T) { + + // Expected to fail. + privateKey, _, err := decodeECDSAPrivateKey(BadKeyData) + if err == nil && privateKey != nil { + t.Fatal("unexpected result: decoding of bad private key data should have returned an error") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestDecodePrivateKeyRSAEncrypted(t *testing.T) { + + // Expected to fail on decode of encrypted pem rsa private key + privateKey, _, err := decodeRSAPrivateKey(PrivateKeyEncryptedRSA2048) + if err == nil && privateKey != nil { + t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestDecodePrivateKeyECDSAEncrypted(t *testing.T) { + + // Expected to fail on decode of encrypted pem ecdsa private key + privateKey, _, err := decodeECDSAPrivateKey(PrivateKeyECDSANISTSecP384R1Encrypted) + if err == nil && privateKey != nil { + t.Fatal("unexpected result: decoding of encrypted private key should have returned an error") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateBadData(t *testing.T) { // should fail bad base64 data - dat, _, err := verifyCertificate(BadData, "") + _, _, _, _, err := verifyCertKeyPair(BadCertData, BadKeyData, "", true) if err == nil { - t.Errorf("Unexpected result, there should have been a base64 decoding failure") + t.Fatalf("unexpected result: there should have been a base64 decoding failure") } +} + +func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairDSA(t *testing.T) { + // should fail due to x509 + DSA being unsupported + _, _, _, _, err := verifyCertKeyPair(SelfSignedDSACertificate, SelfSignedDSAPrivateKey, "", true) - // should fail, can't verify self signed cert against this rootCA - dat, _, err = verifyCertificate(SelfSignedCertOnly, rootCA) if err == nil { - t.Errorf("Unexpected result, a certificate verification error should have occured") + t.Fatalf("unexpected result: the DSA PKI algorithm is unsupported") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateSelfSignedX509v1(t *testing.T) { + // should successfully validate as x509v1 must remain supported + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedX509v1Certificate, SelfSignedX509v1PrivateKey, "", true) + + if err != nil { + t.Fatalf("unexpected result: the x509v1 cert/key pair is valid and should have passed validation") + } + + if !unknownAuth { + t.Fatalf("unexpected result: certificate verification should have detected signature of unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Fatal("unexpected result: can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") + } + + if len(certChain) == 0 { + t.Fatal("unexpected: certChain should not be empty") + } +} + +func TestVerifyAndEncodeCertificateSelfSignedNoSkiAkiCertKeyPair(t *testing.T) { + + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedNOSKIAKIRSACertificate, SelfSignedNOSKIAKIRSAPrivateKey, "", true) + + if err != nil { + t.Fatalf("unexpected result: a certificate verification error should have occured") + } + + if !unknownAuth { + t.Fatalf("unexpected result: certificate verification should have detected unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Fatal("unexpected result: can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") + } + + if len(certChain) == 0 { + t.Fatal("unexpected: certChain should not be empty") } +} + +func TestVerifyAndEncodeCertificateSelfSignedCertKeyPair(t *testing.T) { + + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(SelfSignedRSACertificate, SelfSignedRSAPrivateKey, "", true) - // should pass, unknown authority is just a warning not an error - dat, unknownAuth, err := verifyCertificate(GoodTLSKeys, "") if err != nil { - t.Errorf("Test failure: %s", err) + t.Fatalf("unexpected result, a certificate verification error should have occured") } + if !unknownAuth { - t.Errorf("Unexpected result, certificate verification should have detected unknown authority") + t.Fatalf("unexpected result, certificate verification should have detected unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Fatal("unexpected result: can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") + } + + if len(certChain) == 0 { + t.Fatal("unexpected: certchain should not empty") } +} + +func TestVerifyAndEncodeCertificateSelfSignedCertKeyPairMisMatchedPrivateKey(t *testing.T) { + + // Should fail on cert/private-key mismatch + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificate, PrivateKeyPKCS1RSA2048, "", true) + + if err == nil { + t.Fatalf("unexpected result: a certificate/key modulus mismatch error should have occurred") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateSelfSignedNoServerAuthExtKeyUsage(t *testing.T) { + + // Should fail due to not having the serverAuth extKeyUsage (x509v3 only) + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificateNoServerAuthExtKeyUsage, SelfSignedRSAPrivateKeyNoServerAuthExtKeyUsage, "", true) + + if err == nil { + t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the server auth extKeyUsage") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateSelfSignedRSANoKeyEnciphermentKeyUsage(t *testing.T) { + + // Should fail due to not having the keyEncipherment keyUsage (x509v3 only) + // keyUsage extension must include keyEncipherment if the PKI algorithm is RSA. + _, _, _, _, err := verifyCertKeyPair(SelfSignedRSACertificateNoKeyEnciphermentKeyUsage, SelfSignedRSAPrivateKeyNoKeyEnciphermentKeyUsage, "", true) + + if err == nil { + t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the keyEncipherment keyUsage (required for x509v3+RSA certificates)") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateCASignedCertKeyPair(t *testing.T) { + + // Should succeed, but with unknown authority warning. + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, "", true) - // should pass - dat, _, err = verifyCertificate(GoodTLSKeys, rootCA) if err != nil { - t.Errorf("Test failure: %s", err) + t.Fatalf("unexpected result: " + err.Error()) } - certs := strings.SplitAfter(dat, PemCertEndMarker) - length := len(certs) - 1 - if length != 3 { // rootCA now included in certChain - t.Errorf("Test failure: expected 2 certs from verifyCertificate(), got: %d ", length) + if !unknownAuth { + t.Fatalf("unexpected result, certificate verification should have detected unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Fatal("unexpected result: can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") + } + + if len(certChain) == 0 { + t.Fatal("unexpected: certchain should not empty") + } +} + +func TestVerifyAndEncodeCertificateCASignedCertKeyPairWithRootCA(t *testing.T) { + + // should succeed and be fully validated. + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedRSACertificateChain, CASignedRSACertificateChainPrivateKey, CASignedRSARootCA, true) + + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + if unknownAuth { + t.Fatalf("unexpected result: warning for unknown authority even though rootCA is in certChain") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Fatal("unexpected result: can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") + } + + if len(certChain) == 0 { + t.Fatal("unexpected: certchain should not empty") + } +} + +func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPair(t *testing.T) { + + // Should succeed, but with unknown authority warning. + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, "", true) + + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + if !unknownAuth { + t.Fatalf("unexpected result, certificate verification should have detected unknown authority") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Fatal("unexpected result: can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") + } + + if len(certChain) == 0 { + t.Fatal("unexpected: certchain should not empty") + } +} + +func TestVerifyAndEncodeCertificateCASignedNoSkiAkiCertKeyPairWithRootCA(t *testing.T) { + + // should succeed and be fully validated despite not having subject/authority key identifier(s). + certChain, certPrivateKey, unknownAuth, _, err := verifyCertKeyPair(CASignedNoSkiAkiRSACertificateChain, CASignedNoSkiAkiRSAPrivateKey, CASignedNoSkiAkiRSARootCA, true) + + if err != nil { + t.Fatalf("unexpected result: " + err.Error()) + } + + if unknownAuth { + t.Fatalf("unexpected result: warning for unknown authority even though rootCA is in certChain") + } + + // Decode the clean Private Key + pBlock, remain := pem.Decode([]byte(certPrivateKey)) + + if pBlock == nil { + t.Fatal("unexpected result: can't decode cleaned private key pem block") + } else if len(remain) > 0 { + t.Fatal("unexpected result: remaining bytes after decode > 0. expected: 0") + } + + if len(certChain) == 0 { + t.Fatal("unexpected: cert chain should not empty") + } +} + +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutDigitalSignatureKeyUsage(t *testing.T) { + // Should fail due to unsupported private/public key algorithm + // keyUsage must contain the digitalSignature usage if a DSA based PKI algorithm is indicated (unlike RSA). + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificateNoDigitalSignatureKeyUsage, SelfSignedECDSAPrivateKeyNoDigitalSignatureKeyUsage, "", true) + + if err == nil { + t.Fatalf("unexpected result: x509v3 certificate should have been rejected since it doesn't have the digitalSignature keyUsage (required for x509v3+ECDSA certificates)") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPair(t *testing.T) { + // Should be successful as the certificate and key are valid with proper keyUsage/extendedKeyUsage. + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "", true) + + if err != nil { + t.Fatalf("unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) + } +} + +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairECDisabled(t *testing.T) { + // Should be rejected as allowEC flag has been set to false + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKey, "", false) + + if err == nil { + t.Fatalf("unexpected result - ECDSA cert/key pair should have been rejected due to allowEC being false") + } else { + t.Logf("expected error message: %s", err.Error()) + } +} + +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairWithoutParams(t *testing.T) { + // Test result should be successful as the certificate and key are valid with proper keyUsage/extendedKeyUsage. + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, SelfSignedECDSAPrivateKeyWithoutParams, "", true) + + if err != nil { + t.Fatalf("unexpected result - valid ECDSA cert/key pair should have been validated: " + err.Error()) + } +} + +func TestVerifyAndEncodeCertificateECDSASelfSignedCertificateKeyPairMisMatchedPrivateKey(t *testing.T) { + // Should fail due to mismatched ECDSA cert/private key pair + _, _, _, _, err := verifyCertKeyPair(SelfSignedECDSACertificate, PrivateKeyECDSANISTPrime256V1, "", true) + + if err == nil { + t.Fatalf("unexpected Result: Mismatched ECDSA cert/key pair should have failed verification") + } else { + t.Logf("expected error message: %s", err.Error()) } }