{"record":{"id":"ab3fbe24611db6d2","repo":"OpenNHP/opennhp","slug":"failed-to-read-hrk-data-v","errorCode":null,"errorMessage":"failed to read HRK data: %v","messagePattern":"failed to read HRK data: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/core/verifier/csv/csv.go","lineNumber":308,"sourceCode":"}\n\nfunc (a *Attestation) verifyCertChain(chipId string) error {\n\t// Download HRK from Hygon's certificate server\n\tif a.hrk == nil {\n\t\tresp, err := http.Get(\"https://cert.hygon.cn/hrk\")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to download HRK: %v\", err)\n\t\t}\n\t\tdefer resp.Body.Close()\n\n\t\tif resp.StatusCode != http.StatusOK {\n\t\t\treturn fmt.Errorf(\"unexpected status code when download HRK: %d\", resp.StatusCode)\n\t\t}\n\n\t\t// Read the response body (HRK content)\n\t\thrkData, err := io.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to read HRK data: %v\", err)\n\t\t}\n\n\t\ta.hrk = hrkData\n\t}\n\n\tdigest, err := Sm3Digest(a.hrk)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\texpectedDigest, _ := hex.DecodeString(\"f5a46663059fdb4cdd06d097ed21782142923bb3430b3b938f23d54292094e3a\")\n\tif !bytes.Equal(digest, expectedDigest) {\n\t\treturn fmt.Errorf(\"HRK digest verification failed: got %x, want %x\", digest, expectedDigest)\n\t}\n\n\tif err := a.verifyHygonCertInfo(a.hrk, 0x03, 0, a.hrk[0x04:0x14]); err != nil {\n\t\treturn err\n\t}","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/core/verifier/csv/csv.go#L290-L326","documentation":"verifyCertChain reads the HRK response body with io.ReadAll; if reading the stream fails it wraps the error here. The HTTP response was successful (status 200) but the body could not be fully read — typically a dropped connection mid-body or a reader/timeout error.","triggerScenarios":"First verifyCertChain call when a.hrk is nil, the GET to https://cert.hygon.cn/hrk returned 200, but io.ReadAll(resp.Body) fails due to connection reset mid-transfer, TLS read error, response body truncation, or an intervening proxy that closes the connection.","commonSituations":"Unstable network links (mobile/VPN); aggressive middleboxes or proxies that cut long responses; server-side timeouts writing the body; containerized environments with short idle timeouts.","solutions":["Retry the download; this error is usually transient.","Use an HTTP client with a sane timeout and retry/backoff policy instead of http.Get's defaults.","Validate the HRK digest after download (the code already checks a fixed SM3 digest) so partial bodies are caught even when reads succeed.","Persist a known-good HRK locally and fall back to it when the fetch fails.","Check whether a proxy/CDN in the path is truncating responses (compare Content-Length vs bytes read)."],"exampleFix":"// before\nhrkData, err := io.ReadAll(resp.Body)\nif err != nil {\n\treturn fmt.Errorf(\"failed to read HRK data: %v\", err)\n}\n// after: retry once on transient read failure\nhrkData, err := io.ReadAll(resp.Body)\nif err != nil {\n\tresp2, gerr := client.Get(hrkURL)\n\tif gerr == nil {\n\t\tdefer resp2.Body.Close()\n\t\thrkData, err = io.ReadAll(resp2.Body)\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to read HRK data: %v\", err)\n\t}\n}","handlingStrategy":"retry","validationCode":"// verify a cached HRK is complete before trusting it\nfunc hrkLooksValid(data []byte) bool {\n\treturn len(data) >= 0x2a8 // must contain all fields the verifier slices\n}","typeGuard":null,"tryCatchPattern":"if err := att.Verify(chipId); err != nil {\n\tif strings.Contains(err.Error(), \"failed to read HRK data\") {\n\t\ttime.Sleep(backoff)\n\t\treturn att.Verify(chipId) // transient mid-body read failure\n\t}\n\treturn err\n}","preventionTips":["Use an HTTP client with explicit timeouts instead of http.Get defaults.","Retry transient body-read failures automatically.","Always validate the downloaded HRK against its pinned SM3 digest before use.","Investigate middleboxes/proxies if truncation recurs."],"tags":["network","io","hrk-download","http"],"backgroundTag":"network-request-failed","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"}