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  }