ory/hydra · error

unable to base64 decode the TLS private key: %v

Error message

unable to base64 decode the TLS private key: %v

What it means

CertificateFromBase64 decodes the base64-encoded private key PEM. This error is returned when the key string is not valid standard base64. The certificate decoded fine, but the key material is corrupted or not base64.

Source

Thrown at oryx/tlsx/cert.go:80

- ` + prefix + `_CERT: Base64 encoded (without padding) string of the TLS certificate (PEM encoded) to be used for HTTP over TLS (HTTPS).
	Example: ` + prefix + `_CERT="-----BEGIN CERTIFICATE-----\nMIIDZTCCAk2gAwIBAgIEV5xOtDANBgkqhkiG9w0BAQ0FADA0MTIwMAYDVQQDDClP..."

- ` + prefix + `_KEY: Base64 encoded (without padding) string of the private key (PEM encoded) to be used for HTTP over TLS (HTTPS).
	Example: ` + prefix + `_KEY="-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDg..."
`
}

// CertificateFromBase64 loads a TLS certificate from a base64-encoded string of
// the PEM representations of the cert and key.
func CertificateFromBase64(certBase64, keyBase64 string) (tls.Certificate, error) {
	certPEM, err := base64.StdEncoding.DecodeString(certBase64)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("unable to base64 decode the TLS certificate: %v", err)
	}
	keyPEM, err := base64.StdEncoding.DecodeString(keyBase64)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("unable to base64 decode the TLS private key: %v", err)
	}
	cert, err := tls.X509KeyPair(certPEM, keyPEM)
	if err != nil {
		return tls.Certificate{}, fmt.Errorf("unable to load X509 key pair: %v", err)
	}
	return cert, nil
}

// [deprecated] Certificate returns a TLS Certificate by looking at its
// arguments. If both certPEMBase64 and keyPEMBase64 are not empty and contain
// base64-encoded PEM representations of a cert and key, respectively, that key
// pair is returned. Otherwise, if certPath and keyPath point to PEM files, the
// key pair is loaded from those. Returns ErrNoCertificatesConfigured if all
// arguments are empty, and ErrInvalidCertificateConfiguration if the arguments
// are inconsistent.
//
// This function is deprecated. Use CertificateFromBase64 or GetCertificate
// instead.

View on GitHub (pinned to 4174065ffb)

Solutions

  1. Re-encode the key: `base64 -w0 key.pem` and use that exact output
  2. Strip all whitespace/newlines from keyBase64 before decoding
  3. Check the value is standard (not URL-safe) base64 and not the raw PEM block
  4. Verify cert and key arguments are not swapped

Example fix

// before
keyB64 := "-----BEGIN PRIVATE KEY-----\n..." // raw PEM
// after
keyPEMBytes, _ := os.ReadFile("key.pem")
keyB64 := base64.StdEncoding.EncodeToString(keyPEMBytes)
Defensive patterns

Strategy: validation

Validate before calling

func isStdBase64(s string) bool {
    _, err := base64.StdEncoding.DecodeString(s)
    return err == nil
}
// run before CertificateFromBase64: isStdBase64(keyBase64)

Try / catch

cert, err := tlsx.CertificateFromBase64(certB64, keyB64)
if err != nil && strings.Contains(err.Error(), "base64 decode the TLS private key") {
    log.Error("keyBase64 is not valid standard base64; re-encode with `base64 -w0 key.pem`")
    return err
}

Prevention

When it happens

Trigger: Calling CertificateFromBase64 (directly or through Certificate/GetCertFunc) where certBase64 is valid but keyBase64 fails base64.StdEncoding.DecodeString — e.g. raw PEM key pasted, URL-safe base64, stray whitespace, or an empty/garbage key value.

Common situations: Only the key was re-generated/re-uploaded and pasted as raw PEM, env var containing the key got truncated, quoting issues in YAML/env files mangling the key string, or swapped cert/key order.

Understand the failure class

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/c41374197129c1de. Report an issue: GitHub.