github.com/brimstone/sbuca@v0.0.0-20151202175429-8691d9eba5c5/pkix/cert.go (about) 1 package pkix 2 3 import ( 4 "crypto/x509" 5 "crypto/x509/pkix" 6 "encoding/pem" 7 "errors" 8 "io/ioutil" 9 "math/big" 10 "strings" 11 ) 12 13 type Certificate struct { 14 DerBytes []byte 15 16 Crt *x509.Certificate 17 } 18 19 func GenSubject(organization string) pkix.Name { 20 return pkix.Name{ 21 Organization: []string{organization}, 22 } 23 } 24 func NewCertificateFromDER(derBytes []byte) (*Certificate, error) { 25 26 crt, err := x509.ParseCertificate(derBytes) 27 if err != nil { 28 return nil, err 29 } 30 31 cert := &Certificate{ 32 DerBytes: derBytes, 33 Crt: crt, 34 } 35 36 return cert, nil 37 } 38 func NewCertificateFromPEM(pemBytes []byte) (*Certificate, error) { 39 40 pemBlock, _ := pem.Decode(pemBytes) 41 if pemBlock == nil { 42 return nil, errors.New("PEM decode failed") 43 } 44 45 crt, err := x509.ParseCertificate(pemBlock.Bytes) 46 if err != nil { 47 return nil, err 48 } 49 50 cert := &Certificate{ 51 DerBytes: pemBlock.Bytes, 52 Crt: crt, 53 } 54 55 return cert, nil 56 } 57 func NewCertificateFromPEMFile(filename string) (*Certificate, error) { 58 59 data, err := ioutil.ReadFile(filename) 60 if err != nil { 61 return nil, err 62 } 63 64 return NewCertificateFromPEM(data) 65 } 66 67 func (certificate *Certificate) ToPEM() ([]byte, error) { 68 69 pemBlock := &pem.Block{ 70 Type: "CERTIFICATE", 71 Bytes: certificate.DerBytes, 72 } 73 74 pemBytes := pem.EncodeToMemory(pemBlock) 75 76 return pemBytes, nil 77 } 78 func (certificate *Certificate) ToPEMFile(filename string) error { 79 pemBytes, err := certificate.ToPEM() 80 if err != nil { 81 return err 82 } 83 84 return ioutil.WriteFile(filename, pemBytes, 0400) 85 } 86 func (certificate *Certificate) GetSerialNumber() *big.Int { 87 return certificate.Crt.SerialNumber 88 } 89 90 func Marshal(name pkix.Name) (string, error) { 91 var output []string 92 if name.CommonName != "" { 93 output = append(output, "CN="+name.CommonName) 94 } 95 if len(name.Country) > 0 { 96 for i := range name.Country { 97 output = append(output, "C="+name.Country[i]) 98 } 99 } 100 if len(name.Locality) > 0 { 101 for i := range name.Locality { 102 output = append(output, "L="+name.Locality[i]) 103 } 104 } 105 if len(name.Province) > 0 { 106 for i := range name.Province { 107 output = append(output, "ST="+name.Province[i]) 108 } 109 } 110 if len(name.StreetAddress) > 0 { 111 for i := range name.StreetAddress { 112 output = append(output, "SA="+name.StreetAddress[i]) 113 } 114 } 115 if len(name.Organization) > 0 { 116 for i := range name.Organization { 117 output = append(output, "O="+name.Organization[i]) 118 } 119 } 120 if len(name.OrganizationalUnit) > 0 { 121 for i := range name.OrganizationalUnit { 122 output = append(output, "OU="+name.OrganizationalUnit[i]) 123 } 124 } 125 return strings.Join(output, ","), nil 126 } 127 128 func Unmarshal(dn string) (pkix.Name, error) { 129 var output pkix.Name 130 segments := strings.Split(dn, ",") 131 for segment := range segments { 132 identifier := strings.SplitN(segments[segment], "=", 2) 133 if identifier[0] == "CN" { 134 output.CommonName = identifier[1] 135 } else if identifier[0] == "C" { 136 output.Country = append(output.Country, identifier[1]) 137 } else if identifier[0] == "L" { 138 output.Locality = append(output.Locality, identifier[1]) 139 } else if identifier[0] == "ST" { 140 output.Province = append(output.Province, identifier[1]) 141 } else if identifier[0] == "SA" { 142 output.StreetAddress = append(output.StreetAddress, identifier[1]) 143 } else if identifier[0] == "O" { 144 output.Organization = append(output.Organization, identifier[1]) 145 } else if identifier[0] == "OU" { 146 output.OrganizationalUnit = append(output.OrganizationalUnit, identifier[1]) 147 } 148 } 149 return output, nil 150 }