dubbo.apache.org/dubbo-go/v3@v3.1.1/xds/credentials/certgenerate/crypto.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 /* 19 * 20 * Copyright Istio Authors 21 * 22 */ 23 24 package certgenerate 25 26 import ( 27 "crypto" 28 "crypto/ecdsa" 29 "crypto/rsa" 30 "crypto/x509" 31 "encoding/pem" 32 "fmt" 33 "reflect" 34 "strings" 35 ) 36 37 const ( 38 blockTypeECPrivateKey = "EC PRIVATE KEY" 39 blockTypeRSAPrivateKey = "RSA PRIVATE KEY" // PKCS#1 private key 40 blockTypePKCS8PrivateKey = "PRIVATE KEY" // PKCS#8 plain private key 41 ) 42 43 // ParsePemEncodedCertificate constructs a `x509.Certificate` object using the 44 // given a PEM-encoded certificate. 45 func ParsePemEncodedCertificate(certBytes []byte) (*x509.Certificate, error) { 46 cb, _ := pem.Decode(certBytes) 47 if cb == nil { 48 return nil, fmt.Errorf("invalid PEM encoded certificate") 49 } 50 51 cert, err := x509.ParseCertificate(cb.Bytes) 52 if err != nil { 53 return nil, fmt.Errorf("failed to parse X.509 certificate") 54 } 55 56 return cert, nil 57 } 58 59 // ParsePemEncodedCertificateChain constructs a slice of `x509.Certificate` 60 // objects using the given a PEM-encoded certificate chain. 61 func ParsePemEncodedCertificateChain(certBytes []byte) ([]*x509.Certificate, error) { 62 var ( 63 certs []*x509.Certificate 64 cb *pem.Block 65 ) 66 for { 67 cb, certBytes = pem.Decode(certBytes) 68 if cb == nil { 69 break 70 } 71 cert, err := x509.ParseCertificate(cb.Bytes) 72 if err != nil { 73 return nil, fmt.Errorf("failed to parse X.509 certificate") 74 } 75 certs = append(certs, cert) 76 } 77 if len(certs) == 0 { 78 return nil, fmt.Errorf("no PEM encoded X.509 certificates parsed") 79 } 80 return certs, nil 81 } 82 83 // ParsePemEncodedCSR constructs a `x509.CertificateRequest` object using the 84 // given PEM-encoded certificate signing request. 85 func ParsePemEncodedCSR(csrBytes []byte) (*x509.CertificateRequest, error) { 86 block, _ := pem.Decode(csrBytes) 87 if block == nil { 88 return nil, fmt.Errorf("certificate signing request is not properly encoded") 89 } 90 csr, err := x509.ParseCertificateRequest(block.Bytes) 91 if err != nil { 92 return nil, fmt.Errorf("failed to parse X.509 certificate signing request") 93 } 94 return csr, nil 95 } 96 97 // ParsePemEncodedKey takes a PEM-encoded key and parsed the bytes into a `crypto.PrivateKey`. 98 func ParsePemEncodedKey(keyBytes []byte) (crypto.PrivateKey, error) { 99 kb, _ := pem.Decode(keyBytes) 100 if kb == nil { 101 return nil, fmt.Errorf("invalid PEM-encoded key") 102 } 103 104 switch kb.Type { 105 case blockTypeECPrivateKey: 106 key, err := x509.ParseECPrivateKey(kb.Bytes) 107 if err != nil { 108 return nil, fmt.Errorf("failed to parse the ECDSA private key") 109 } 110 return key, nil 111 case blockTypeRSAPrivateKey: 112 key, err := x509.ParsePKCS1PrivateKey(kb.Bytes) 113 if err != nil { 114 return nil, fmt.Errorf("failed to parse the RSA private key") 115 } 116 return key, nil 117 case blockTypePKCS8PrivateKey: 118 key, err := x509.ParsePKCS8PrivateKey(kb.Bytes) 119 if err != nil { 120 return nil, fmt.Errorf("failed to parse the PKCS8 private key") 121 } 122 return key, nil 123 default: 124 return nil, fmt.Errorf("unsupported PEM block type for a private key: %s", kb.Type) 125 } 126 } 127 128 // GetRSAKeySize returns the size if it is RSA key, otherwise it returns an error. 129 func GetRSAKeySize(privKey crypto.PrivateKey) (int, error) { 130 if t := reflect.TypeOf(privKey); t != reflect.TypeOf(&rsa.PrivateKey{}) { 131 return 0, fmt.Errorf("key type is not RSA: %v", t) 132 } 133 pkey := privKey.(*rsa.PrivateKey) 134 return pkey.N.BitLen(), nil 135 } 136 137 // IsSupportedECPrivateKey is a predicate returning true if the private key is EC based 138 func IsSupportedECPrivateKey(privKey *crypto.PrivateKey) bool { 139 switch (*privKey).(type) { 140 // this should agree with var SupportedECSignatureAlgorithms 141 case *ecdsa.PrivateKey: 142 return true 143 default: 144 return false 145 } 146 } 147 148 // PemCertBytestoString: takes an array of PEM certs in bytes and returns a string array in the same order with 149 // trailing newline characters removed 150 func PemCertBytestoString(caCerts []byte) []string { 151 certs := []string{} 152 var cert string 153 pemBlock := caCerts 154 for block, rest := pem.Decode(pemBlock); block != nil && len(block.Bytes) != 0; block, rest = pem.Decode(pemBlock) { 155 if len(rest) == 0 { 156 cert = strings.TrimPrefix(strings.TrimSuffix(string(pemBlock), "\n"), "\n") 157 certs = append(certs, cert) 158 break 159 } 160 cert = string(pemBlock[0 : len(pemBlock)-len(rest)]) 161 cert = strings.TrimPrefix(strings.TrimSuffix(cert, "\n"), "\n") 162 certs = append(certs, cert) 163 pemBlock = rest 164 } 165 return certs 166 }