github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/p2p/secure/secure_manager.go (about) 1 package secure 2 3 import ( 4 "bytes" 5 "crypto/x509" 6 "crypto/x509/pkix" 7 "encoding/asn1" 8 "errors" 9 "fmt" 10 "github.com/bigzoro/my_simplechain/common" 11 "github.com/bigzoro/my_simplechain/log" 12 "github.com/bigzoro/my_simplechain/rlp" 13 mapset "github.com/deckarep/golang-set" 14 "golang.org/x/crypto/sha3" 15 "io/ioutil" 16 "math/big" 17 "os" 18 "path/filepath" 19 "reflect" 20 "strings" 21 "time" 22 ) 23 24 type SecureConfig struct { 25 //root certificates 26 TlsRootCerts [][]byte 27 // List of TLS intermediate certificates; 28 TlsIntermediateCerts [][]byte 29 //revocation lists 30 RevocationList [][]byte 31 } 32 type SecureManager struct { 33 opts *x509.VerifyOptions 34 // list of CA TLS certs we trust ,setupTLSCAs 35 TLSRootCerts [][]byte 36 // list of intermediate TLS certs we trust,setupTLSCAs 37 TLSIntermediateCerts [][]byte 38 // list of certificate revocation lists,setupCRLs 39 CRL []*pkix.CertificateList 40 crlHashes mapset.Set 41 } 42 43 func rlpHash(x interface{}) (h common.Hash) { 44 hw := sha3.NewLegacyKeccak256() 45 rlp.Encode(hw, x) 46 hw.Sum(h[:0]) 47 return h 48 } 49 50 // 设置吊销证书 51 func (s *SecureManager) setupCRLs(conf *SecureConfig) error { 52 s.crlHashes = mapset.NewSet() 53 // setup the CRL (if present) 54 s.CRL = make([]*pkix.CertificateList, len(conf.RevocationList)) 55 for i, CRLBytes := range conf.RevocationList { 56 hash := rlpHash(CRLBytes) 57 s.crlHashes.Add(hash) 58 crl, err := x509.ParseCRL(CRLBytes) 59 if err != nil { 60 return errors.New(fmt.Sprintf("could not parse Content %v", err)) 61 } 62 // Massage the ECDSA signature values 63 if isECDSASignatureAlgorithm(crl.SignatureAlgorithm.Algorithm) { 64 r, s, err := UnmarshalECDSASignature(crl.SignatureValue.RightAlign()) 65 if err != nil { 66 return err 67 } 68 sig, err := MarshalECDSASignature(r, s) 69 if err != nil { 70 return err 71 } 72 crl.SignatureValue = asn1.BitString{Bytes: sig, BitLength: 8 * len(sig)} 73 } 74 s.CRL[i] = crl 75 } 76 return nil 77 } 78 func (s *SecureManager) SaveCRL(dir string, CRLBytes []byte) ([]*big.Int, error) { 79 hash := rlpHash(CRLBytes) 80 if s.crlHashes != nil && s.crlHashes.Contains(hash) { 81 return nil, errors.New("crl exists") 82 } 83 crl, err := x509.ParseCRL(CRLBytes) 84 if err != nil { 85 return nil, errors.New(fmt.Sprintf("could not parse Content %v", err)) 86 } 87 // Massage the ECDSA signature values 88 if isECDSASignatureAlgorithm(crl.SignatureAlgorithm.Algorithm) { 89 r, s, err := UnmarshalECDSASignature(crl.SignatureValue.RightAlign()) 90 if err != nil { 91 return nil, err 92 } 93 sig, err := MarshalECDSASignature(r, s) 94 if err != nil { 95 return nil, err 96 } 97 crl.SignatureValue = asn1.BitString{Bytes: sig, BitLength: 8 * len(sig)} 98 } 99 serialNumbers := make([]*big.Int, 0) 100 for _, rc := range crl.TBSCertList.RevokedCertificates { 101 serialNumbers = append(serialNumbers, rc.SerialNumber) 102 } 103 s.CRL = append(s.CRL, crl) 104 CRLsDir := filepath.Join(dir, CRLsFolder) 105 if !PathExists(CRLsDir) { 106 os.MkdirAll(CRLsDir, os.ModePerm) 107 } 108 fileName := fmt.Sprintf("crl_%d.pem", time.Now().Nanosecond()) 109 fileName = filepath.Join(CRLsDir, fileName) 110 log.Info("SecureManager receive crl data,save in", "path", fileName) 111 if err = ioutil.WriteFile(fileName, CRLBytes, 0666); err != nil { 112 return nil, err 113 } 114 return serialNumbers, nil 115 } 116 func PathExists(path string) bool { 117 _, err := os.Stat(path) 118 if err == nil { 119 return true 120 } 121 if os.IsNotExist(err) { 122 return false 123 } 124 return false 125 } 126 127 // 包括根证书和根证书 128 func (s *SecureManager) setupTLSCAs(conf *SecureConfig) error { 129 opts := &x509.VerifyOptions{Roots: x509.NewCertPool(), Intermediates: x509.NewCertPool()} 130 // Load TLS root and intermediate CA identities 131 s.TLSRootCerts = make([][]byte, len(conf.TlsRootCerts)) 132 rootCerts := make([]*x509.Certificate, len(conf.TlsRootCerts)) 133 for i, trustedCert := range conf.TlsRootCerts { 134 cert, err := GetCertFromPem(trustedCert) 135 if err != nil { 136 return err 137 } 138 rootCerts[i] = cert 139 s.TLSRootCerts[i] = trustedCert 140 opts.Roots.AddCert(cert) 141 } 142 // make and fill the set of intermediate certs (if present) 143 s.TLSIntermediateCerts = make([][]byte, len(conf.TlsIntermediateCerts)) 144 intermediateCerts := make([]*x509.Certificate, len(conf.TlsIntermediateCerts)) 145 for i, trustedCert := range conf.TlsIntermediateCerts { 146 cert, err := GetCertFromPem(trustedCert) 147 if err != nil { 148 return err 149 } 150 intermediateCerts[i] = cert 151 s.TLSIntermediateCerts[i] = trustedCert 152 opts.Intermediates.AddCert(cert) 153 } 154 s.opts = opts 155 // ensure that our CAs are properly formed and that they are valid 156 for _, cert := range append(append([]*x509.Certificate{}, rootCerts...), intermediateCerts...) { 157 if cert == nil { 158 continue 159 } 160 if !cert.IsCA { 161 return errors.New(fmt.Sprintf("CA Certificate did not have the CA attribute, (SN: %x)", cert.SerialNumber)) 162 } 163 if _, err := getSubjectKeyIdentifierFromCert(cert); err != nil { 164 return errors.New(fmt.Sprintf("%v CA Certificate problem with Subject Key Identifier extension, (SN: %x)", err, cert.SerialNumber)) 165 } 166 167 if err := s.validateTLSCAIdentity(cert, opts); err != nil { 168 return errors.New(fmt.Sprintf("%v CA Certificate is not valid, (SN: %s)", err, cert.SerialNumber)) 169 } 170 } 171 return nil 172 } 173 174 func (s *SecureManager) validateTLSCAIdentity(cert *x509.Certificate, opts *x509.VerifyOptions) error { 175 if !cert.IsCA { 176 return errors.New("only CA identities can be validated") 177 } 178 validationChain, err := s.getUniqueValidationChain(cert, *opts) 179 if err != nil { 180 return errors.New(fmt.Sprintf("%v could not obtain certification chain", err)) 181 } 182 if len(validationChain) == 1 { 183 return nil 184 } 185 return s.validateCertAgainstChain(cert, validationChain) 186 } 187 188 func (s *SecureManager) getUniqueValidationChain(cert *x509.Certificate, opts x509.VerifyOptions) ([]*x509.Certificate, error) { 189 // ask golang to validate the cert for us based on the options that we've built at setup time 190 if s.opts == nil { 191 return nil, errors.New("the supplied identity has no verify options") 192 } 193 validationChains, err := cert.Verify(opts) 194 if err != nil { 195 return nil, errors.New(fmt.Sprintf("%v the supplied identity is not valid", err)) 196 } 197 198 // we only support a single validation chain; 199 // if there's more than one then there might 200 // be unclarity about who owns the identity 201 if len(validationChains) != 1 { 202 return nil, errors.New(fmt.Sprintf("%v this MSP only supports a single validation chain, got %d", err, len(validationChains))) 203 } 204 205 // Make the additional verification checks that were done in Go 1.14. 206 err = verifyLegacyNameConstraints(validationChains[0]) 207 if err != nil { 208 return nil, errors.New(fmt.Sprintf("%v the supplied identity is not valid", err)) 209 } 210 211 return validationChains[0], nil 212 } 213 214 var ( 215 oidExtensionSubjectAltName = asn1.ObjectIdentifier{2, 5, 29, 17} 216 oidExtensionNameConstraints = asn1.ObjectIdentifier{2, 5, 29, 30} 217 ) 218 219 // verifyLegacyNameConstraints exercises the name constraint validation rules 220 // that were part of the certificate verification process in Go 1.14. 221 // 222 // If a signing certificate contains a name constratint, the leaf certificate 223 // does not include SAN extensions, and the leaf's common name looks like a 224 // host name, the validation would fail with an x509.CertificateInvalidError 225 // and a rason of x509.NameConstraintsWithoutSANs. 226 func verifyLegacyNameConstraints(chain []*x509.Certificate) error { 227 if len(chain) < 2 { 228 return nil 229 } 230 231 // Leaf certificates with SANs are fine. 232 if oidInExtensions(oidExtensionSubjectAltName, chain[0].Extensions) { 233 return nil 234 } 235 // Leaf certificates without a hostname in CN are fine. 236 if !validHostname(chain[0].Subject.CommonName) { 237 return nil 238 } 239 // If an intermediate or root have a name constraint, validation 240 // would fail in Go 1.14. 241 for _, c := range chain[1:] { 242 if oidInExtensions(oidExtensionNameConstraints, c.Extensions) { 243 return x509.CertificateInvalidError{Cert: chain[0], Reason: x509.NameConstraintsWithoutSANs} 244 } 245 } 246 return nil 247 } 248 249 func oidInExtensions(oid asn1.ObjectIdentifier, exts []pkix.Extension) bool { 250 for _, ext := range exts { 251 if ext.Id.Equal(oid) { 252 return true 253 } 254 } 255 return false 256 } 257 258 // validHostname reports whether host is a valid hostname that can be matched or 259 // matched against according to RFC 6125 2.2, with some leniency to accommodate 260 // legacy values. 261 // 262 // This implementation is sourced from the standard library. 263 func validHostname(host string) bool { 264 host = strings.TrimSuffix(host, ".") 265 266 if len(host) == 0 { 267 return false 268 } 269 270 for i, part := range strings.Split(host, ".") { 271 if part == "" { 272 // Empty label. 273 return false 274 } 275 if i == 0 && part == "*" { 276 // Only allow full left-most wildcards, as those are the only ones 277 // we match, and matching literal '*' characters is probably never 278 // the expected behavior. 279 continue 280 } 281 for j, c := range part { 282 if 'a' <= c && c <= 'z' { 283 continue 284 } 285 if '0' <= c && c <= '9' { 286 continue 287 } 288 if 'A' <= c && c <= 'Z' { 289 continue 290 } 291 if c == '-' && j != 0 { 292 continue 293 } 294 if c == '_' || c == ':' { 295 // Not valid characters in hostnames, but commonly 296 // found in deployments outside the WebPKI. 297 continue 298 } 299 return false 300 } 301 } 302 303 return true 304 } 305 func (s *SecureManager) validateCertAgainstChain(cert *x509.Certificate, validationChain []*x509.Certificate) error { 306 // here we know that the identity is valid; now we have to check whether it has been revoked 307 308 // identify the SKI of the CA that signed this cert 309 SKI, err := getSubjectKeyIdentifierFromCert(validationChain[1]) 310 if err != nil { 311 return errors.New(fmt.Sprintf("%vcould not obtain Subject Key Identifier for signer cert", err)) 312 } 313 314 // check whether one of the CRLs we have has this cert's 315 // SKI as its AuthorityKeyIdentifier 316 for _, crl := range s.CRL { 317 aki, err := getAuthorityKeyIdentifierFromCrl(crl) 318 if err != nil { 319 return errors.New(fmt.Sprintf("%v could not obtain Authority Key Identifier for crl", err)) 320 } 321 322 // check if the SKI of the cert that signed us matches the AKI of any of the CRLs 323 if bytes.Equal(aki, SKI) { 324 // we have a CRL, check whether the serial number is revoked 325 for _, rc := range crl.TBSCertList.RevokedCertificates { 326 if rc.SerialNumber.Cmp(cert.SerialNumber) == 0 { 327 // We have found a CRL whose AKI matches the SKI of 328 // the CA (root or intermediate) that signed the 329 // certificate that is under validation. As a 330 // precaution, we verify that said CA is also the 331 // signer of this CRL. 332 err = validationChain[1].CheckCRLSignature(crl) 333 if err != nil { 334 // the CA cert that signed the certificate 335 // that is under validation did not sign the 336 // candidate CRL - skip 337 log.Error(fmt.Sprintf("invalid signature over the identified CRL, error %+v", err)) 338 continue 339 } 340 341 // A CRL also includes a time of revocation so that 342 // the CA can say "this cert is to be revoked starting 343 // from this time"; however here we just assume that 344 // revocation applies instantaneously from the time 345 // the MSP config is committed and used so we will not 346 // make use of that field 347 return errors.New("the certificate has been revoked") 348 } 349 } 350 } 351 } 352 353 return nil 354 } 355 356 type authorityKeyIdentifier struct { 357 KeyIdentifier []byte `asn1:"optional,tag:0"` 358 AuthorityCertIssuer []byte `asn1:"optional,tag:1"` 359 AuthorityCertSerialNumber big.Int `asn1:"optional,tag:2"` 360 } 361 362 // getAuthorityKeyIdentifierFromCrl returns the Authority Key Identifier 363 // for the supplied CRL. The authority key identifier can be used to identify 364 // the public key corresponding to the private key which was used to sign the CRL. 365 func getAuthorityKeyIdentifierFromCrl(crl *pkix.CertificateList) ([]byte, error) { 366 aki := authorityKeyIdentifier{} 367 for _, ext := range crl.TBSCertList.Extensions { 368 // Authority Key Identifier is identified by the following ASN.1 tag 369 // authorityKeyIdentifier (2 5 29 35) (see https://tools.ietf.org/html/rfc3280.html) 370 if reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 35}) { 371 _, err := asn1.Unmarshal(ext.Value, &aki) 372 if err != nil { 373 return nil, errors.New(fmt.Sprintf("%vfailed to unmarshal AKI", err)) 374 } 375 376 return aki.KeyIdentifier, nil 377 } 378 } 379 380 return nil, errors.New("authorityKeyIdentifier not found in certificate") 381 } 382 383 func (s *SecureManager) validateCertAgainst(cert *x509.Certificate) error { 384 // check whether one of the CRLs we have has this cert's 385 for _, crl := range s.CRL { 386 // we have a CRL, check whether the serial number is revoked 387 for _, rc := range crl.TBSCertList.RevokedCertificates { 388 if rc.SerialNumber.Cmp(cert.SerialNumber) == 0 { 389 return errors.New("the certificate has been revoked") 390 } 391 } 392 } 393 return nil 394 }