hashicorp/nomad · error

error parsing %s public key: %w

Error message

error parsing %s public key: %w

What it means

This error is returned by the keyring public-key parsing helper in nomad/structs/keyring.go when a PEM-encoded key declared with the RS256 (RSA) algorithm cannot be decoded into an rsa.PublicKey. x509.ParsePKCS1PublicKey failed, meaning the underlying DER bytes are not a valid PKCS#1 RSA public key. Nomad wraps the underlying parse error with the algorithm name so the operator knows which key failed.

Source

Thrown at nomad/structs/keyring.go:582

	// a new key. Therefore this field can be used for cache control.
	CreateTime int64
}

// GetPublicKey returns the concrete PublicKey type. This *must* be used to
// retrieve the public key as functions such as go-jose's Claims(pubKey,
// claims) inspect pubKey's concrete type.
func (pubKey *KeyringPublicKey) GetPublicKey() (any, error) {
	switch alg := pubKey.Algorithm; alg {

	case PubKeyAlgEdDSA:
		// Convert public key bytes to an ed25519 public key
		return ed25519.PublicKey(pubKey.PublicKey), nil

	case PubKeyAlgRS256:
		// PEM -> rsa.PublickKey
		rsaPubKey, err := x509.ParsePKCS1PublicKey(pubKey.PublicKey)
		if err != nil {
			return nil, fmt.Errorf("error parsing %s public key: %w", alg, err)
		}
		return rsaPubKey, nil

	default:
		return nil, fmt.Errorf("unknown algorithm: %q", alg)
	}
}

// KeyringGetConfigResponse is the response for Keyring.GetConfig RPCs.
type KeyringGetConfigResponse struct {
	OIDCDiscovery *OIDCDiscoveryConfig
}

// OIDCDiscoveryConfig represents the response to OIDC Discovery requests
// usually at: /.well-known/openid-configuration
//
// Only the fields Nomad uses are implemented since many fields in the
// specification are not relevant to Nomad's use case:

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Re-export the key as a PKCS#1 RSA public key: openssl rsa -in key.pem -RSAPublicKey_out -out rsapub.pem, and reconfigure Nomad with it
  2. Confirm the key's algorithm field matches the key type (RS256 for RSA); if the key is EC/Ed25519, switch the configured algorithm instead of the key
  3. Inspect the wrapped inner error (%w) — e.g. 'asn1: structure error' points at malformed DER, while type mismatches indicate the wrong PEM format
  4. Verify the PEM block is a PUBLIC KEY/RSA PUBLIC KEY block, not a CERTIFICATE or PRIVATE KEY block

Example fix

// before (PEM is PKIX/SPKI, fails PKCS1 parse)
signing_key = "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
// after (convert to PKCS#1)
// openssl rsa -pubin -in pub.pem -RSAPublicKey_out -out rsapub.pem
signing_key = "-----BEGIN RSA PUBLIC KEY-----\n...\n-----END RSA PUBLIC KEY-----"
Defensive patterns

Strategy: validation

Validate before calling

func validateRSAPublicKeyPEM(pemBytes []byte) error {
	block, _ := pem.Decode(pemBytes)
	if block == nil { return fmt.Errorf("no PEM block") }
	if _, err := x509.ParsePKCS1PublicKey(block.Bytes); err != nil {
		return fmt.Errorf("not a PKCS#1 RSA public key: %w", err)
	}
	return nil
}

Type guard

func isPKCS1RSAPublicKey(pemBytes []byte) bool {
	block, _ := pem.Decode(pemBytes)
	if block == nil { return false }
	_, err := x509.ParsePKCS1PublicKey(block.Bytes)
	return err == nil
}

Prevention

When it happens

Trigger: Calling keyring config/JWKS-related APIs (e.g. workload identity / OIDC key setup) where a key loaded via ParsePublicKey or similar has PubKeyAlgRS256 but its PEM payload decodes to something else — e.g. a PKIX SubjectPublicKeyInfo, a PKCS#8 private key, an EC key, or corrupted base64/DER bytes.

Common situations: Operators paste an EC or Ed25519 public key while configuring signing_algorithm = "RS256"; a key was exported in SPKI/PKIX format (openssl pkey -pubout) instead of PKCS#1 (openssl rsa -RSAPublicKey_out); the key file was truncated or contains a certificate instead of a raw public key.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/55c50c044f214ee1. Report an issue: GitHub.