github.com/lestrrat-go/jwx/v2@v2.0.21/cert/chain.go (about)

     1  package cert
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  )
     8  
     9  // Chain represents a certificate chain as used in the `x5c` field of
    10  // various objects within JOSE.
    11  //
    12  // It stores the certificates as a list of base64 encoded []byte
    13  // sequence. By definition these values must PKIX encoded.
    14  type Chain struct {
    15  	certificates [][]byte
    16  }
    17  
    18  func (cc Chain) MarshalJSON() ([]byte, error) {
    19  	var buf bytes.Buffer
    20  	buf.WriteByte('[')
    21  	for i, cert := range cc.certificates {
    22  		if i > 0 {
    23  			buf.WriteByte(',')
    24  		}
    25  		buf.WriteByte('"')
    26  		buf.Write(cert)
    27  		buf.WriteByte('"')
    28  	}
    29  	buf.WriteByte(']')
    30  	return buf.Bytes(), nil
    31  }
    32  
    33  func (cc *Chain) UnmarshalJSON(data []byte) error {
    34  	var tmp []string
    35  	if err := json.Unmarshal(data, &tmp); err != nil {
    36  		return fmt.Errorf(`failed to unmarshal certificate chain: %w`, err)
    37  	}
    38  
    39  	certs := make([][]byte, len(tmp))
    40  	for i, cert := range tmp {
    41  		certs[i] = []byte(cert)
    42  	}
    43  	cc.certificates = certs
    44  	return nil
    45  }
    46  
    47  // Get returns the n-th ASN.1 DER + base64 encoded certificate
    48  // stored. `false` will be returned in the second argument if
    49  // the corresponding index is out of range.
    50  func (cc *Chain) Get(index int) ([]byte, bool) {
    51  	if index < 0 || index >= len(cc.certificates) {
    52  		return nil, false
    53  	}
    54  
    55  	return cc.certificates[index], true
    56  }
    57  
    58  // Len returns the number of certificates stored in this Chain
    59  func (cc *Chain) Len() int {
    60  	return len(cc.certificates)
    61  }
    62  
    63  var pemStart = []byte("----- BEGIN CERTIFICATE -----")
    64  var pemEnd = []byte("----- END CERTIFICATE -----")
    65  
    66  func (cc *Chain) AddString(der string) error {
    67  	return cc.Add([]byte(der))
    68  }
    69  
    70  func (cc *Chain) Add(der []byte) error {
    71  	// We're going to be nice and remove marker lines if they
    72  	// give it to us
    73  	der = bytes.TrimPrefix(der, pemStart)
    74  	der = bytes.TrimSuffix(der, pemEnd)
    75  	der = bytes.TrimSpace(der)
    76  	cc.certificates = append(cc.certificates, der)
    77  	return nil
    78  }