Go API Documentation

github.com/TykTechnologies/tyk/internal/crypto

No package summary is available.

Package

Files: 6. Third party imports: 3. Imports from organisation: 1. Tests: 0. Benchmarks: 0.

Constants

// `{"` in base64
const B64JSONPrefix = "ey"
const DefaultHashAlgorithm = "murmur64"
const MongoBsonIdLength = 24
const SHA256 = crypto.SHA256
const (
	HashSha256	= "sha256"
	HashMurmur32	= "murmur32"
	HashMurmur64	= "murmur64"
	HashMurmur128	= "murmur128"
)
const (
	rsaPrivateKey	= "RSA PRIVATE KEY"
	certificate	= "CERTIFICATE"
)

Vars

var (
	ErrCertExpired = errors.New("Certificate has expired")
)
var certSubject = pkix.Name{
	Organization:	[]string{"Tyk Technologies Ltd"},
	Country:	[]string{"UK"},
	Province:	[]string{"London"},
	Locality:	[]string{"London"},
	StreetAddress:	[]string{"Worship Street"},
}

Types

CipherSuite

CipherSuite stores information about a cipher suite. It shadows tls.CipherSuite but translates TLS versions to strings.

Field name Field type Comment
ID

uint16

No comment on field.
Name

string

No comment on field.
Insecure

bool

No comment on field.
TLS

[]string

No comment on field.
type CipherSuite struct {
	ID		uint16		`json:"id"`
	Name		string		`json:"name"`
	Insecure	bool		`json:"insecure"`
	TLS		[]string	`json:"tls"`
}

Hash

This type doesn't have documentation.

Field name Field type Comment
type

crypto.Hash

No comment on field.
type Hash = crypto.Hash

Functions

func Decrypt

Decrypt from base64 to decrypted string

func Decrypt(key []byte, cryptoText string) string {
	ciphertext, err := base64.URLEncoding.DecodeString(cryptoText)
	if err != nil {
		logrus.Error(err)
		return ""
	}

	block, err := aes.NewCipher(key)
	if err != nil {
		logrus.Error(err)
		return ""
	}

	// The IV needs to be unique, but not secure. Therefore it's common to
	// include it at the beginning of the ciphertext.
	if len(ciphertext) < aes.BlockSize {
		logrus.Error("ciphertext too short")
		return ""
	}
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	stream := cipher.NewCFBDecrypter(block, iv)

	// XORKeyStream can work in-place if the two arguments are the same.
	stream.XORKeyStream(ciphertext, ciphertext)

	return string(ciphertext)
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: aes.BlockSize, aes.NewCipher, base64.URLEncoding, cipher.NewCFBDecrypter, logrus.Error.

func Encrypt

encrypt string to base64 crypto using AES

func Encrypt(key []byte, str string) string {
	plaintext := []byte(str)

	block, err := aes.NewCipher(key)
	if err != nil {
		logrus.Error(err)
		return ""
	}

	// The IV needs to be unique, but not secure. Therefore, it's common to
	// include it at the beginning of the ciphertext.
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		logrus.Error(err)
		return ""
	}

	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	// convert to base64
	return base64.URLEncoding.EncodeToString(ciphertext)
}

Cognitive complexity: 4, Cyclomatic complexity: 3

Uses: aes.BlockSize, aes.NewCipher, base64.URLEncoding, cipher.NewCFBEncrypter, io.ReadFull, logrus.Error, rand.Reader.

func GenCertificate

GenCertificate generates a self-signed X.509 certificate based on the provided template. It returns the certificate, private key, combined PEM bytes, and a tls.Certificate.

The function generates a private key, sets the certificate fields if not already set, and creates the certificate in PEM format. Use NotBefore and NotAfter in template to control the certificate expiry. If the NotBefore field of the template is zero-valued, it is set to the current time. If the NotAfter field is zero-valued, it is set to one hour after the NotBefore time. The generated certificate is then encoded to PEM format along with the private key.

A tls.Certificate is created using the PEM-encoded certificate and private key. If setLeaf is true, the certificate's Leaf field is set to the template.

func GenCertificate(template *x509.Certificate, setLeaf bool) ([]byte, []byte, []byte, tls.Certificate) {
	priv, _ := rsa.GenerateKey(rand.Reader, 2048)

	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)
	template.SerialNumber = serialNumber
	template.BasicConstraintsValid = true
	if template.NotBefore.IsZero() {
		template.NotBefore = time.Now()
	}

	if template.NotAfter.IsZero() {
		template.NotAfter = template.NotBefore.Add(time.Hour)
	}

	derBytes, _ := x509.CreateCertificate(rand.Reader, template, template, &priv.PublicKey, priv)

	var certPem, keyPem bytes.Buffer
	pem.Encode(&certPem, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
	pem.Encode(&keyPem, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})

	clientCert, _ := tls.X509KeyPair(certPem.Bytes(), keyPem.Bytes())
	if setLeaf {
		clientCert.Leaf = template
	}
	combinedPEM := bytes.Join([][]byte{certPem.Bytes(), keyPem.Bytes()}, []byte("\n"))

	return certPem.Bytes(), keyPem.Bytes(), combinedPEM, clientCert
}

Cognitive complexity: 9, Cyclomatic complexity: 4

Uses: big.Int, big.NewInt, bytes.Buffer, bytes.Join, pem.Block, pem.Encode, rand.Int, rand.Reader, rsa.GenerateKey, time.Hour, time.Now, tls.X509KeyPair, x509.CreateCertificate, x509.MarshalPKCS1PrivateKey.

func GenServerCertificate

GenServerCertificate generates a self-signed server certificate for "localhost" with DNS names "localhost" and IP addresses 127.0.0.1 and ::. It returns the certificate, private key, combined PEM bytes, and a tls.Certificate.

func GenServerCertificate() ([]byte, []byte, []byte, tls.Certificate) {
	certPem, privPem, combinedPEM, cert := GenCertificate(&x509.Certificate{
		DNSNames:	[]string{"localhost"},
		IPAddresses:	[]net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::")},
	}, false)

	return certPem, privPem, combinedPEM, cert
}

Cognitive complexity: 3, Cyclomatic complexity: 1

Uses: net.IP, net.ParseIP, x509.Certificate.

func GenerateClientCertAndKeyChain

GenerateClientCertAndKeyChain generates a client certificate and private key signed by the given root certificate and key, and includes the root certificate in the chain for testing purposes. It returns the client certificate chain and private key in PEM format along with an error, if any.

Parameters:

  • tb: The testing.TB instance to log errors and fail the test if necessary.
  • rootCertPEM: The root certificate in PEM format.
  • rootKeyPEM: The root private key in PEM format.

Returns:

  • *bytes.Buffer: The client certificate chain in PEM format.
  • *bytes.Buffer: The client private key in PEM format.
  • error: Any error encountered during the generation.

func GenerateClientCertAndKeyChain(tb testing.TB, rootCertPEM, rootKeyPEM []byte) (*bytes.Buffer, *bytes.Buffer, error) {
	tb.Helper()
	clientCertPEM, clientKeyPEM, err := GenerateClientCertAndKeyPEM(tb, rootCertPEM, rootKeyPEM)
	assert.NoError(tb, err)
	// Include the root certificate in the client certificate chain
	_, _ = clientCertPEM.Write(rootCertPEM)

	return clientCertPEM, clientKeyPEM, nil
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: assert.NoError.

func GenerateClientCertAndKeyPEM

GenerateClientCertAndKeyPEM generates a client certificate and private key signed by the given root certificate and key for testing purposes. It returns the client certificate and private key in PEM format along with an error, if any.

Parameters:

  • tb: The testing.TB instance to log errors and fail the test if necessary.
  • rootCertPEM: The root certificate in PEM format.
  • rootKeyPEM: The root private key in PEM format.

Returns:

  • *bytes.Buffer: The client certificate in PEM format.
  • *bytes.Buffer: The client private key in PEM format.
  • error: Any error encountered during the generation.

func GenerateClientCertAndKeyPEM(tb testing.TB, rootCertPEM, rootKeyPEM []byte) (*bytes.Buffer, *bytes.Buffer, error) {
	tb.Helper()

	rootCert, rootKey, err := decodeRootCertAndKey(rootCertPEM, rootKeyPEM)
	assert.NoError(tb, err)

	// Generate RSA key pair for the client
	clientKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, err
	}

	// Create a template for the client certificate
	clientCertTemplate := x509.Certificate{
		SerialNumber:	big.NewInt(3),
		Subject:	certSubject,
		NotBefore:	time.Now(),
		NotAfter:	time.Now().AddDate(1, 0, 0),	// 1 year
		KeyUsage:	x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:	[]x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
	}

	// Create the client certificate signed by the root CA
	clientCertDER, err := x509.CreateCertificate(rand.Reader, &clientCertTemplate, rootCert, &clientKey.PublicKey, rootKey)
	if err != nil {
		return nil, nil, err
	}

	// Encode the client certificate to PEM format
	var clientCertPEM bytes.Buffer
	assert.NoError(tb, pem.Encode(&clientCertPEM, &pem.Block{Type: certificate, Bytes: clientCertDER}))

	// Encode the client private key to PEM format
	var clientKeyPEM bytes.Buffer
	assert.NoError(tb, pem.Encode(&clientKeyPEM, &pem.Block{Type: rsaPrivateKey, Bytes: x509.MarshalPKCS1PrivateKey(clientKey)}))

	return &clientCertPEM, &clientKeyPEM, nil
}

Cognitive complexity: 8, Cyclomatic complexity: 3

Uses: assert.NoError, big.NewInt, bytes.Buffer, pem.Block, pem.Encode, rand.Reader, rsa.GenerateKey, time.Now, x509.Certificate, x509.CreateCertificate, x509.ExtKeyUsage, x509.ExtKeyUsageClientAuth, x509.KeyUsageDigitalSignature, x509.KeyUsageKeyEncipherment, x509.MarshalPKCS1PrivateKey.

func GenerateRSAPublicKey

GenerateRSAPublicKey generates an RSA public key.

func GenerateRSAPublicKey(tb testing.TB) []byte {
	tb.Helper()
	// Generate a private key.
	priv, err := rsa.GenerateKey(rand.Reader, 2048)
	assert.NoError(tb, err)

	// Derive the public key from the private key.
	publicKey := &priv.PublicKey

	// Save the public key in PEM format.
	publicKeyBytes, err := x509.MarshalPKIXPublicKey(publicKey)
	assert.NoError(tb, err)

	publicKeyBlock := &pem.Block{
		Type:	"PUBLIC KEY",
		Bytes:	publicKeyBytes,
	}

	publicKeyPEM := pem.EncodeToMemory(publicKeyBlock)
	return publicKeyPEM
}

Cognitive complexity: 1, Cyclomatic complexity: 1

Uses: assert.NoError, pem.Block, pem.EncodeToMemory, rand.Reader, rsa.GenerateKey, x509.MarshalPKIXPublicKey.

func GenerateRootCertAndKey

GenerateRootCertAndKey generates a root certificate and private key for testing purposes. It returns the root certificate and private key in PEM format along with an error, if any.

Parameters:

  • tb: The testing.TB instance to log errors and fail the test if necessary.

Returns:

  • []byte: The root certificate in PEM format.
  • []byte: The root private key in PEM format.
  • error: Any error encountered during the generation.

func GenerateRootCertAndKey(tb testing.TB) ([]byte, []byte, error) {
	tb.Helper()
	// Generate RSA key pair
	rootKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, err
	}

	// Create a template for the root certificate
	rootCertTemplate := x509.Certificate{
		SerialNumber:		big.NewInt(1),
		Subject:		certSubject,
		NotBefore:		time.Now(),
		NotAfter:		time.Now().AddDate(10, 0, 0),	// 10 years
		KeyUsage:		x509.KeyUsageCertSign | x509.KeyUsageCRLSign,
		BasicConstraintsValid:	true,
		IsCA:			true,
	}

	// Create the root certificate
	rootCertDER, err := x509.CreateCertificate(rand.Reader, &rootCertTemplate, &rootCertTemplate, &rootKey.PublicKey, rootKey)
	if err != nil {
		return nil, nil, err
	}

	// Encode the root certificate to PEM format
	var rootCertPEM bytes.Buffer
	assert.NoError(tb, pem.Encode(&rootCertPEM, &pem.Block{Type: certificate, Bytes: rootCertDER}))

	// Encode the root private key to PEM format
	var rootKeyPEM bytes.Buffer
	assert.NoError(tb, pem.Encode(&rootKeyPEM, &pem.Block{Type: rsaPrivateKey, Bytes: x509.MarshalPKCS1PrivateKey(rootKey)}))

	return rootCertPEM.Bytes(), rootKeyPEM.Bytes(), nil
}

Cognitive complexity: 7, Cyclomatic complexity: 3

Uses: assert.NoError, big.NewInt, bytes.Buffer, pem.Block, pem.Encode, rand.Reader, rsa.GenerateKey, time.Now, x509.Certificate, x509.CreateCertificate, x509.KeyUsageCRLSign, x509.KeyUsageCertSign, x509.MarshalPKCS1PrivateKey.

func GenerateServerCertAndKeyChain

GenerateServerCertAndKeyChain generates a server certificate and private key signed by the given root certificate and key, and includes the root certificate in the chain for testing purposes. It returns the server certificate chain and private key in PEM format along with an error, if any.

Parameters:

  • tb: The testing.TB instance to log errors and fail the test if necessary.
  • rootCertPEM: The root certificate in PEM format.
  • rootKeyPEM: The root private key in PEM format.

Returns:

  • *bytes.Buffer: The server certificate chain in PEM format.
  • *bytes.Buffer: The server private key in PEM format.
  • error: Any error encountered during the generation.

func GenerateServerCertAndKeyChain(tb testing.TB, rootCertPEM, rootKeyPEM []byte) (*bytes.Buffer, *bytes.Buffer, error) {
	tb.Helper()
	serverCertPEM, serverKeyPEM, err := GenerateServerCertAndKeyPEM(tb, rootCertPEM, rootKeyPEM)
	assert.NoError(tb, err)
	// Include the root certificate in the client certificate chain
	_, _ = serverCertPEM.Write(rootCertPEM)

	return serverCertPEM, serverKeyPEM, nil
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: assert.NoError.

func GenerateServerCertAndKeyPEM

GenerateServerCertAndKeyPEM generates a server certificate and private key signed by the given root certificate and key for testing purposes. It returns the server certificate and private key in PEM format along with an error, if any.

Parameters:

  • tb: The testing.TB instance to log errors and fail the test if necessary.
  • rootCertPEM: The root certificate in PEM format.
  • rootKeyPEM: The root private key in PEM format.

Returns:

  • *bytes.Buffer: The server certificate in PEM format.
  • *bytes.Buffer: The server private key in PEM format.
  • error: Any error encountered during the generation.

func GenerateServerCertAndKeyPEM(tb testing.TB, rootCertPEM, rootKeyPEM []byte) (*bytes.Buffer, *bytes.Buffer, error) {
	tb.Helper()

	rootCert, rootKey, err := decodeRootCertAndKey(rootCertPEM, rootKeyPEM)
	assert.NoError(tb, err)

	// Generate RSA key pair for the server
	serverKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, nil, err
	}

	// Create a template for the server certificate
	serverCertTemplate := x509.Certificate{
		SerialNumber:	big.NewInt(2),
		Subject:	certSubject,
		NotBefore:	time.Now(),
		NotAfter:	time.Now().AddDate(1, 0, 0),	// 1 year
		KeyUsage:	x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
		ExtKeyUsage:	[]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
		IPAddresses:	[]net.IP{net.ParseIP("127.0.0.1")},
		DNSNames:	[]string{"localhost"},
	}

	// Create the server certificate signed by the root CA
	serverCertDER, err := x509.CreateCertificate(rand.Reader, &serverCertTemplate, rootCert, &serverKey.PublicKey, rootKey)
	if err != nil {
		return nil, nil, err
	}

	// Encode the server certificate to PEM format
	var serverCertPEM bytes.Buffer
	assert.NoError(tb, pem.Encode(&serverCertPEM, &pem.Block{Type: certificate, Bytes: serverCertDER}))

	// Encode the server private key to PEM format
	var serverKeyPEM bytes.Buffer
	assert.NoError(tb, pem.Encode(&serverKeyPEM, &pem.Block{Type: rsaPrivateKey, Bytes: x509.MarshalPKCS1PrivateKey(serverKey)}))

	return &serverCertPEM, &serverKeyPEM, nil
}

Cognitive complexity: 10, Cyclomatic complexity: 3

Uses: assert.NoError, big.NewInt, bytes.Buffer, net.IP, net.ParseIP, pem.Block, pem.Encode, rand.Reader, rsa.GenerateKey, time.Now, x509.Certificate, x509.CreateCertificate, x509.ExtKeyUsage, x509.ExtKeyUsageServerAuth, x509.KeyUsageDigitalSignature, x509.KeyUsageKeyEncipherment, x509.MarshalPKCS1PrivateKey.

func GenerateToken

GenerateToken generates a token. If hashing algorithm is empty, it uses legacy key generation.

func GenerateToken(orgID, keyID, hashAlgorithm string) (string, error) {
	if keyID == "" {
		keyID = uuid.NewHex()
	}

	if hashAlgorithm != "" {
		_, err := hashFunction(hashAlgorithm)
		if err != nil {
			hashAlgorithm = DefaultHashAlgorithm
		}

		jsonToken := fmt.Sprintf(`{"org":"%s","id":"%s","h":"%s"}`, orgID, keyID, hashAlgorithm)
		return base64.StdEncoding.EncodeToString([]byte(jsonToken)), err
	}

	// Legacy keys
	return orgID + keyID, nil
}

Cognitive complexity: 7, Cyclomatic complexity: 4

Uses: base64.StdEncoding, fmt.Sprintf, uuid.NewHex.

func GetCiphers

GetCiphers generates a list of CipherSuite from the available ciphers.

func GetCiphers() []*CipherSuite {
	ciphers := tls.CipherSuites()
	result := make([]*CipherSuite, 0, len(ciphers))

	for _, cipher := range ciphers {
		result = append(result, NewCipher(cipher))
	}

	return result
}

Cognitive complexity: 3, Cyclomatic complexity: 2

Uses: tls.CipherSuites.

func GetPaddedString

func GetPaddedString(str string) []byte {
	return []byte(RightPad2Len(str, "=", 32))
}

Cognitive complexity: 0, Cyclomatic complexity: 1

func HashKey

func HashKey(in string, hashKey bool) string {
	if !hashKey {
		// Not hashing? Return the raw key
		return in
	}
	return HashStr(in)
}

Cognitive complexity: 2, Cyclomatic complexity: 2

func HashStr

func HashStr(in string, withAlg ...string) string {
	var algo string
	if len(withAlg) > 0 && withAlg[0] != "" {
		algo = withAlg[0]
	} else {
		algo = TokenHashAlgo(in)
	}

	h, err := hashFunction(algo)

	if err != nil {
		logrus.Error(err)
	}

	h.Write([]byte(in))
	return hex.EncodeToString(h.Sum(nil))
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: hex.EncodeToString, logrus.Error.

func HexSHA256

HexSHA256 calculates the SHA256 hash of the provided certificate bytes and returns the result as a hexadecimal string.

func HexSHA256(cert []byte) string {
	certSHA := sha256.Sum256(cert)
	return hex.EncodeToString(certSHA[:])
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: hex.EncodeToString, sha256.Sum256.

func IsPublicKey

IsPublicKey verifies if given certificate is a public key only.

func IsPublicKey(cert *tls.Certificate) bool {
	return cert.Leaf != nil && strings.HasPrefix(cert.Leaf.Subject.CommonName, "Public Key: ")
}

Cognitive complexity: 0, Cyclomatic complexity: 2

Uses: strings.HasPrefix.

func NewCipher

NewCipher translates tls.CipherSuite to our local type.

func NewCipher(in *tls.CipherSuite) *CipherSuite {
	return &CipherSuite{
		ID:		in.ID,
		Name:		in.Name,
		Insecure:	in.Insecure,
		TLS:		TLSVersions(in.SupportedVersions),
	}
}

Cognitive complexity: 1, Cyclomatic complexity: 1

func PrefixPublicKeyCommonName

PrefixPublicKeyCommonName returns x509.Certificate with prefixed CommonName. This is used in UI/response to hint the type certificate during listing.

func PrefixPublicKeyCommonName(blockBytes []byte) *x509.Certificate {
	return &x509.Certificate{
		Subject: pkix.Name{
			CommonName: "Public Key: " + HexSHA256(blockBytes),
		},
	}
}

Cognitive complexity: 2, Cyclomatic complexity: 1

Uses: pkix.Name, x509.Certificate.

func ResolveCipher

ResolveCipher translates a string representation of a cipher to its uint16 ID. It's case-insensitive when matching the cipher by name.

func ResolveCipher(cipherName string) (uint16, error) {
	ciphers := GetCiphers()
	for _, cipher := range ciphers {
		if strings.EqualFold(cipher.Name, cipherName) {
			return cipher.ID, nil
		}
	}
	return 0, fmt.Errorf("cipher %s not found", cipherName)
}

Cognitive complexity: 5, Cyclomatic complexity: 3

Uses: fmt.Errorf, strings.EqualFold.

func RightPad2Len

func RightPad2Len(s, padStr string, overallLen int) string {
	padCountInt := 1 + (overallLen-len(padStr))/len(padStr)
	retStr := s + strings.Repeat(padStr, padCountInt)
	return retStr[:overallLen]
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: strings.Repeat.

func TLSVersions

TLSVersions will return a list of TLS versions as a string.

func TLSVersions(in []uint16) []string {
	versions := make([]string, len(in))
	for i, v := range in {
		switch v {
		case tls.VersionTLS10:
			versions[i] = "1.0"
		case tls.VersionTLS11:
			versions[i] = "1.1"
		case tls.VersionTLS12:
			versions[i] = "1.2"
		case tls.VersionTLS13:
			versions[i] = "1.3"
		default:
			versions[i] = ""
		}
	}
	return versions
}

Cognitive complexity: 9, Cyclomatic complexity: 7

Uses: tls.VersionTLS10, tls.VersionTLS11, tls.VersionTLS12, tls.VersionTLS13.

func TokenHashAlgo

func TokenHashAlgo(token string) string {
	// Legacy tokens not b64 and not JSON records
	if strings.HasPrefix(token, B64JSONPrefix) {
		if jsonToken, err := base64.StdEncoding.DecodeString(token); err == nil {
			hashAlgo, err := jsonparser.GetString(jsonToken, "h")

			if err != nil {
				logrus.Error(err)
				return ""
			}

			return hashAlgo
		}
	}

	return ""
}

Cognitive complexity: 6, Cyclomatic complexity: 4

Uses: base64.StdEncoding, jsonparser.GetString, logrus.Error, strings.HasPrefix.

func TokenID

func TokenID(token string) (id string, err error) {
	jsonToken, err := base64.StdEncoding.DecodeString(token)
	if err != nil {
		return "", err
	}

	return jsonparser.GetString(jsonToken, "id")
}

Cognitive complexity: 2, Cyclomatic complexity: 2

Uses: base64.StdEncoding, jsonparser.GetString.

func TokenOrg

func TokenOrg(token string) string {
	if strings.HasPrefix(token, B64JSONPrefix) {
		if jsonToken, err := base64.StdEncoding.DecodeString(token); err == nil {
			// Checking error in case if it is a legacy token which just by accided has the same b64JSON prefix
			if org, err := jsonparser.GetString(jsonToken, "org"); err == nil {
				return org
			}
		}
	}

	// 24 is mongo bson id length
	if len(token) > MongoBsonIdLength {
		newToken := token[:MongoBsonIdLength]
		_, err := hex.DecodeString(newToken)
		if err == nil {
			return newToken
		}
	}

	return ""
}

Cognitive complexity: 10, Cyclomatic complexity: 6

Uses: base64.StdEncoding, hex.DecodeString, jsonparser.GetString, strings.HasPrefix.

func ValidateRequestCerts

ValidateRequestCerts validates client TLS certificates against a list of allowed certificates configured in API definition. It returns an error if TLS is not enabled, the client certificate is missing, or if it is not allowed or expired.

func ValidateRequestCerts(r *http.Request, certs []*tls.Certificate) error {
	if r.TLS == nil {
		return errors.New("TLS not enabled")
	}

	if len(r.TLS.PeerCertificates) == 0 {
		return errors.New("Client TLS certificate is required")
	}

	// Loop through r.TLS.PeerCertificates to add intermediate CA certificates to the allow list.
	for _, peerCertificate := range r.TLS.PeerCertificates {
		certID := HexSHA256(peerCertificate.Raw)

		for _, cert := range certs {
			// In case a cert can't be parsed or is invalid,
			// it will be present in the cert list as 'nil'
			if cert == nil {
				// Invalid cert, continue to next one
				continue
			}

			if cert.Leaf.IsCA && verifyCertAgainstCA(cert, peerCertificate) == nil {
				return nil
			}

			// Extensions[0] contains cache of certificate SHA256
			if string(cert.Leaf.Extensions[0].Value) == certID {
				if time.Now().After(cert.Leaf.NotAfter) {
					return ErrCertExpired
				}
				// Happy flow, we matched a certificate
				return nil
			}
		}
	}

	return errors.New("Certificate with SHA256 " + HexSHA256(r.TLS.PeerCertificates[0].Raw) + " not allowed")
}

Cognitive complexity: 18, Cyclomatic complexity: 10

Uses: errors.New, time.Now.

func (*CipherSuite) String

String returns a human-readable string for the cipher.

func (c *CipherSuite) String() string {
	return fmt.Sprintf("Cipher ID: %d, Name: %s, Insecure: %t, TLS: %v", c.ID, c.Name, c.Insecure, c.TLS)
}

Cognitive complexity: 0, Cyclomatic complexity: 1

Uses: fmt.Sprintf.

Private functions

func decodeRootCertAndKey

decodeRootCertAndKey (rootCertPEM,rootKeyPEM []byte) (*x509.Certificate, *rsa.PrivateKey, error)
References: fmt.Errorf, pem.Decode, x509.ParseCertificate, x509.ParsePKCS1PrivateKey.

func hashFunction

hashFunction (algorithm string) (hash.Hash, error)
References: fmt.Errorf, murmur3.New128, murmur3.New32, murmur3.New64, sha256.New.

func verifyCertAgainstCA

verifyCertAgainstCA (caCert *tls.Certificate, peerCert *x509.Certificate) error
References: x509.NewCertPool, x509.VerifyOptions.


Tests

Files: 2. Third party imports: 1. Imports from organisation: 0. Tests: 6. Benchmarks: 0.

Test functions

TestGenerateRSAPublicKey

References: assert.Contains.

TestGetCiphers

TestIsPublicKey

References: pkix.Name, testing.T, tls.Certificate, x509.Certificate.

TestNewCipher

References: tls.CipherSuite, tls.VersionTLS12, tls.VersionTLS13.

TestResolveCipher

References: testing.T.

TestTLSVersions

References: testing.T, tls.VersionTLS10, tls.VersionTLS11, tls.VersionTLS12, tls.VersionTLS13.