github.com/Venafi/vcert/v5@v5.10.2/pkg/certificate/certificate_test.go (about)

     1  /*
     2   * Copyright 2018 Venafi, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *  http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package certificate
    18  
    19  import (
    20  	"crypto"
    21  	"crypto/rand"
    22  	"crypto/rsa"
    23  	"crypto/x509"
    24  	"crypto/x509/pkix"
    25  	"encoding/asn1"
    26  	"encoding/pem"
    27  	"math/big"
    28  	"net"
    29  	"os"
    30  	"reflect"
    31  	"strings"
    32  	"testing"
    33  	"time"
    34  
    35  	"github.com/Venafi/vcert/v5/pkg/util"
    36  )
    37  
    38  func getCertificateRequestForTest() *Request {
    39  	req := Request{}
    40  	req.Subject.CommonName = "vcert.test.vfidev.com"
    41  	req.Subject.Organization = []string{"Venafi, Inc."}
    42  	req.Subject.OrganizationalUnit = []string{"Engineering", "Automated Tests"}
    43  	req.Subject.Country = []string{"US"}
    44  	req.Subject.Locality = []string{"SLC"}
    45  	req.Subject.Province = []string{"Utah"}
    46  
    47  	host, _ := os.Hostname()
    48  	req.DNSNames = []string{host}
    49  
    50  	addrs, _ := net.InterfaceAddrs()
    51  	var ips []net.IP
    52  	for _, add := range addrs {
    53  		ip, _, _ := net.ParseCIDR(add.String())
    54  		v4 := ip.To4()
    55  		if v4 != nil && !v4.IsLoopback() {
    56  			ips = append(ips, ip)
    57  		}
    58  
    59  	}
    60  	req.IPAddresses = ips
    61  
    62  	req.ExtKeyUsages = *NewExtKeyUsageSlice("ServerAuth")
    63  
    64  	return &req
    65  }
    66  
    67  func generateTestCertificate() (*x509.Certificate, crypto.Signer, error) {
    68  	req := getCertificateRequestForTest()
    69  
    70  	priv, err := GenerateECDSAPrivateKey(EllipticCurveP384)
    71  	if err != nil {
    72  		return nil, nil, err
    73  	}
    74  
    75  	certBytes, err := generateSelfSigned(req, x509.KeyUsageKeyEncipherment|x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, priv)
    76  	if err != nil {
    77  		return nil, nil, err
    78  	}
    79  
    80  	cert, err := x509.ParseCertificate(certBytes)
    81  	if err != nil {
    82  		return nil, nil, err
    83  	}
    84  
    85  	return cert, priv, nil
    86  }
    87  
    88  func generateSelfSigned(request *Request, ku x509.KeyUsage, eku []x509.ExtKeyUsage, privateKey crypto.Signer) ([]byte, error) {
    89  	notBefore := time.Now()
    90  	limit := new(big.Int).Lsh(big.NewInt(1), 128)
    91  	serial, _ := rand.Int(rand.Reader, limit)
    92  
    93  	certRequest := x509.Certificate{
    94  		SerialNumber: serial,
    95  	}
    96  	certRequest.Subject = request.Subject
    97  	certRequest.DNSNames = request.DNSNames
    98  	certRequest.EmailAddresses = request.EmailAddresses
    99  	certRequest.IPAddresses = request.IPAddresses
   100  	certRequest.SignatureAlgorithm = request.SignatureAlgorithm
   101  	certRequest.ExtKeyUsage = eku
   102  	certRequest.NotBefore = notBefore.UTC()
   103  	if ku&x509.KeyUsageCertSign != x509.KeyUsageCertSign {
   104  		certRequest.NotAfter = certRequest.NotBefore.AddDate(0, 0, 90)
   105  		certRequest.IsCA = false
   106  	} else {
   107  		certRequest.NotAfter = certRequest.NotBefore.AddDate(0, 0, 180)
   108  		certRequest.IsCA = true
   109  	}
   110  	certRequest.BasicConstraintsValid = true
   111  
   112  	pub := publicKey(privateKey)
   113  
   114  	cert, err := x509.CreateCertificate(rand.Reader, &certRequest, &certRequest, pub, privateKey)
   115  	if err != nil {
   116  		cert = nil
   117  	}
   118  
   119  	return cert, err
   120  }
   121  
   122  func TestGenerateRSAPrivateKey(t *testing.T) {
   123  	priv, err := GenerateRSAPrivateKey(512)
   124  	if err != nil {
   125  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   126  	}
   127  
   128  	err = priv.Validate()
   129  	if err != nil {
   130  		t.Fatalf("Error validating RSA Private Key\nError: %s", err)
   131  	}
   132  }
   133  
   134  func TestGenerateECDSAPrivateKey(t *testing.T) {
   135  	ellipticCurves := []EllipticCurve{EllipticCurveP256, EllipticCurveP384, EllipticCurveP521}
   136  	for _, curve := range ellipticCurves {
   137  		_, err := GenerateECDSAPrivateKey(curve)
   138  		if err != nil {
   139  			t.Fatalf("Error generating ECDSA Private Key\nError: %s", err)
   140  		}
   141  	}
   142  }
   143  
   144  func TestGenerateCertificateRequestWithRSAKey(t *testing.T) {
   145  	req := getCertificateRequestForTest()
   146  	var err error
   147  	req.PrivateKey, err = GenerateRSAPrivateKey(512)
   148  	if err != nil {
   149  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   150  	}
   151  
   152  	err = req.GenerateCSR()
   153  	if err != nil {
   154  		t.Fatalf("Error generating Certificate Request\nError: %s", err)
   155  	}
   156  
   157  	pemBlock, _ := pem.Decode(req.GetCSR())
   158  	if pemBlock == nil {
   159  		t.Fatalf("Failed to decode CSR as PEM")
   160  	}
   161  
   162  	parsedReq, err := x509.ParseCertificateRequest(pemBlock.Bytes)
   163  	if err != nil {
   164  		t.Fatalf("Error parsing generated Certificate Request\nError: %s", err)
   165  	}
   166  
   167  	err = parsedReq.CheckSignature()
   168  	if err != nil {
   169  		t.Fatalf("Error checking signature of generated Certificate Request\nError: %s", err)
   170  	}
   171  
   172  	validateExtendedKeyUsage(t, parsedReq)
   173  }
   174  
   175  func TestGenerateCertificateRequestWithECDSAKey(t *testing.T) {
   176  	req := getCertificateRequestForTest()
   177  	var err error
   178  	req.PrivateKey, err = GenerateECDSAPrivateKey(EllipticCurveP521)
   179  	if err != nil {
   180  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   181  	}
   182  
   183  	err = req.GenerateCSR()
   184  	if err != nil {
   185  		t.Fatalf("Error generating Certificate Request\nError: %s", err)
   186  	}
   187  
   188  	pemBlock, _ := pem.Decode(req.GetCSR())
   189  	if pemBlock == nil {
   190  		t.Fatalf("Failed to decode CSR as PEM")
   191  	}
   192  
   193  	parsedReq, err := x509.ParseCertificateRequest(pemBlock.Bytes)
   194  	if err != nil {
   195  		t.Fatalf("Error parsing generated Certificate Request\nError: %s", err)
   196  	}
   197  
   198  	err = parsedReq.CheckSignature()
   199  	if err != nil {
   200  		t.Fatalf("Error checking signature of generated Certificate Request\nError: %s", err)
   201  	}
   202  }
   203  
   204  func TestGenerateCertificateRequestWithED25519Key(t *testing.T) {
   205  	req := getCertificateRequestForTest()
   206  	var err error
   207  	req.PrivateKey, err = GenerateED25519PrivateKey()
   208  	if err != nil {
   209  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   210  	}
   211  
   212  	err = req.GenerateCSR()
   213  	if err != nil {
   214  		t.Fatalf("Error generating Certificate Request\nError: %s", err)
   215  	}
   216  
   217  	pemBlock, _ := pem.Decode(req.GetCSR())
   218  	if pemBlock == nil {
   219  		t.Fatalf("Failed to decode CSR as PEM")
   220  	}
   221  
   222  	parsedReq, err := x509.ParseCertificateRequest(pemBlock.Bytes)
   223  	if err != nil {
   224  		t.Fatalf("Error parsing generated Certificate Request\nError: %s", err)
   225  	}
   226  
   227  	err = parsedReq.CheckSignature()
   228  	if err != nil {
   229  		t.Fatalf("Error checking signature of generated Certificate Request\nError: %s", err)
   230  	}
   231  }
   232  
   233  func validateExtendedKeyUsage(t *testing.T, parsedReq *x509.CertificateRequest) {
   234  	if parsedReq.Extensions == nil {
   235  		t.Fatalf("No extensions found in generated Certificate Request")
   236  	}
   237  
   238  	var extKeyUsages pkix.Extension
   239  	for _, extension := range parsedReq.Extensions {
   240  		if extension.Id.Equal(ExtensionExtKeyUsageOid) {
   241  			extKeyUsages = extension
   242  			break
   243  		}
   244  	}
   245  
   246  	if extKeyUsages.Id == nil {
   247  		t.Fatalf("No extension Extended Key Usages found in generated Certificate Request")
   248  	}
   249  
   250  	var b []asn1.ObjectIdentifier
   251  	_, err := asn1.Unmarshal(extKeyUsages.Value, &b)
   252  	if err != nil {
   253  		panic(err)
   254  	}
   255  
   256  	if len(b) != 1 {
   257  		t.Fatalf("Invalid extension Extended Key Usages found in generated Certificate Request. It was expected only one but it was gotten %q", len(b))
   258  	}
   259  
   260  	if !b[0].Equal(ExtKeyUsageServerAuthOid) {
   261  		t.Fatalf("Invalid extension Extended Key Usages found in generated Certificate Request. It was expected %q but it was gotten %q", ExtKeyUsageServerAuthOid, b[0])
   262  	}
   263  }
   264  
   265  func TestEllipticCurveString(t *testing.T) {
   266  	curve := EllipticCurveP521
   267  	stringCurve := curve.String()
   268  	if stringCurve != "P521" {
   269  		t.Fatalf("Unexpected string value was returned.  Expected: P521 Actual: %s", stringCurve)
   270  	}
   271  	curve = EllipticCurveP384
   272  	stringCurve = curve.String()
   273  	if stringCurve != "P384" {
   274  		t.Fatalf("Unexpected string value was returned.  Expected: P384 Actual: %s", stringCurve)
   275  	}
   276  	curve = EllipticCurveP256
   277  	stringCurve = curve.String()
   278  	if stringCurve != "P256" {
   279  		t.Fatalf("Unexpected string value was returned.  Expected: P256 Actual: %s", stringCurve)
   280  	}
   281  }
   282  
   283  func TestEllipticCurveSetByString(t *testing.T) {
   284  	curve := EllipticCurveDefault
   285  	curve.Set("P521")
   286  	if curve != EllipticCurveP521 {
   287  		t.Fatalf("Unexpected string value was returned.  Expected: P521 Actual: %s", curve.String())
   288  	}
   289  	curve.Set("P384")
   290  	if curve != EllipticCurveP384 {
   291  		t.Fatalf("Unexpected string value was returned.  Expected: P384 Actual: %s", curve.String())
   292  	}
   293  	curve.Set("P256")
   294  	if curve != EllipticCurveP256 {
   295  		t.Fatalf("Unexpected string value was returned.  Expected: P256 Actual: %s", curve.String())
   296  	}
   297  	curve.Set("p521")
   298  	if curve != EllipticCurveP521 {
   299  		t.Fatalf("Unexpected string value was returned.  Expected: p521 Actual: %s", curve.String())
   300  	}
   301  	curve.Set("p384")
   302  	if curve != EllipticCurveP384 {
   303  		t.Fatalf("Unexpected string value was returned.  Expected: p384 Actual: %s", curve.String())
   304  	}
   305  	curve.Set("p256")
   306  	if curve != EllipticCurveP256 {
   307  		t.Fatalf("Unexpected string value was returned.  Expected: p256 Actual: %s", curve.String())
   308  	}
   309  }
   310  
   311  func TestKeyTypeString(t *testing.T) {
   312  	keyType := KeyTypeECDSA
   313  	s := keyType.String()
   314  	if s != "ECDSA" {
   315  		t.Fatalf("Unexpected string value was returned.  Expected: ECDSA Actual: %s", s)
   316  	}
   317  	keyType = KeyTypeRSA
   318  	s = keyType.String()
   319  	if s != "RSA" {
   320  		t.Fatalf("Unexpected string value was returned.  Expected: RSA Actual: %s", s)
   321  	}
   322  	keyType = 5
   323  	s = keyType.String()
   324  	if s != "" {
   325  		t.Fatalf("Unexpected string value was returned.  Expected: \"\" Actual: %s", s)
   326  	}
   327  }
   328  
   329  func TestKeyTypeSetByString(t *testing.T) {
   330  	keyType := KeyTypeRSA
   331  	keyType.Set("rsa", "")
   332  	if keyType != KeyTypeRSA {
   333  		t.Fatalf("Unexpected string value was returned.  Expected: RSA Actual: %s", keyType.String())
   334  	}
   335  	keyType.Set("RSA", "")
   336  	if keyType != KeyTypeRSA {
   337  		t.Fatalf("Unexpected string value was returned.  Expected: RSA Actual: %s", keyType.String())
   338  	}
   339  	keyType.Set("ecdsa", "")
   340  	if keyType != KeyTypeECDSA {
   341  		t.Fatalf("Unexpected string value was returned.  Expected: ECDSA Actual: %s", keyType.String())
   342  	}
   343  	keyType.Set("ECDSA", "p384")
   344  	if keyType != KeyTypeECDSA {
   345  		t.Fatalf("Unexpected string value was returned.  Expected: ECDSA Actual: %s", keyType.String())
   346  	}
   347  	keyType.Set("ECDSA", "p384")
   348  	if keyType != KeyTypeECDSA {
   349  		t.Fatalf("Unexpected string value was returned.  Expected: ECDSA Actual: %s", keyType.String())
   350  	}
   351  	keyType.Set("EC", "p384")
   352  	if keyType != KeyTypeECDSA {
   353  		t.Fatalf("Unexpected string value was returned.  Expected: ECDSA Actual: %s", keyType.String())
   354  	}
   355  	keyType.Set("EC", "ed25519")
   356  	if keyType != KeyTypeED25519 {
   357  		t.Fatalf("Unexpected string value was returned.  Expected: ED25519 Actual: %s", keyType.String())
   358  	}
   359  }
   360  
   361  func TestGetPrivateKeyPEMBock(t *testing.T) {
   362  	var priv crypto.Signer
   363  	priv, err := GenerateRSAPrivateKey(512)
   364  	if err != nil {
   365  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   366  	}
   367  
   368  	p, err := GetPrivateKeyPEMBock(priv)
   369  	if err != nil {
   370  		t.Fatalf("Error: %s", err)
   371  	}
   372  	if p == nil {
   373  		t.Fatalf("GetPrivateKeyPEMBock returned nil for RSA key")
   374  	}
   375  
   376  	ellipticCurves := []EllipticCurve{EllipticCurveP256, EllipticCurveP384, EllipticCurveP521}
   377  	for _, curve := range ellipticCurves {
   378  		priv, err = GenerateECDSAPrivateKey(curve)
   379  		if err != nil {
   380  			t.Fatalf("Error generating ECDSA Private Key\nError: %s", err)
   381  		}
   382  
   383  		p, err = GetPrivateKeyPEMBock(priv)
   384  		if err != nil {
   385  			t.Fatalf("Error: %s", err)
   386  		}
   387  		if p == nil {
   388  			t.Fatalf("GetPrivateKeyPEMBock returned nil for ECDSA key")
   389  		}
   390  	}
   391  }
   392  
   393  func TestGetEncryptedPrivateKeyPEMBock(t *testing.T) {
   394  	var priv crypto.Signer
   395  	priv, err := GenerateRSAPrivateKey(512)
   396  	if err != nil {
   397  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   398  	}
   399  
   400  	p, err := GetEncryptedPrivateKeyPEMBock(priv, []byte("something"))
   401  	if err != nil {
   402  		t.Fatalf("Error: %s", err)
   403  	}
   404  	if p == nil {
   405  		t.Fatalf("GetPrivateKeyPEMBock returned nil for RSA key")
   406  	}
   407  
   408  	encoded := pem.EncodeToMemory(p)
   409  	str, err := util.DecryptPkcs8PrivateKey(string(encoded), "something")
   410  	if err != nil {
   411  		t.Fatalf("Error: %s", err)
   412  	}
   413  
   414  	p, _ = pem.Decode([]byte(str))
   415  	if p == nil {
   416  		t.Fatalf("missing private key PEM")
   417  	}
   418  
   419  	_, err = x509.ParsePKCS8PrivateKey(p.Bytes)
   420  	if err != nil {
   421  		t.Fatalf("Error: %s", err)
   422  	}
   423  
   424  	ellipticCurves := []EllipticCurve{EllipticCurveP256, EllipticCurveP384, EllipticCurveP521}
   425  	for _, curve := range ellipticCurves {
   426  		priv, err = GenerateECDSAPrivateKey(curve)
   427  		if err != nil {
   428  			t.Fatalf("Error generating ECDSA Private Key\nError: %s", err)
   429  		}
   430  
   431  		p, err = GetEncryptedPrivateKeyPEMBock(priv, []byte("something"))
   432  		if err != nil {
   433  			t.Fatalf("Error: %s", err)
   434  		}
   435  		if p == nil {
   436  			t.Fatalf("GetPrivateKeyPEMBock returned nil for ECDSA key")
   437  		}
   438  
   439  		strPem := string(pem.EncodeToMemory(p))
   440  
   441  		decryptedKey, err := util.DecryptPkcs8PrivateKey(strPem, "something")
   442  		if err != nil {
   443  			t.Fatalf("Error: %s", err)
   444  		}
   445  		p, _ = pem.Decode([]byte(decryptedKey))
   446  		_, err = x509.ParsePKCS8PrivateKey(p.Bytes)
   447  		if err != nil {
   448  			t.Fatalf("Error: %s", err)
   449  		}
   450  	}
   451  }
   452  
   453  func TestGetCertificatePEMBlock(t *testing.T) {
   454  	cert, _, err := generateTestCertificate()
   455  	if err != nil {
   456  		t.Fatalf("Error generating test certificate\nError: %s", err)
   457  	}
   458  	certPem := GetCertificatePEMBlock(cert.Raw)
   459  	if certPem == nil {
   460  		t.Fatalf("GetCertificatePEMBlock returned nil pem block")
   461  	}
   462  }
   463  
   464  func TestGetCertificateRequestPEMBlock(t *testing.T) {
   465  	certRequest := getCertificateRequestForTest()
   466  	var priv crypto.Signer
   467  	priv, err := GenerateRSAPrivateKey(512)
   468  	if err != nil {
   469  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   470  	}
   471  	err = GenerateRequest(certRequest, priv)
   472  	if err != nil {
   473  		t.Fatalf("Error generating request\nError: %s", err)
   474  	}
   475  	csrPem := GetCertificateRequestPEMBlock(certRequest.GetCSR())
   476  	if csrPem == nil {
   477  		t.Fatalf("GetCertificateRequestPEMBlock returned nil pem block")
   478  	}
   479  }
   480  
   481  func TestPublicKey(t *testing.T) {
   482  	priv, _ := GenerateRSAPrivateKey(512)
   483  	pub := PublicKey(priv)
   484  	if pub == nil {
   485  		t.Fatal("should return public key")
   486  	}
   487  }
   488  
   489  const (
   490  	checkCertificatePrivateKeyRSAvalid = `
   491  -----BEGIN PRIVATE KEY-----
   492  MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKiD4hrY58XqeYEB
   493  yIg14R6R2Ia/53cBSkNhzRn7Q9wDIzA8qJUkGNu8Oz0nE2V3LhDXsNM7B+IgO1LB
   494  YRBgegCKHpQVsYlnNUmETbJSILEsbEZZLCaMBXC/xONKpJi9E3qyNr6vNvYxd12O
   495  l9RN3tTl6NJG5gS8BAf8Z6X7r6bdAgMBAAECgYEAjpLGgiByOCkhk9yGZXfwd4S9
   496  xYQnubAFvOzKMuk7iLG+29j2aPiZb4/aLusYpggnmWhj2tNe4BqVFnc2QDzf+qTO
   497  fEmDm1mBnc0V+k0Rt99Wq9KPVMAm2EJBFrUGK7VGQ3H4B02kS+ywz6z25mebCzBT
   498  JlA7m3jaUdGJQEEPXgECQQDcVwlQrTPOxkG6UX3wfqtSgby0nVPH1N7h+aIVRbZY
   499  wfdXFsJEIv9ePly0S8MFLpxBNczR4Dqpm6ViEGkUEM+tAkEAw8mt5TAw9//38x0n
   500  ZyeYhGrM0qOMHHLw5XhnaJPiJ4NyU96aspr+Ppv4Z550f+Z3dIGSKnDinQly1jL1
   501  f21Z8QJBAKrR7y7UmG2d1icUNobULQ3x9tIvhlxN891NIxNK0GtPNOoXgtRALapq
   502  voQomDDUSd9kTj4HkHMdb8Hu5wffYKECQA5NBfGusnT68m6Em6MyRjat4mYkYhCV
   503  6LiqMct2udcvB8POh7gyEA4csGlJLrNE70bITBfjhPn5fbTdpgb3wtECQQC4dQBg
   504  335myMx7IDWT/I6R7i0Rx+WY7XZ84PkTwTd0q78yIhRS/42rgwEBMkkxlSg5X2sb
   505  Xjw3nEoRoeTEToar
   506  -----END PRIVATE KEY-----
   507  `
   508  	checkCertificatePrivateKeyRSAinvalid = `
   509  -----BEGIN PRIVATE KEY-----
   510  MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKOZvVaHHImhKD+r
   511  RZXJYV8busd0g0uWBGMeK+VltyG8H/h/neyPmHoEh62P/3FG3UP7oOAAGfz3/yCW
   512  hf7fHmNz1d6/HyCdQvD4kz/e9E6ty+k1iM5X6pGS97xPsObgHfyOgLn1/YdKvq81
   513  yG+O/mtfqQEI2izYUAbhUtq3qbctAgMBAAECgYAumTzH56YmQYQAVp10Y67bcz+J
   514  TlOTdQB85vwj1AwMjNQiaN8noWMR5jZrJmfg8QlXMtYI156PYmgF9Tnndc/mmVlg
   515  ow9mqEWjXZoBLCP++EkAbQ8dwmuGJB9WzIWFvj6bnKUOJAqQpsXv/wOqcrO7RZb0
   516  h2Wt/08tpuMZSYnUtQJBANIOKhCxJGjRbPgiczPFauuPi/kqSl1tLFbJfK0XBOvg
   517  Dezwz4YZpkhj1ttM6JB8QcDHEOMZ3XJMu+m8TqAB4cMCQQDHYmL7FzFg8QGeeeUe
   518  a4EVFSxmN45y2qSq2KyN0eaeuuV+fHjiLFyi+rZ+gA9xnyQFWcwTH+tFvcbi5aI7
   519  WgRPAkAC2XBWo6CDz3tz7juz0xS9N0hFy/4QQF/emYMYcfx+Gp71vNqDzitERh5v
   520  AR8Sfq0BqXGgMwSe/U17QTOr1fqzAkAFiwixbl2jElA3NbBW/ioiieooFVdSfh2h
   521  2lBByRoeQ5fpwlAiCZWxukKkla7YO9Jmi66OwY5q6/HBkRzHhaMlAkAEeP1wnnnQ
   522  F3iRLaRPmLtKf8sO1onEkSaQAq5p8/RFvNNwwqMh1t9wu9UYIefICoFsK0wAza9j
   523  4qQY8qM+To1X
   524  -----END PRIVATE KEY-----
   525  `
   526  	checkCertificateCSRRSA = `
   527  -----BEGIN CERTIFICATE REQUEST-----
   528  MIIBrDCCARUCAQAwbDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFV0YWgxEjAQBgNV
   529  BAcMCVNhbHQgTGFrZTEPMA0GA1UECgwGVmVuYWZpMQ8wDQYDVQQLDAZEZXZPcHMx
   530  GDAWBgNVBAMMD3Rlc3QudmVuZGV2LmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
   531  gYkCgYEAqIPiGtjnxep5gQHIiDXhHpHYhr/ndwFKQ2HNGftD3AMjMDyolSQY27w7
   532  PScTZXcuENew0zsH4iA7UsFhEGB6AIoelBWxiWc1SYRNslIgsSxsRlksJowFcL/E
   533  40qkmL0TerI2vq829jF3XY6X1E3e1OXo0kbmBLwEB/xnpfuvpt0CAwEAAaAAMA0G
   534  CSqGSIb3DQEBCwUAA4GBAGsKm5fJ8Zm/j9XMPXhPYmOdiDj+9QlcFq7uRRqwpxo7
   535  C507RR5Pj2zBRZRLJcc/bNTQFqnW92kIcvJ+YvrQl/GkEMKM2wds/RyMXRHtOJvZ
   536  YQt6JtkAeQOMECJ7RRHrZiG+m2by2YAB2krthK2gJGSr80xWzZWzrgdwdTe2sxUG
   537  -----END CERTIFICATE REQUEST-----
   538  `
   539  	chechCertificateRSACert = `
   540  -----BEGIN CERTIFICATE-----
   541  MIICyjCCAbICCQDtS0qAZisbTTANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJV
   542  UzENMAsGA1UECAwEVXRhaDESMBAGA1UEBwwJU2FsdCBMYWtlMQ8wDQYDVQQKDAZW
   543  ZW5hZmkxDzANBgNVBAsMBkRldk9wczESMBAGA1UEAwwJVmVuYWZpIENBMB4XDTE5
   544  MDMxNDE1MjAzMloXDTE5MDQxMzE1MjAzMlowbDELMAkGA1UEBhMCVVMxDTALBgNV
   545  BAgMBFV0YWgxEjAQBgNVBAcMCVNhbHQgTGFrZTEPMA0GA1UECgwGVmVuYWZpMQ8w
   546  DQYDVQQLDAZEZXZPcHMxGDAWBgNVBAMMD3Rlc3QudmVuZGV2LmNvbTCBnzANBgkq
   547  hkiG9w0BAQEFAAOBjQAwgYkCgYEAqIPiGtjnxep5gQHIiDXhHpHYhr/ndwFKQ2HN
   548  GftD3AMjMDyolSQY27w7PScTZXcuENew0zsH4iA7UsFhEGB6AIoelBWxiWc1SYRN
   549  slIgsSxsRlksJowFcL/E40qkmL0TerI2vq829jF3XY6X1E3e1OXo0kbmBLwEB/xn
   550  pfuvpt0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAMsuZogw+GE3ACQpULxxC3GFP
   551  +3N91g79V5PBP9flBuMuNoC5sQdEFaRBYA7VAUc/0kwT9hbQsm6GO/PnuhDljkqB
   552  2toPXTW5Okg93r0ZlTKrNWamsj3b5JQOB/dvjBx2c4VDzaD7lO0WMPaNbc0DV1Mm
   553  5UGslmj7iZIMRmyV4Cvdq/1u3/GjjO8q7qglltYtCP79xAw78dCbhtbdFzCixJ+g
   554  wNesasf48fL5jiH4gCwpzNij0ryhR0zglz+TsHRGVMef2CNFOw0PfkinQoaDI/Y+
   555  e/0CZ8Cg2oudlSulDRWzFJBwiCapeRfwkLkhO/pjd0ILvBk8DFzjwCFTpi2SpQ==
   556  -----END CERTIFICATE-----
   557  `
   558  	chechCertificateRSACert2 = `
   559  -----BEGIN CERTIFICATE-----
   560  MIICyjCCAbICCQDtS0qAZisbTjANBgkqhkiG9w0BAQsFADBmMQswCQYDVQQGEwJV
   561  UzENMAsGA1UECAwEVXRhaDESMBAGA1UEBwwJU2FsdCBMYWtlMQ8wDQYDVQQKDAZW
   562  ZW5hZmkxDzANBgNVBAsMBkRldk9wczESMBAGA1UEAwwJVmVuYWZpIENBMB4XDTE5
   563  MDMxNDE4MDMwMVoXDTE5MDQxMzE4MDMwMVowbDELMAkGA1UEBhMCVVMxDTALBgNV
   564  BAgMBFV0YWgxEjAQBgNVBAcMCVNhbHQgTGFrZTEPMA0GA1UECgwGVmVuYWZpMQ8w
   565  DQYDVQQLDAZEZXZPcHMxGDAWBgNVBAMMD3Rlc3QudmVuZGV2LmNvbTCBnzANBgkq
   566  hkiG9w0BAQEFAAOBjQAwgYkCgYEAo5m9VocciaEoP6tFlclhXxu6x3SDS5YEYx4r
   567  5WW3Ibwf+H+d7I+YegSHrY//cUbdQ/ug4AAZ/Pf/IJaF/t8eY3PV3r8fIJ1C8PiT
   568  P970Tq3L6TWIzlfqkZL3vE+w5uAd/I6AufX9h0q+rzXIb47+a1+pAQjaLNhQBuFS
   569  2repty0CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAfb5V/rcEEsZ68rRaEerkvPCk
   570  EiBMepUAzGrUFQyENiA2qoRuqKnOjhyzZ4uFiXFamiqCK0kjzUVraAYjzhGkH6AU
   571  AxUKXh5fa9tkt0XsZCS1aTjuDYAPO2Ug62OejUoZtRjy+nGUM7dYku9syzhmQ+hK
   572  AHu1RG+ZOtT13j3SAH0nkjEADzzsZhZWj/m5HtGQUY9ehAQhbTqn/M+aeGPxOdPt
   573  Ys0kiIJWXXW4JpJLfwKE9VFERQdHVum0+j8dUfOfyo0clJLPcesBFQ4RRkituxnG
   574  vDm5x5eZ/dsjYa8CcADBe/2KJBnldZW02o1/OqJ67m2Q1Y74hRTV5MGybpYx/w==
   575  -----END CERTIFICATE-----
   576  `
   577  )
   578  
   579  func TestRequest_CheckCertificate(t *testing.T) {
   580  	rsaPrivKeyInvalid := pemRSADecode(checkCertificatePrivateKeyRSAinvalid)
   581  	rsaPrivKeyValid := pemRSADecode(checkCertificatePrivateKeyRSAvalid)
   582  
   583  	cases := []struct {
   584  		name         string
   585  		request      Request
   586  		cert         string
   587  		valid        bool
   588  		errorMessage string
   589  	}{
   590  		{"valid req", Request{KeyType: KeyTypeRSA, PrivateKey: rsaPrivKeyValid}, chechCertificateRSACert, true, ""},
   591  		{"mismatched key type", Request{KeyType: KeyTypeECDSA, PrivateKey: rsaPrivKeyValid}, chechCertificateRSACert, false, "key type"},
   592  		{"mismatched keys", Request{KeyType: KeyTypeRSA, PrivateKey: rsaPrivKeyInvalid}, chechCertificateRSACert, false, "key modulus"},
   593  		{"valid csr", Request{csr: []byte(checkCertificateCSRRSA)}, chechCertificateRSACert, true, ""},
   594  		{"csr mismatched keys", Request{csr: []byte(checkCertificateCSRRSA)}, chechCertificateRSACert2, false, "key modulus"},
   595  	}
   596  	for i := range cases {
   597  		c := cases[i]
   598  		t.Run(c.name, func(t *testing.T) {
   599  			err := c.request.CheckCertificate(c.cert)
   600  			if c.valid && err != nil {
   601  				t.Fatalf("cert should be valid but checker found error: %s", err)
   602  			}
   603  			if !c.valid && err == nil {
   604  				t.Fatalf("certificate should failed but check returns that its valid")
   605  			}
   606  			if !c.valid && !strings.Contains(err.Error(), c.errorMessage) {
   607  				t.Fatalf("unexpected error '%s' (should conatins %s)", err.Error(), c.errorMessage)
   608  			}
   609  		})
   610  	}
   611  }
   612  
   613  func Test_NewRequest(t *testing.T) {
   614  	rsaPk, err := GenerateRSAPrivateKey(512)
   615  	if err != nil {
   616  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   617  	}
   618  
   619  	ecdsaPk, err := GenerateECDSAPrivateKey(EllipticCurveP256)
   620  	if err != nil {
   621  		t.Fatalf("Error generating ECDSA Private Key\nError: %s", err)
   622  	}
   623  
   624  	ed25519Pk, err := GenerateED25519PrivateKey()
   625  	if err != nil {
   626  		t.Fatalf("Error generating ECDSA Private Key\nError: %s", err)
   627  	}
   628  
   629  	cases := []struct {
   630  		name        string
   631  		certificate *x509.Certificate
   632  		expRequest  Request
   633  	}{
   634  		{
   635  			name: "rsa key",
   636  			certificate: &x509.Certificate{
   637  				PublicKey: rsaPk.Public(),
   638  			},
   639  			expRequest: Request{KeyType: KeyTypeRSA, KeyLength: 512},
   640  		},
   641  		{
   642  			name: "ecdsa key",
   643  			certificate: &x509.Certificate{
   644  				PublicKey: ecdsaPk.Public(),
   645  			},
   646  			expRequest: Request{KeyType: KeyTypeECDSA, KeyCurve: EllipticCurveP256},
   647  		},
   648  		{
   649  			name: "ed25519 key",
   650  			certificate: &x509.Certificate{
   651  				PublicKey: ed25519Pk.Public(),
   652  			},
   653  			expRequest: Request{KeyType: KeyTypeED25519, KeyCurve: EllipticCurveED25519},
   654  		},
   655  	}
   656  	for _, c := range cases {
   657  		c := c
   658  		t.Run(c.name, func(t *testing.T) {
   659  			req := NewRequest(c.certificate)
   660  			if !reflect.DeepEqual(req, &c.expRequest) {
   661  				t.Fatalf("expected request to be %v, got %v", c.expRequest, req)
   662  			}
   663  		})
   664  	}
   665  }
   666  
   667  func TestRequest_SetCSR_and_GetCSR(t *testing.T) {
   668  	checkCN := "setcsr.example.com"
   669  	certificateRequest := x509.CertificateRequest{}
   670  	certificateRequest.Subject.CommonName = checkCN
   671  	pk, err := GenerateRSAPrivateKey(512)
   672  	if err != nil {
   673  		t.Fatalf("Error generating RSA Private Key\nError: %s", err)
   674  	}
   675  
   676  	csr, err := x509.CreateCertificateRequest(rand.Reader, &certificateRequest, pk)
   677  	if err != nil {
   678  		csr = nil
   679  	}
   680  
   681  	rawCsr := csr
   682  
   683  	pemCsr := pem.EncodeToMemory(GetCertificateRequestPEMBlock(csr))
   684  	r := Request{}
   685  
   686  	csrs := [][]byte{rawCsr, pemCsr}
   687  	for _, csr := range csrs {
   688  		err = r.SetCSR(csr)
   689  		if err != nil {
   690  			t.Fatal(err)
   691  		}
   692  		gotCsr := r.GetCSR()
   693  		block, _ := pem.Decode(gotCsr)
   694  		cert, err := x509.ParseCertificateRequest(block.Bytes)
   695  		if err != nil {
   696  			t.Fatal(err)
   697  		}
   698  		if cert.Subject.CommonName != checkCN {
   699  			t.Fatalf("%s =! %s", cert.Subject.CommonName, checkCN)
   700  		}
   701  		err = r.SetCSR(pemCsr)
   702  		if err != nil {
   703  			t.Fatal(err)
   704  		}
   705  		t.Logf("Got cn %s from csr %s", cert.Subject.CommonName, gotCsr)
   706  	}
   707  
   708  }
   709  
   710  func pemRSADecode(priv string) *rsa.PrivateKey {
   711  	privPem, _ := pem.Decode([]byte(priv))
   712  
   713  	parsedKey, err := x509.ParsePKCS8PrivateKey(privPem.Bytes)
   714  	if err != nil {
   715  		panic(err)
   716  	}
   717  	return parsedKey.(*rsa.PrivateKey)
   718  }
   719  
   720  type FindNewestCertificateWithSansMock struct {
   721  	// testCase name
   722  	name string
   723  	// expected returned certificate
   724  	expected *CertificateInfo
   725  	// sans argument passed to FindNewestCertificateWithSans function
   726  	sans *Sans
   727  }
   728  
   729  func createTimeMock(t *testing.T, s string) time.Time {
   730  	time, err := time.Parse(time.RFC3339, s)
   731  
   732  	if err != nil {
   733  		t.Error(err)
   734  		t.Fatalf("error parsing time string %q", s)
   735  	}
   736  
   737  	return time
   738  }
   739  
   740  func TestFindNewestCertificateWithSans(t *testing.T) {
   741  	// create a list of certificates where we will try to find according to our
   742  	// testCases, we are not interested in any other field but the `SANS.DNS`,
   743  	// and `ValidTo` which are the ones used to match in the
   744  	// `FindNewestCertificateWithSans` function
   745  	certificates := []*CertificateInfo{
   746  		{
   747  			SANS: Sans{
   748  				DNS: []string{
   749  					"one.vfidev.com",
   750  				},
   751  			},
   752  			ValidTo: createTimeMock(t, "2022-08-22T00:00:00.000+00:00"),
   753  		},
   754  		{
   755  			SANS: Sans{
   756  				DNS: []string{
   757  					"one.vfidev.com",
   758  					"two.vfidev.com",
   759  				},
   760  			},
   761  			ValidTo: createTimeMock(t, "2022-08-22T00:00:00.000+00:00"),
   762  		},
   763  		{
   764  			SANS: Sans{
   765  				DNS: []string{
   766  					"one.vfidev.com",
   767  					"two.vfidev.com",
   768  				},
   769  			},
   770  			ValidTo: createTimeMock(t, "2030-01-01T00:00:00.000+00:00"),
   771  		},
   772  		{
   773  			SANS: Sans{
   774  				DNS: []string{
   775  					"1.vfidev.com",
   776  					"2.vfidev.com",
   777  					"3.vfidev.com",
   778  				},
   779  			},
   780  			ValidTo: createTimeMock(t, "2022-08-22T00:00:00.000+00:00"),
   781  		},
   782  	}
   783  
   784  	testCases := []FindNewestCertificateWithSansMock{
   785  		// should not return any certificate
   786  		{
   787  			name:     "Empty SANS",
   788  			expected: nil,
   789  			sans:     nil,
   790  		},
   791  		// should return the only existing certificate
   792  		{
   793  			name: "Simple",
   794  			expected: &CertificateInfo{
   795  				SANS: Sans{
   796  					DNS: []string{
   797  						"one.vfidev.com",
   798  					},
   799  				},
   800  				ValidTo: createTimeMock(t, "2022-08-22T00:00:00.000+00:00"),
   801  			},
   802  			sans: &Sans{DNS: []string{"one.vfidev.com"}},
   803  		},
   804  		//should return the newest certificate
   805  		{
   806  			name: "Newest",
   807  			expected: &CertificateInfo{
   808  				SANS: Sans{
   809  					DNS: []string{
   810  						"one.vfidev.com",
   811  						"two.vfidev.com",
   812  					},
   813  				},
   814  				ValidTo: createTimeMock(t, "2030-01-01T00:00:00.000+00:00"),
   815  			},
   816  			sans: &Sans{DNS: []string{"one.vfidev.com", "two.vfidev.com"}},
   817  		},
   818  		// should return the only existing certificate regardless of the order of
   819  		// the sans arguments
   820  		{
   821  			name: "Order of arguments",
   822  			expected: &CertificateInfo{
   823  				SANS: Sans{
   824  					DNS: []string{
   825  						"1.vfidev.com",
   826  						"2.vfidev.com",
   827  						"3.vfidev.com",
   828  					},
   829  				},
   830  				ValidTo: createTimeMock(t, "2022-08-22T00:00:00.000+00:00"),
   831  			},
   832  			sans: &Sans{DNS: []string{"3.vfidev.com", "2.vfidev.com", "1.vfidev.com"}},
   833  		},
   834  	}
   835  
   836  	for _, testCase := range testCases {
   837  		t.Run(testCase.name, func(t *testing.T) {
   838  			// ignore error, just use the certificate value as a sign of success
   839  			certificate, _ := FindNewestCertificateWithSans(certificates, testCase.sans)
   840  
   841  			// certificate should have been found but function returned no certificate
   842  			if testCase.expected != nil && certificate == nil {
   843  				t.Fatalf("certificate should have been found but function returned no certificate\nsans provided: %v\nexpected certificate: %v", util.GetJsonAsString(testCase.sans), util.GetJsonAsString(testCase.expected))
   844  			}
   845  
   846  			// no certificate should have been found but function returned one
   847  			if testCase.expected == nil && certificate != nil {
   848  				t.Fatalf("no certificate should have been found but function returned one\nsans provided: %v\nreturned certificate: %v", util.GetJsonAsString(testCase.sans), util.GetJsonAsString(certificate))
   849  			}
   850  
   851  			if !reflect.DeepEqual(testCase.expected, certificate) {
   852  				t.Fatalf("certificates did not match.\nexpected:\n%v\ngot:\n%v", util.GetJsonAsString(testCase.expected), util.GetJsonAsString(certificate))
   853  			}
   854  		})
   855  	}
   856  }