mirror of
https://github.com/hanzoai/traces.git
synced 2026-10-30 18:20:41 +00:00
* Update dskit for gRPC interface change * Update vendor * Update vendor * bump dskit * update go.sum * manifest --------- Co-authored-by: javiermolinar <[email protected]>
124 lines
2.5 KiB
Go
124 lines
2.5 KiB
Go
package pemutil
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
const (
|
|
certType string = "CERTIFICATE"
|
|
keyType string = "PRIVATE KEY"
|
|
)
|
|
|
|
func ParseCertificates(certsBytes []byte) ([]*x509.Certificate, error) {
|
|
objects, err := parseBlocks(certsBytes, certType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
certs := []*x509.Certificate{}
|
|
for _, object := range objects {
|
|
cert, ok := object.(*x509.Certificate)
|
|
if !ok {
|
|
return nil, fmt.Errorf("expected *x509.Certificate; got %T", object)
|
|
}
|
|
certs = append(certs, cert)
|
|
}
|
|
|
|
return certs, nil
|
|
}
|
|
|
|
func ParsePrivateKey(keyBytes []byte) (crypto.PrivateKey, error) {
|
|
objects, err := parseBlocks(keyBytes, keyType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(objects) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
privateKey, ok := objects[0].(crypto.PrivateKey)
|
|
if !ok {
|
|
return nil, fmt.Errorf("expected crypto.PrivateKey; got %T", objects[0])
|
|
}
|
|
return privateKey, nil
|
|
}
|
|
|
|
func EncodePKCS8PrivateKey(privateKey interface{}) ([]byte, error) {
|
|
keyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return pem.EncodeToMemory(&pem.Block{
|
|
Type: keyType,
|
|
Bytes: keyBytes,
|
|
}), nil
|
|
}
|
|
|
|
func EncodeCertificates(certificates []*x509.Certificate) []byte {
|
|
pemBytes := []byte{}
|
|
for _, cert := range certificates {
|
|
pemBytes = append(pemBytes, pem.EncodeToMemory(&pem.Block{
|
|
Type: certType,
|
|
Bytes: cert.Raw,
|
|
})...)
|
|
}
|
|
return pemBytes
|
|
}
|
|
|
|
func parseBlocks(blocksBytes []byte, expectedType string) ([]interface{}, error) {
|
|
objects := []interface{}{}
|
|
var foundBlocks = false
|
|
for {
|
|
if len(blocksBytes) == 0 {
|
|
if len(objects) == 0 && !foundBlocks {
|
|
return nil, errors.New("no PEM blocks found")
|
|
}
|
|
return objects, nil
|
|
}
|
|
object, rest, foundBlock, err := parseBlock(blocksBytes, expectedType)
|
|
blocksBytes = rest
|
|
if foundBlock {
|
|
foundBlocks = true
|
|
}
|
|
switch {
|
|
case err != nil:
|
|
return nil, err
|
|
case object != nil:
|
|
objects = append(objects, object)
|
|
}
|
|
}
|
|
}
|
|
|
|
func parseBlock(pemBytes []byte, pemType string) (interface{}, []byte, bool, error) {
|
|
pemBlock, rest := pem.Decode(pemBytes)
|
|
if pemBlock == nil {
|
|
return nil, nil, false, nil
|
|
}
|
|
|
|
if pemBlock.Type != pemType {
|
|
return nil, rest, true, nil
|
|
}
|
|
|
|
var object interface{}
|
|
var err error
|
|
switch pemType {
|
|
case certType:
|
|
object, err = x509.ParseCertificate(pemBlock.Bytes)
|
|
case keyType:
|
|
object, err = x509.ParsePKCS8PrivateKey(pemBlock.Bytes)
|
|
default:
|
|
err = fmt.Errorf("PEM type not supported: %q", pemType)
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, nil, false, err
|
|
}
|
|
|
|
return object, rest, true, nil
|
|
}
|