github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/utils/crypto/crypto.go (about)

     1  package crypto
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/ecdsa"
     6  	"crypto/elliptic"
     7  	"crypto/hmac"
     8  	"crypto/rand"
     9  	"crypto/sha256"
    10  	"crypto/x509"
    11  	"encoding/base64"
    12  	"encoding/binary"
    13  	"encoding/pem"
    14  	"errors"
    15  	"fmt"
    16  	"math/big"
    17  	mrand "math/rand"
    18  	"sync"
    19  	"time"
    20  
    21  	"github.com/ugorji/go/codec"
    22  	"go.aporeto.io/tg/tglib/windowscertbug"
    23  	"go.uber.org/zap"
    24  )
    25  
    26  type nonce struct {
    27  	r *mrand.Rand
    28  	sync.Mutex
    29  }
    30  
    31  // PublicKey is an intermediate structure to create gobs
    32  type PublicKey struct {
    33  	X *big.Int
    34  	Y *big.Int
    35  }
    36  
    37  //Nonce16Byte interface generates 16 byte nonce
    38  type Nonce16Byte interface {
    39  	GenerateNonce16Bytes([]byte)
    40  }
    41  
    42  var doOnce sync.Once
    43  var n nonce
    44  
    45  // Nonce initializes and returns nonce of type Nonce16Byte.
    46  func Nonce() Nonce16Byte {
    47  	doOnce.Do(func() {
    48  		n.r = mrand.New(mrand.NewSource(time.Now().UnixNano()))
    49  	})
    50  
    51  	return &n
    52  }
    53  
    54  func (n *nonce) GenerateNonce16Bytes(b []byte) {
    55  	n.Lock()
    56  	low := n.r.Uint64()
    57  	high := n.r.Uint64()
    58  	n.Unlock()
    59  
    60  	binary.LittleEndian.PutUint64(b[:8], low)
    61  	binary.LittleEndian.PutUint64(b[8:], high)
    62  }
    63  
    64  // ComputeHmac256 computes the HMAC256 of the message
    65  func ComputeHmac256(tags []byte, key []byte) ([]byte, error) {
    66  
    67  	var buffer bytes.Buffer
    68  	if err := binary.Write(&buffer, binary.BigEndian, tags); err != nil {
    69  		return []byte{}, err
    70  	}
    71  
    72  	h := hmac.New(sha256.New, key)
    73  
    74  	if _, err := h.Write(buffer.Bytes()); err != nil {
    75  		return []byte{}, err
    76  	}
    77  
    78  	return h.Sum(nil), nil
    79  
    80  }
    81  
    82  // VerifyHmac verifies if the HMAC of the message matches the one provided
    83  func VerifyHmac(tags []byte, expectedMAC []byte, key []byte) bool {
    84  	messageMAC, err := ComputeHmac256(tags, key)
    85  	if err != nil {
    86  		return false
    87  	}
    88  
    89  	return hmac.Equal(messageMAC, expectedMAC)
    90  }
    91  
    92  // GenerateRandomBytes returns securely generated random bytes.
    93  // It will return an error if the system's secure random
    94  // number generator fails to function correctly, in which
    95  // case the caller should not continue.
    96  func GenerateRandomBytes(n int) ([]byte, error) {
    97  	b := make([]byte, n)
    98  
    99  	if _, err := rand.Read(b); err != nil {
   100  		zap.L().Debug("GenerateRandomBytes failed", zap.Error(err))
   101  		return nil, err
   102  	}
   103  
   104  	s := base64.StdEncoding.EncodeToString(b)
   105  
   106  	return []byte(s[:n]), nil
   107  }
   108  
   109  // GenerateRandomString returns a URL-safe, base64 encoded
   110  // securely generated random string.
   111  // It will return an error if the system's secure random
   112  // number generator fails to function correctly, in which
   113  // case the caller should not continue.
   114  func GenerateRandomString(s int) (string, error) {
   115  	b, err := GenerateRandomBytes(s)
   116  	return base64.URLEncoding.EncodeToString(b), err
   117  }
   118  
   119  // CreateEphemeralKey creates an ephmeral private/public key based on the
   120  // provided public key and the corresponding elliptic curve
   121  func CreateEphemeralKey(curve func() elliptic.Curve, pub *ecdsa.PublicKey) (*ecdsa.PrivateKey, []byte) {
   122  
   123  	ephemeral, err := ecdsa.GenerateKey(curve(), rand.Reader)
   124  	if err != nil {
   125  		zap.L().Error("CreateEphemeralKey failed, returning empty array of bytes", zap.Error(err))
   126  		return nil, []byte{}
   127  	}
   128  
   129  	ephPub := elliptic.Marshal(pub.Curve, ephemeral.PublicKey.X, ephemeral.PublicKey.Y)
   130  
   131  	return ephemeral, ephPub
   132  
   133  }
   134  
   135  // LoadRootCertificates loads the certificates in the provide PEM buffer in a CertPool
   136  func LoadRootCertificates(rootPEM []byte) *x509.CertPool {
   137  
   138  	roots := x509.NewCertPool()
   139  
   140  	ok := roots.AppendCertsFromPEM(rootPEM)
   141  	if !ok {
   142  		zap.L().Error("AppendCertsFromPEM failed", zap.ByteString("rootPEM", rootPEM))
   143  		return nil
   144  	}
   145  
   146  	return roots
   147  
   148  }
   149  
   150  // LoadEllipticCurveKey parses and creates an EC key
   151  func LoadEllipticCurveKey(keyPEM []byte) (*ecdsa.PrivateKey, error) {
   152  
   153  	block, _ := pem.Decode(keyPEM)
   154  	if block == nil {
   155  		return nil, fmt.Errorf("LoadElliticCurveKey bad pem block: %s", string(keyPEM))
   156  	}
   157  
   158  	// Parse the key
   159  	key, err := x509.ParseECPrivateKey(block.Bytes)
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  
   164  	return key, nil
   165  }
   166  
   167  // LoadAndVerifyCertificate parses, validates, and creates a certificate structure from a PEM buffer
   168  // It must be provided with the a CertPool
   169  func LoadAndVerifyCertificate(certPEM []byte, roots *x509.CertPool) (*x509.Certificate, error) {
   170  
   171  	cert, err := LoadCertificate(certPEM)
   172  	if err != nil {
   173  		return nil, err
   174  	}
   175  
   176  	opts := x509.VerifyOptions{
   177  		Roots: roots,
   178  	}
   179  
   180  	if _, err := windowscertbug.VerifyCertificate(cert, opts); err != nil {
   181  		return nil, err
   182  	}
   183  
   184  	return cert, nil
   185  
   186  }
   187  
   188  // LoadAndVerifyECSecrets loads all the certificates and keys to memory in the right data structures
   189  func LoadAndVerifyECSecrets(keyPEM, certPEM, caCertPEM []byte) (key *ecdsa.PrivateKey, cert *x509.Certificate, rootCertPool *x509.CertPool, err error) {
   190  
   191  	// Parse the key
   192  	key, err = LoadEllipticCurveKey(keyPEM)
   193  	if err != nil {
   194  		return nil, nil, nil, err
   195  	}
   196  
   197  	rootCertPool = LoadRootCertificates(caCertPEM)
   198  	if rootCertPool == nil {
   199  		return nil, nil, nil, errors.New("unable to load root certificate pool")
   200  	}
   201  
   202  	cert, err = LoadAndVerifyCertificate(certPEM, rootCertPool)
   203  	if err != nil {
   204  		return nil, nil, nil, err
   205  	}
   206  
   207  	return key, cert, rootCertPool, nil
   208  
   209  }
   210  
   211  // LoadCertificate loads a certificate from a PEM file without verifying
   212  // Should only be used for loading a root CA certificate. It will only read
   213  // the first certificate
   214  func LoadCertificate(certPEM []byte) (*x509.Certificate, error) {
   215  
   216  	// Decode the certificate
   217  	certBlock, _ := pem.Decode(certPEM)
   218  	if certBlock == nil {
   219  		return nil, fmt.Errorf("unable to parse pem block: %s", string(certPEM))
   220  	}
   221  
   222  	// Create the certificate structure
   223  	cert, err := x509.ParseCertificate(certBlock.Bytes)
   224  	if err != nil {
   225  		return nil, err
   226  	}
   227  
   228  	return cert, nil
   229  }
   230  
   231  //EncodePublicKeyV1 encodes the public key to a byte slice
   232  func EncodePublicKeyV1(publicKey *ecdsa.PublicKey) []byte {
   233  
   234  	p := &PublicKey{X: publicKey.X, Y: publicKey.Y}
   235  
   236  	buf := make([]byte, 0, 1400)
   237  	var h codec.Handle = new(codec.CborHandle)
   238  	enc := codec.NewEncoderBytes(&buf, h)
   239  
   240  	if err := enc.Encode(p); err != nil {
   241  		return nil
   242  	}
   243  
   244  	return buf
   245  
   246  }
   247  
   248  // DecodePublicKeyV1 decodes the provided public key
   249  func DecodePublicKeyV1(key []byte) (*ecdsa.PublicKey, error) {
   250  	var p PublicKey
   251  
   252  	var h codec.Handle = new(codec.CborHandle)
   253  
   254  	dec := codec.NewDecoderBytes(key, h)
   255  	if err := dec.Decode(&p); err != nil {
   256  		return nil, err
   257  	}
   258  
   259  	return &ecdsa.PublicKey{
   260  		Curve: elliptic.P256(),
   261  		X:     p.X,
   262  		Y:     p.Y,
   263  	}, nil
   264  }
   265  
   266  //EncodePublicKeyV2 encodes the public key to a byte slice
   267  func EncodePublicKeyV2(publicKey *ecdsa.PublicKey) []byte {
   268  	return elliptic.Marshal(publicKey.Curve, publicKey.X, publicKey.Y)
   269  }
   270  
   271  // DecodePublicKeyV2 decodes the provided public key
   272  func DecodePublicKeyV2(key []byte) (*ecdsa.PublicKey, error) {
   273  
   274  	x, y := elliptic.Unmarshal(elliptic.P256(), key)
   275  	if x == nil || y == nil {
   276  		return nil, fmt.Errorf("Failed to decode public key")
   277  	}
   278  
   279  	return &ecdsa.PublicKey{
   280  		Curve: elliptic.P256(),
   281  		X:     x,
   282  		Y:     y,
   283  	}, nil
   284  }
   285  
   286  //EncodePrivateKey encodes the private key to a byte slice.
   287  func EncodePrivateKey(privateKey *ecdsa.PrivateKey) []byte {
   288  	return elliptic.Marshal(privateKey.PublicKey.Curve, privateKey.D, privateKey.PublicKey.X)
   289  }