hashicorp/nomad · error

error parsing rsa key: %w

Error message

error parsing rsa key: %w

What it means

If the root key stores an RSA key (used for Workload Identity JWT signing since Nomad 1.7), generateCipher parses it as PKCS#1 DER via x509.ParsePKCS1PrivateKey. A non-empty RSAKey blob that isn't valid PKCS#1 DER produces "error parsing rsa key".

Source

Thrown at nomad/encrypter.go:691

		}
	default:
		return nil, fmt.Errorf("invalid algorithm %s", rootKey.Meta.Algorithm)
	}

	ed25519Key := ed25519.NewKeyFromSeed(rootKey.Key)

	cs := cipherSet{
		rootKey:         rootKey,
		wrapper:         wrapper,
		eddsaPrivateKey: ed25519Key,
	}

	// Unmarshal RSAKey for Workload Identity JWT signing if one exists. Prior to
	// 1.7 only the ed25519 key was used.
	if len(rootKey.RSAKey) > 0 {
		rsaKey, err := x509.ParsePKCS1PrivateKey(rootKey.RSAKey)
		if err != nil {
			return nil, fmt.Errorf("error parsing rsa key: %w", err)
		}

		cs.rsaPrivateKey = rsaKey
		cs.rsaPKCS1PublicKey = x509.MarshalPKCS1PublicKey(&rsaKey.PublicKey)
	}

	return &cs, nil
}

// waitForKey retrieves the key material by ID from the keyring, retrying with
// geometric backoff until the context expires.
func (e *Encrypter) waitForKey(ctx context.Context, keyID string) (*cipherSet, error) {
	var ks *cipherSet

	err := helper.WithBackoffFunc(ctx, 50*time.Millisecond, 100*time.Millisecond,
		func() error {
			e.keyringLock.RLock()
			defer e.keyringLock.RUnlock()

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Check the wrapped x509 error; 'asn1: structure error' confirms malformed DER bytes
  2. Rotate the root key to regenerate a correctly encoded RSA key
  3. If migrating keys manually, ensure the bytes are x509.MarshalPKCS1PrivateKey DER, not PEM or PKCS8
  4. Restore a known-good keyring snapshot if state corruption is suspected

Example fix

// before: storing PEM bytes in RSAKey
rootKey.RSAKey = pemBytes
// after: store raw PKCS1 DER
der, _ := x509.MarshalPKCS1PrivateKey(priv), error check
rootKey.RSAKey = x509.MarshalPKCS1PrivateKey(priv)
Defensive patterns

Strategy: validation

Validate before calling

if len(rootKey.RSAKey) > 0 {
    if _, err := x509.ParsePKCS1PrivateKey(rootKey.RSAKey); err != nil {
        return fmt.Errorf("RSAKey is not PKCS1 DER: %w", err)
    }
}

Type guard

func isPKCS1DER(b []byte) bool { _, err := x509.ParsePKCS1PrivateKey(b); return len(b) > 0 && err == nil }

Try / catch

if err != nil && strings.HasPrefix(err.Error(), "error parsing rsa key") { /* rotate key to regenerate RSA material */ }

Prevention

When it happens

Trigger: rootKey.RSAKey has len > 0 but its bytes are not a valid PKCS1 private key — corrupted storage, wrong encoding (e.g. PKCS8 or PEM-wrapped bytes stored raw), or bytes from the wrong key.

Common situations: Snapshot restores that mangled binary columns; tooling that stored a PEM or PKCS8 encoding where Nomad expects raw PKCS1 DER; partial writes during crash.

Related errors


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