slackhq/nebula · error

got a key of %d bytes, expected %d

Error message

got a key of %d bytes, expected %d

What it means

Test() performed a self-ECDH (DeriveNoise with the node's own public key) and the resulting shared secret length did not equal NoiseKeySize (32 bytes). The library throws this because a derive operation returning a different-size secret means the key or HSM cannot produce valid Noise material.

Source

Thrown at pkclient/pkclient.go:84

	switch t := e.(type) {
	case *ecdsa.PublicKey:
		return ecKeyToArray(e.(*ecdsa.PublicKey)), nil
	default:
		return nil, fmt.Errorf("unknown public key type: %T", t)
	}
}

func (c *PKClient) Test() error {
	pub, err := c.GetPubKey()
	if err != nil {
		return fmt.Errorf("failed to get public key: %w", err)
	}
	out, err := c.DeriveNoise(pub) //do an ECDH with ourselves as a quick test
	if err != nil {
		return err
	}
	if len(out) != NoiseKeySize {
		return fmt.Errorf("got a key of %d bytes, expected %d", len(out), NoiseKeySize)
	}
	return nil
}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Provision/verify the key is EC P-256 (prime256v1) specifically
  2. Check the HSM vendor's derive output format; left-pad to 32 bytes if a firmware quirk strips leading zeros
  3. Update the HSM firmware/vendor PKCS#11 library
  4. Confirm CKA_EC_PARAMS is the prime256v1 OID
  5. Test the same key with a minimal PKCS#11 derive script to see raw length

Example fix

// before
pkcs11-tool --keypairgen --key-type EC:secp384r1 --usage-derive
// after
pkcs11-tool --keypairgen --key-type EC:prime256v1 --usage-derive
Defensive patterns

Strategy: validation

Validate before calling

// ensure curve is P-256 before deriving
params, _ := session.GetAttributeValue(key, []*pkcs11.Attribute{
    pkcs11.NewAttribute(pkcs11.CKA_EC_PARAMS, nil),
})
// prime256v1 OID encoding: 06 08 2A 86 48 CE 3D 03 01 07
if !bytes.Equal(params[0].Value, []byte{0x06,0x08,0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07}) {
    return errors.New("HSM EC key is not P-256")
}

Try / catch

if err := client.Test(); err != nil {
    if strings.Contains(err.Error(), "got a key of") {
        return fmt.Errorf("HSM derive output incompatible; use P-256 key/vendor fix: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling Test() when session.DeriveNoise succeeds but returns byte length != NoiseKeySize — e.g. the HSM derives raw X coordinate padded differently, or the key is not a P-256 EC key.

Common situations: HSMs that return the derived secret with leading-zero padding stripped; non-P-256 curves (P-384/P-521) producing 48/66-byte secrets; non-EC keys that still expose a derive mechanism.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/bd9c626e025e23d9. Report an issue: GitHub.