OpenNHP/opennhp · error
invalid input key
Error message
invalid input key
What it means
The `nhp-device pubkey` command decodes the first positional argument as a base64 private key and passes the raw bytes to core.ECDHFromKey for the chosen cipher (SM2 by default, Curve25519 with --curve). ECDHFromKey returns nil when the bytes are not a valid private key scalar for that curve, and the command reports 'invalid input key'.
Solutions
- Regenerate the key with `nhp-device keygen --curve` or `--sm2` and pass its privateKey output verbatim
- Match the cipher flag to the key's origin: use --curve only for Curve25519 keys, omit it (SM2) only for SM2 keys
- Confirm you are passing the private key, not the public key, as the positional argument
- Quote the key argument so shells do not split or alter it
Example fix
// before nhp-device pubkey <curve25519-privkey> # parsed as SM2, fails // after nhp-device pubkey --curve <curve25519-privkey>
Defensive patterns
Strategy: validation
Validate before calling
const buf = Buffer.from(keyArg, 'base64');
if (buf.length === 0 || buf.toString('base64') !== keyArg.replace(/\s/g,'')) {
throw new Error('argument is not valid standard base64 key material');
}
// length must match the cipher: e.g. 32 bytes for Curve25519 Type guard
const looksLikeBase64Key = (s) => typeof s === 'string' && /^[A-Za-z0-9+/]+={0,2}$/.test(s.trim()) && Buffer.from(s, 'base64').length > 0; Try / catch
try {
execSync(`nhp-device pubkey ${cipherFlag} ${key}`);
} catch (e) {
if (String(e.stderr).includes('invalid input key')) {
// regenerate or re-select the cipher flag before retrying
}
} Prevention
- Always take keys verbatim from `nhp-device keygen --json` output
- Track which cipher (--curve/--sm2) each key belongs to
- Never pass public keys to the pubkey command; it expects a private key
- Quote key arguments in shell scripts
When it happens
Trigger: Running `nhp-device pubkey <base64-key>` where the decoded bytes are the wrong length or otherwise invalid for the selected ECC type — e.g. a Curve25519 key passed with default SM2 mode, a truncated key, a public key pasted instead of a private key, or whitespace/corruption in the base64.
Common situations: Copying a key between cipher schemes (mixing --curve and --sm2 output); pasting a public key where a private key is expected; shell mangling of the argument; hand-crafted test keys that are not valid scalars.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid input key
- failed to create device
- decode private key
- invalid input key
- missing remote peer public key
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/02822a815035dca0.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/db/main/main.go:183
},
Action: func(c *cli.Context) error {
privKey, err := base64.StdEncoding.DecodeString(c.Args().First())
if err != nil {
if c.Bool("json") {
json.NewEncoder(os.Stdout).Encode(map[string]interface{}{
"error": err.Error(),
})
return nil
}
return err
}
cipherType := core.ECC_SM2
if c.Bool("curve") {
cipherType = core.ECC_CURVE25519
}
e := core.ECDHFromKey(cipherType, privKey)
if e == nil {
err := fmt.Errorf("invalid input key")
if c.Bool("json") {
json.NewEncoder(os.Stdout).Encode(map[string]interface{}{
"error": err.Error(),
})
return nil
}
return err
}
pub := e.PublicKeyBase64()
if c.Bool("json") {
json.NewEncoder(os.Stdout).Encode(map[string]string{
"publicKey": pub,
})
} else {
fmt.Println("Public key: ", pub)
}
return nil
},View on GitHub (pinned to 6e04ca5ff0)