{"record":{"id":"50e2dcb876de56f5","repo":"OpenNHP/opennhp","slug":"failed-to-unwrap-data-private-key-s","errorCode":null,"errorMessage":"failed to unwrap data private key: %s","messagePattern":"failed to unwrap data private key: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"endpoints/agent/udpagent.go","lineNumber":1399,"sourceCode":"\n\t\t\tif ztdoId != ztdo.GetObjectID() {\n\t\t\t\tfmt.Printf(\"Error: ztdo id mismatch, please check with data provider\\n\")\n\t\t\t\treturn \"\", fmt.Errorf(\"ztdo id mismatch, please check with data provider\")\n\t\t\t}\n\n\t\t\t// decrypt data private key\n\t\t\tsaDataPrk := ztdolib.NewSymmetricAgreement(ztdo.GetECCMode(), false)\n\t\t\tsaDataPrk.SetMessagePatterns(ztdolib.DataPrivateKeyWrappingPatterns)\n\t\t\tsaDataPrk.SetPsk([]byte(ztdolib.InitialDHPKeyWrappingString))\n\t\t\tsaDataPrk.SetStaticKeyPair(teeEcdh)\n\t\t\tsaDataPrk.SetEphemeralKeyPair(consumerEphemeralEcdh)\n\t\t\tsaDataPrk.SetRemoteStaticPublicKey(providerPbk)\n\n\t\t\tgcmKey, ad := saDataPrk.AgreeSymmetricKey()\n\n\t\t\tdataPrkBase64, err := dataPrkWrapping.Unwrap(gcmKey[:], ad)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to unwrap data private key: %s\", err)\n\t\t\t}\n\n\t\t\tif ztdoPath == \"\" || output == \"\" {\n\t\t\t\treturn \"\", fmt.Errorf(\"ztdo path or output is empty\")\n\t\t\t}\n\n\t\t\t// decrypt data\n\t\t\tdataKeyPairEccMode := ztdo.GetECCMode()\n\n\t\t\tdataMsgPattern := [][]ztdolib.MessagePattern{\n\t\t\t\t{ztdolib.MessagePatternS, ztdolib.MessagePatternDHSS},\n\t\t\t\t{ztdolib.MessagePatternRS, ztdolib.MessagePatternDHSS},\n\t\t\t}\n\n\t\t\tdataPrk, _ := base64.StdEncoding.DecodeString(dataPrkBase64)\n\t\t\tsaData := ztdolib.NewSymmetricAgreement(dataKeyPairEccMode, false)\n\t\t\tsaData.SetMessagePatterns(dataMsgPattern)\n\t\t\tsaData.SetStaticKeyPair(core.ECDHFromKey(dataKeyPairEccMode.ToEccType(), dataPrk))","sourceCodeStart":1381,"sourceCodeEnd":1417,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/endpoints/agent/udpagent.go#L1381-L1417","documentation":"The agent could not unwrap the ztdo data private key. It derives a symmetric key via a Noise-style agreement with the provider's public key (saDataPrk.AgreeSymmetricKey) and calls dataPrkWrapping.Unwrap; any failure (wrong key material, tampered wrapping blob, wrong cipher scheme/ECC mode) is wrapped here.","triggerScenarios":"dataPrkWrapping.Unwrap(gcmKey[:], ad) errors: the ProviderPublicKeyBase64 doesn't match the key that wrapped the data private key, the wrapped key blob was altered, or the DHP key-wrapping pattern/PSK constants differ between producer and consumer versions.","commonSituations":"Provider rotated its key pair after encrypting; agent configured with an outdated provider public key; mixed SM2 vs Curve25519 (ECC mode) implementations; ztdo produced by an older library version using different InitialDHPKeyWrappingString.","solutions":["Verify the provider public key (ProviderPublicKeyBase64) is the current key that actually wrapped the data private key.","Confirm both sides use the same cipher scheme / ECC mode (curve vs gmsm).","Check that agent and provider ztdolib versions agree on the key-wrapping patterns and PSK constants.","Ask the provider to re-encrypt with its current key and re-publish the ztdo.","Confirm the ztdo id mismatch check passed — a wrong record will also fail unwrapping."],"exampleFix":"// before: provider key from message trusted blindly\nproviderPbk, _ := base64.StdEncoding.DecodeString(dataPrkWrapping.ProviderPublicKeyBase64)\n\n// after: decode with error check\nproviderPbk, err := base64.StdEncoding.DecodeString(dataPrkWrapping.ProviderPublicKeyBase64)\nif err != nil || len(providerPbk) != expectedKeyLen {\n    return \"\", fmt.Errorf(\"invalid provider public key: %w\", err)\n}","handlingStrategy":"validation","validationCode":"pbk, err := base64.StdEncoding.DecodeString(dataPrkWrapping.ProviderPublicKeyBase64)\nif err != nil {\n    return fmt.Errorf(\"provider public key is not valid base64\")\n}\nif len(pbk) != expectedPublicKeyLen(eccMode) {\n    return fmt.Errorf(\"provider public key length mismatch for ecc mode\")\n}","typeGuard":"func validProviderKey(b64 string, mode ztdolib.ECCMode) bool {\n    k, err := base64.StdEncoding.DecodeString(b64)\n    return err == nil && len(k) == expectedPublicKeyLen(mode)\n}","tryCatchPattern":"prk, err := dataPrkWrapping.Unwrap(gcmKey[:], ad)\nif err != nil {\n    // likely key rotation; refetch provider pubkey and retry once\n    return fmt.Errorf(\"data private key unwrap failed (check provider key rotation): %w\", err)\n}","preventionTips":["Track provider key rotations and re-encrypt data on rotation.","Distribute provider public keys via the authenticated peer table, not ad hoc.","Keep ztdolib versions and PSK/wrapping-pattern constants aligned across producer and consumer."],"tags":["crypto","key-wrapping","dhp","ztdo"],"backgroundTag":"decryption-key-mismatch","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}