github.com/s7techlab/cckit@v0.10.5/identity/cert.go (about) 1 package identity 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/elliptic" 6 "crypto/rsa" 7 "crypto/x509" 8 "crypto/x509/pkix" 9 "encoding/asn1" 10 "encoding/base64" 11 "encoding/hex" 12 "encoding/pem" 13 "fmt" 14 15 "github.com/pkg/errors" 16 ) 17 18 // Certificate decode and parse .pem []byte x509 certificate structure 19 func Certificate(c []byte) (cert *x509.Certificate, err error) { 20 block, _ := pem.Decode(c) 21 if block == nil { 22 return nil, ErrPemEncodedExpected 23 } 24 return x509.ParseCertificate(block.Bytes) 25 } 26 27 func CertSubjEqual(a, b []byte) (bool, error) { 28 certA, err := Certificate(a) 29 if err != nil { 30 return false, errors.Wrap(err, `certificate 1`) 31 } 32 33 certB, err := Certificate(b) 34 if err != nil { 35 return false, errors.Wrap(err, `certificate 1`) 36 } 37 38 return GetDN(&certA.Subject) == GetDN(&certB.Subject), nil 39 } 40 41 // ID returns identifier from .509 certificate and base64 encode 42 func ID(subject, issuer string) string { 43 return base64.StdEncoding.EncodeToString([]byte(IDRaw(subject, issuer))) 44 } 45 46 // IDRaw generates string identifier from .509 certificate 47 func IDRaw(subject, issuer string) string { 48 return fmt.Sprintf("x509::%s::%s", subject, issuer) 49 } 50 51 // IDByCert returns id by certificate subject and issuer 52 func IDByCert(cert *x509.Certificate) string { 53 return ID(GetDN(&cert.Subject), GetDN(&cert.Issuer)) 54 } 55 56 // GetDN (distinguished name) associated with a pkix.Name. 57 // NOTE: This code is almost a direct copy of the String() function in 58 // https://go-review.googlesource.com/c/go/+/67270/1/src/crypto/x509/pkix/pkix.go#26 59 // which returns a DN as defined by RFC 2253. 60 func GetDN(name *pkix.Name) string { 61 r := name.ToRDNSequence() 62 s := "" 63 for i := 0; i < len(r); i++ { 64 rdn := r[len(r)-1-i] 65 if i > 0 { 66 s += "," 67 } 68 for j, tv := range rdn { 69 if j > 0 { 70 s += "+" 71 } 72 typeString := tv.Type.String() 73 typeName, ok := attributeTypeNames[typeString] 74 if !ok { 75 derBytes, err := asn1.Marshal(tv.Value) 76 if err == nil { 77 s += typeString + "=#" + hex.EncodeToString(derBytes) 78 continue // No value escaping necessary. 79 } 80 typeName = typeString 81 } 82 s += typeName + "=" + getEscaped(tv.Value) 83 } 84 } 85 return s 86 } 87 88 func getEscaped(val interface{}) string { 89 90 valueString := fmt.Sprint(val) 91 escaped := "" 92 begin := 0 93 for idx, c := range valueString { 94 if (idx == 0 && (c == ' ' || c == '#')) || 95 (idx == len(valueString)-1 && c == ' ') { 96 escaped += valueString[begin:idx] 97 escaped += "\\" + string(c) 98 begin = idx + 1 99 continue 100 } 101 switch c { 102 case ',', '+', '"', '\\', '<', '>', ';': 103 escaped += valueString[begin:idx] 104 escaped += "\\" + string(c) 105 begin = idx + 1 106 } 107 } 108 escaped += valueString[begin:] 109 return escaped 110 } 111 112 var attributeTypeNames = map[string]string{ 113 "2.5.4.6": "C", 114 "2.5.4.10": "O", 115 "2.5.4.11": "OU", 116 "2.5.4.3": "CN", 117 "2.5.4.5": "SERIALNUMBER", 118 "2.5.4.7": "L", 119 "2.5.4.8": "ST", 120 "2.5.4.9": "STREET", 121 "2.5.4.17": "POSTALCODE", 122 } 123 124 func MarshalPublicKey(publicKey interface{}) []byte { 125 switch pubKey := publicKey.(type) { 126 case *rsa.PublicKey: 127 fmt.Println(`LALALALAL`) 128 return nil 129 case *ecdsa.PublicKey: 130 return elliptic.Marshal(pubKey.Curve, pubKey.X, pubKey.Y) 131 } 132 133 return nil 134 }