github.com/AntonOrnatskyi/goproxy@v0.0.0-20190205095733-4526a9fa18b4/utils/cert/cert.go (about) 1 package cert 2 3 import ( 4 "bytes" 5 cryptorand "crypto/rand" 6 "crypto/rsa" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "encoding/pem" 10 "io/ioutil" 11 "math/big" 12 "math/rand" 13 "net" 14 "strconv" 15 "time" 16 ) 17 18 func CreateSignCertToFile(rootCa *x509.Certificate, rootKey *rsa.PrivateKey, domainOrIP string, expireDays int, name string) (err error) { 19 cert, key, err := CreateSignCert(rootCa, rootKey, domainOrIP, expireDays) 20 if err != nil { 21 return 22 } 23 err = ioutil.WriteFile(name+".crt", cert, 0755) 24 if err != nil { 25 return 26 } 27 err = ioutil.WriteFile(name+".key", key, 0755) 28 return 29 } 30 func CreateSignCert(rootCa *x509.Certificate, rootKey *rsa.PrivateKey, domainOrIP string, expireDays int) (certBytes []byte, keyBytes []byte, err error) { 31 cer := &x509.Certificate{ 32 SerialNumber: big.NewInt(rand.Int63()), //证书序列号 33 Subject: pkix.Name{ 34 Country: []string{getCountry()}, 35 Organization: []string{domainOrIP}, 36 OrganizationalUnit: []string{domainOrIP}, 37 CommonName: domainOrIP, 38 }, 39 NotBefore: time.Now().Add(-time.Hour), 40 NotAfter: time.Now().Add(time.Hour * 24 * time.Duration(expireDays)), 41 BasicConstraintsValid: true, 42 IsCA: false, 43 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, 44 //KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment, 45 EmailAddresses: []string{}, 46 IPAddresses: []net.IP{}, 47 } 48 if ip := net.ParseIP(domainOrIP); ip != nil { 49 cer.IPAddresses = append(cer.IPAddresses, ip) 50 } else { 51 cer.DNSNames = append(cer.DNSNames, domainOrIP) 52 } 53 54 // cer.IPAddresses = append(cer.IPAddresses, alternateIPs...) 55 // cer.DNSNames = append(cer.DNSNames, alternateDNS...) 56 57 //生成公钥私钥对 58 priKey, err := rsa.GenerateKey(cryptorand.Reader, 2048) 59 if err != nil { 60 return 61 } 62 certBytes, err = x509.CreateCertificate(cryptorand.Reader, cer, rootCa, &priKey.PublicKey, rootKey) 63 if err != nil { 64 return 65 } 66 67 //编码证书文件和私钥文件 68 caPem := &pem.Block{ 69 Type: "CERTIFICATE", 70 Bytes: certBytes, 71 } 72 certBytes = pem.EncodeToMemory(caPem) 73 74 buf := x509.MarshalPKCS1PrivateKey(priKey) 75 keyPem := &pem.Block{ 76 Type: "RSA PRIVATE KEY", 77 Bytes: buf, 78 } 79 keyBytes = pem.EncodeToMemory(keyPem) 80 return 81 } 82 func CreateCaToFile(name, domainOrIP string, expireDays int) (err error) { 83 ca, key, err := CreateCa(domainOrIP, expireDays) 84 if err != nil { 85 return 86 } 87 err = ioutil.WriteFile(name+".crt", ca, 0755) 88 if err != nil { 89 return 90 } 91 err = ioutil.WriteFile(name+".key", key, 0755) 92 return 93 } 94 func CreateCa(organization string, expireDays int) (certBytes []byte, keyBytes []byte, err error) { 95 priv, err := rsa.GenerateKey(cryptorand.Reader, 2048) 96 if err != nil { 97 return nil, nil, err 98 } 99 100 template := x509.Certificate{ 101 SerialNumber: big.NewInt(1), 102 Subject: pkix.Name{ 103 CommonName: organization, 104 Organization: []string{organization}, 105 OrganizationalUnit: []string{organization}, 106 Country: []string{getCountry()}, 107 }, 108 NotBefore: time.Now().Add(-time.Hour), 109 NotAfter: time.Now().Add(time.Hour * 24 * time.Duration(expireDays)), 110 111 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, 112 ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, 113 BasicConstraintsValid: true, 114 IsCA: true, 115 } 116 117 derBytes, err := x509.CreateCertificate(cryptorand.Reader, &template, &template, &priv.PublicKey, priv) 118 if err != nil { 119 return nil, nil, err 120 } 121 122 // Generate cert 123 certBuffer := bytes.Buffer{} 124 if err := pem.Encode(&certBuffer, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { 125 return nil, nil, err 126 } 127 128 // Generate key 129 keyBuffer := bytes.Buffer{} 130 if err := pem.Encode(&keyBuffer, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}); err != nil { 131 return nil, nil, err 132 } 133 134 return certBuffer.Bytes(), keyBuffer.Bytes(), nil 135 } 136 func ParseCertAndKeyBytes(certPemFileByes, keyFileBytes []byte) (cert *x509.Certificate, privateKey *rsa.PrivateKey, err error) { 137 //解析根证书 138 cert, err = ParseCertBytes(certPemFileByes) 139 if err != nil { 140 return 141 } 142 //解析私钥 143 privateKey, err = ParseKeyBytes(keyFileBytes) 144 return 145 } 146 func ParseCertAndKey(certPemFile, keyFile string) (cert *x509.Certificate, privateKey *rsa.PrivateKey, err error) { 147 //解析根证书 148 cert, err = ParseCert(certPemFile) 149 if err != nil { 150 return 151 } 152 //解析私钥 153 privateKey, err = ParseKey(keyFile) 154 return 155 } 156 func ParseCert(certPemFile string) (cert *x509.Certificate, err error) { 157 //解析证书 158 certFile_, err := ioutil.ReadFile(certPemFile) 159 if err != nil { 160 return 161 } 162 cert, err = ParseCertBytes(certFile_) 163 return 164 } 165 func ParseKey(keyFile string) (key *rsa.PrivateKey, err error) { 166 //解析证书 167 keyFile_, err := ioutil.ReadFile(keyFile) 168 if err != nil { 169 return 170 } 171 key, err = ParseKeyBytes(keyFile_) 172 return 173 } 174 func ParseCertBytes(certPemFileBytes []byte) (cert *x509.Certificate, err error) { 175 caBlock, _ := pem.Decode(certPemFileBytes) 176 cert, err = x509.ParseCertificate(caBlock.Bytes) 177 return 178 } 179 func ParseKeyBytes(keyFileBytes []byte) (praKey *rsa.PrivateKey, err error) { 180 keyBlock, _ := pem.Decode(keyFileBytes) 181 praKey, err = x509.ParsePKCS1PrivateKey(keyBlock.Bytes) 182 return 183 } 184 func getCountry() string { 185 CList := []string{"AD", "AE", "AF", "AG", "AI", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BL", "BM", "BN", "BO", "BR", "BS", "BW", "BY", "BZ", "CA", "CF", "CG", "CH", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CU", "CY", "CZ", "DE", "DJ", "DK", "DO", "DZ", "EC", "EE", "EG", "ES", "ET", "FI", "FJ", "FR", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GM", "GN", "GR", "GT", "GU", "GY", "HK", "HN", "HT", "HU", "ID", "IE", "IL", "IN", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KP", "KR", "KT", "KW", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "ML", "MM", "MN", "MO", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", "NP", "NR", "NZ", "OM", "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PR", "PT", "PY", "QA", "RO", "RU", "SA", "SB", "SC", "SD", "SE", "SG", "SI", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TD", "TG", "TH", "TJ", "TM", "TN", "TO", "TR", "TT", "TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VC", "VE", "VN", "YE", "YU", "ZA", "ZM", "ZR", "ZW"} 186 return CList[int(randInt(4))%len(CList)] 187 } 188 func randInt(strLen int) int64 { 189 codes := "123456789" 190 codeLen := len(codes) 191 data := make([]byte, strLen) 192 rand.Seed(time.Now().UnixNano() + rand.Int63() + rand.Int63() + rand.Int63() + rand.Int63()) 193 for i := 0; i < strLen; i++ { 194 idx := rand.Intn(codeLen) 195 data[i] = byte(codes[idx]) 196 } 197 i, _ := strconv.ParseInt(string(data), 10, 64) 198 return i 199 }