github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/cryptogen/ca/ca_test.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 package ca_test 7 8 import ( 9 "crypto/ecdsa" 10 "crypto/x509" 11 "io/ioutil" 12 "net" 13 "os" 14 "path/filepath" 15 "testing" 16 17 "github.com/hechain20/hechain/internal/cryptogen/ca" 18 "github.com/hechain20/hechain/internal/cryptogen/csp" 19 "github.com/stretchr/testify/require" 20 ) 21 22 const ( 23 testCAName = "root0" 24 testCA2Name = "root1" 25 testCA3Name = "root2" 26 testName = "cert0" 27 testName2 = "cert1" 28 testName3 = "cert2" 29 testIP = "172.16.10.31" 30 testCountry = "US" 31 testProvince = "California" 32 testLocality = "San Francisco" 33 testOrganizationalUnit = "Hechain" 34 testStreetAddress = "testStreetAddress" 35 testPostalCode = "123456" 36 ) 37 38 func TestLoadCertificateECDSA(t *testing.T) { 39 testDir, err := ioutil.TempDir("", "ca-test") 40 if err != nil { 41 t.Fatalf("Failed to create test directory: %s", err) 42 } 43 defer os.RemoveAll(testDir) 44 45 // generate private key 46 certDir, err := ioutil.TempDir(testDir, "certs") 47 if err != nil { 48 t.Fatalf("Failed to create certs directory: %s", err) 49 } 50 priv, err := csp.GeneratePrivateKey(certDir) 51 require.NoError(t, err, "Failed to generate signed certificate") 52 53 // create our CA 54 caDir := filepath.Join(testDir, "ca") 55 rootCA, err := ca.NewCA( 56 caDir, 57 testCA3Name, 58 testCA3Name, 59 testCountry, 60 testProvince, 61 testLocality, 62 testOrganizationalUnit, 63 testStreetAddress, 64 testPostalCode, 65 ) 66 require.NoError(t, err, "Error generating CA") 67 68 cert, err := rootCA.SignCertificate( 69 certDir, 70 testName3, 71 nil, 72 nil, 73 &priv.PublicKey, 74 x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment, 75 []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, 76 ) 77 require.NoError(t, err, "Failed to generate signed certificate") 78 // KeyUsage should be x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment 79 require.Equal(t, x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment, 80 cert.KeyUsage) 81 require.Contains(t, cert.ExtKeyUsage, x509.ExtKeyUsageAny) 82 83 loadedCert, err := ca.LoadCertificateECDSA(certDir) 84 require.NoError(t, err) 85 require.NotNil(t, loadedCert, "Should load cert") 86 require.Equal(t, cert.SerialNumber, loadedCert.SerialNumber, "Should have same serial number") 87 require.Equal(t, cert.Subject.CommonName, loadedCert.Subject.CommonName, "Should have same CN") 88 } 89 90 func TestLoadCertificateECDSA_wrongEncoding(t *testing.T) { 91 testDir, err := ioutil.TempDir("", "wrongEncoding") 92 require.NoError(t, err, "failed to create test directory") 93 defer os.RemoveAll(testDir) 94 95 filename := filepath.Join(testDir, "wrong_encoding.pem") 96 err = ioutil.WriteFile(filename, []byte("wrong_encoding"), 0o644) // Wrong encoded cert 97 require.NoErrorf(t, err, "failed to create file %s", filename) 98 99 _, err = ca.LoadCertificateECDSA(testDir) 100 require.NotNil(t, err) 101 require.EqualError(t, err, filename+": wrong PEM encoding") 102 } 103 104 func TestLoadCertificateECDSA_empty_DER_cert(t *testing.T) { 105 testDir, err := ioutil.TempDir("", "ca-test") 106 require.NoError(t, err, "failed to create test directory") 107 defer os.RemoveAll(testDir) 108 109 filename := filepath.Join(testDir, "empty.pem") 110 empty_cert := "-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----" 111 err = ioutil.WriteFile(filename, []byte(empty_cert), 0o644) 112 require.NoErrorf(t, err, "failed to create file %s", filename) 113 114 cert, err := ca.LoadCertificateECDSA(testDir) 115 require.Nil(t, cert) 116 require.NotNil(t, err) 117 require.EqualError(t, err, filename+": wrong DER encoding") 118 } 119 120 func TestNewCA(t *testing.T) { 121 testDir, err := ioutil.TempDir("", "ca-test") 122 if err != nil { 123 t.Fatalf("Failed to create test directory: %s", err) 124 } 125 defer os.RemoveAll(testDir) 126 127 caDir := filepath.Join(testDir, "ca") 128 rootCA, err := ca.NewCA( 129 caDir, 130 testCAName, 131 testCAName, 132 testCountry, 133 testProvince, 134 testLocality, 135 testOrganizationalUnit, 136 testStreetAddress, 137 testPostalCode, 138 ) 139 require.NoError(t, err, "Error generating CA") 140 require.NotNil(t, rootCA, "Failed to return CA") 141 require.NotNil(t, rootCA.Signer, 142 "rootCA.Signer should not be empty") 143 require.IsType(t, &x509.Certificate{}, rootCA.SignCert, 144 "rootCA.SignCert should be type x509.Certificate") 145 146 // check to make sure the root public key was stored 147 pemFile := filepath.Join(caDir, testCAName+"-cert.pem") 148 require.Equal(t, true, checkForFile(pemFile), 149 "Expected to find file "+pemFile) 150 151 require.NotEmpty(t, rootCA.SignCert.Subject.Country, "country cannot be empty.") 152 require.Equal(t, testCountry, rootCA.SignCert.Subject.Country[0], "Failed to match country") 153 require.NotEmpty(t, rootCA.SignCert.Subject.Province, "province cannot be empty.") 154 require.Equal(t, testProvince, rootCA.SignCert.Subject.Province[0], "Failed to match province") 155 require.NotEmpty(t, rootCA.SignCert.Subject.Locality, "locality cannot be empty.") 156 require.Equal(t, testLocality, rootCA.SignCert.Subject.Locality[0], "Failed to match locality") 157 require.NotEmpty(t, rootCA.SignCert.Subject.OrganizationalUnit, "organizationalUnit cannot be empty.") 158 require.Equal(t, testOrganizationalUnit, rootCA.SignCert.Subject.OrganizationalUnit[0], "Failed to match organizationalUnit") 159 require.NotEmpty(t, rootCA.SignCert.Subject.StreetAddress, "streetAddress cannot be empty.") 160 require.Equal(t, testStreetAddress, rootCA.SignCert.Subject.StreetAddress[0], "Failed to match streetAddress") 161 require.NotEmpty(t, rootCA.SignCert.Subject.PostalCode, "postalCode cannot be empty.") 162 require.Equal(t, testPostalCode, rootCA.SignCert.Subject.PostalCode[0], "Failed to match postalCode") 163 } 164 165 func TestGenerateSignCertificate(t *testing.T) { 166 testDir, err := ioutil.TempDir("", "ca-test") 167 if err != nil { 168 t.Fatalf("Failed to create test directory: %s", err) 169 } 170 defer os.RemoveAll(testDir) 171 172 // generate private key 173 certDir, err := ioutil.TempDir(testDir, "certs") 174 if err != nil { 175 t.Fatalf("Failed to create certs directory: %s", err) 176 } 177 priv, err := csp.GeneratePrivateKey(certDir) 178 require.NoError(t, err, "Failed to generate signed certificate") 179 180 // create our CA 181 caDir := filepath.Join(testDir, "ca") 182 rootCA, err := ca.NewCA( 183 caDir, 184 testCA2Name, 185 testCA2Name, 186 testCountry, 187 testProvince, 188 testLocality, 189 testOrganizationalUnit, 190 testStreetAddress, 191 testPostalCode, 192 ) 193 require.NoError(t, err, "Error generating CA") 194 195 cert, err := rootCA.SignCertificate( 196 certDir, 197 testName, 198 nil, 199 nil, 200 &priv.PublicKey, 201 x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment, 202 []x509.ExtKeyUsage{x509.ExtKeyUsageAny}, 203 ) 204 require.NoError(t, err, "Failed to generate signed certificate") 205 // KeyUsage should be x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment 206 require.Equal(t, x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment, 207 cert.KeyUsage) 208 require.Contains(t, cert.ExtKeyUsage, x509.ExtKeyUsageAny) 209 210 cert, err = rootCA.SignCertificate( 211 certDir, 212 testName, 213 nil, 214 nil, 215 &priv.PublicKey, 216 x509.KeyUsageDigitalSignature, 217 []x509.ExtKeyUsage{}, 218 ) 219 require.NoError(t, err, "Failed to generate signed certificate") 220 require.Equal(t, 0, len(cert.ExtKeyUsage)) 221 222 // make sure ous are correctly set 223 ous := []string{"TestOU", "PeerOU"} 224 cert, err = rootCA.SignCertificate(certDir, testName, ous, nil, &priv.PublicKey, 225 x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{}) 226 require.NoError(t, err) 227 require.Contains(t, cert.Subject.OrganizationalUnit, ous[0]) 228 require.Contains(t, cert.Subject.OrganizationalUnit, ous[1]) 229 230 // make sure sans are correctly set 231 sans := []string{testName2, testName3, testIP} 232 cert, err = rootCA.SignCertificate(certDir, testName, nil, sans, &priv.PublicKey, 233 x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{}) 234 require.NoError(t, err) 235 require.Contains(t, cert.DNSNames, testName2) 236 require.Contains(t, cert.DNSNames, testName3) 237 require.Contains(t, cert.IPAddresses, net.ParseIP(testIP).To4()) 238 require.Equal(t, len(cert.DNSNames), 2) 239 240 // check to make sure the signed public key was stored 241 pemFile := filepath.Join(certDir, testName+"-cert.pem") 242 require.Equal(t, true, checkForFile(pemFile), 243 "Expected to find file "+pemFile) 244 245 _, err = rootCA.SignCertificate(certDir, "empty/CA", nil, nil, &priv.PublicKey, 246 x509.KeyUsageKeyEncipherment, []x509.ExtKeyUsage{x509.ExtKeyUsageAny}) 247 require.Error(t, err, "Bad name should fail") 248 249 // use an empty CA to test error path 250 badCA := &ca.CA{ 251 Name: "badCA", 252 SignCert: &x509.Certificate{}, 253 } 254 _, err = badCA.SignCertificate(certDir, testName, nil, nil, &ecdsa.PublicKey{}, 255 x509.KeyUsageKeyEncipherment, []x509.ExtKeyUsage{x509.ExtKeyUsageAny}) 256 require.Error(t, err, "Empty CA should not be able to sign") 257 } 258 259 func checkForFile(file string) bool { 260 if _, err := os.Stat(file); os.IsNotExist(err) { 261 return false 262 } 263 return true 264 }