OpenNHP/opennhp · error

failed to read HRK data

Error message

failed to read HRK data: %v

What it means

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.

Solutions

  1. Retry the download; this error is usually transient.
  2. Use an HTTP client with a sane timeout and retry/backoff policy instead of http.Get's defaults.
  3. Validate the HRK digest after download (the code already checks a fixed SM3 digest) so partial bodies are caught even when reads succeed.
  4. Persist a known-good HRK locally and fall back to it when the fetch fails.
  5. Check whether a proxy/CDN in the path is truncating responses (compare Content-Length vs bytes read).

Example fix

// before
hrkData, err := io.ReadAll(resp.Body)
if err != nil {
	return fmt.Errorf("failed to read HRK data: %v", err)
}
// after: retry once on transient read failure
hrkData, err := io.ReadAll(resp.Body)
if err != nil {
	resp2, gerr := client.Get(hrkURL)
	if gerr == nil {
		defer resp2.Body.Close()
		hrkData, err = io.ReadAll(resp2.Body)
	}
	if err != nil {
		return fmt.Errorf("failed to read HRK data: %v", err)
	}
}
Defensive patterns

Strategy: retry

Validate before calling

// verify a cached HRK is complete before trusting it
func hrkLooksValid(data []byte) bool {
	return len(data) >= 0x2a8 // must contain all fields the verifier slices
}

Try / catch

if err := att.Verify(chipId); err != nil {
	if strings.Contains(err.Error(), "failed to read HRK data") {
		time.Sleep(backoff)
		return att.Verify(chipId) // transient mid-body read failure
	}
	return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/ab3fbe24611db6d2. Report an issue: GitHub.

Appendix: source

Thrown at nhp/core/verifier/csv/csv.go:308

}

func (a *Attestation) verifyCertChain(chipId string) error {
	// Download HRK from Hygon's certificate server
	if a.hrk == nil {
		resp, err := http.Get("https://cert.hygon.cn/hrk")
		if err != nil {
			return fmt.Errorf("failed to download HRK: %v", err)
		}
		defer resp.Body.Close()

		if resp.StatusCode != http.StatusOK {
			return fmt.Errorf("unexpected status code when download HRK: %d", resp.StatusCode)
		}

		// Read the response body (HRK content)
		hrkData, err := io.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("failed to read HRK data: %v", err)
		}

		a.hrk = hrkData
	}

	digest, err := Sm3Digest(a.hrk)
	if err != nil {
		return err
	}

	expectedDigest, _ := hex.DecodeString("f5a46663059fdb4cdd06d097ed21782142923bb3430b3b938f23d54292094e3a")
	if !bytes.Equal(digest, expectedDigest) {
		return fmt.Errorf("HRK digest verification failed: got %x, want %x", digest, expectedDigest)
	}

	if err := a.verifyHygonCertInfo(a.hrk, 0x03, 0, a.hrk[0x04:0x14]); err != nil {
		return err
	}

View on GitHub (pinned to 6e04ca5ff0)