OpenNHP/opennhp · error

failed to download HRK

Error message

failed to download HRK: %v

What it means

verifyCertChain downloads the Hygon Root Key (HRK) from https://cert.hygon.cn/hrk on first use; this error wraps any transport-level failure of that http.Get (DNS failure, connection refused, TLS error, timeout). It means the verifier could not reach Hygon's certificate server at all, so no network response was obtained.

Solutions

  1. Check network connectivity: curl -v https://cert.hygon.cn/hrk from the host running the verifier.
  2. Configure proxy environment variables (HTTPS_PROXY) if the environment routes egress through a proxy.
  3. Pre-populate the HRK (set a.hrk) or cache it locally so the verifier does not need to fetch it at verification time.
  4. Add a retry with timeout around the fetch, since transient network failures abort the whole attestation.
  5. If the domain is unreachable permanently, pin the HRK blob locally after authenticating it against the known digest.

Example fix

// before: single blocking fetch, no timeout
resp, err := http.Get("https://cert.hygon.cn/hrk")
// after: client with timeout + load HRK from local cache/fallback
client := &http.Client{Timeout: 15 * time.Second}
resp, err := client.Get("https://cert.hygon.cn/hrk")
if err != nil {
	hrk, ferr := os.ReadFile(hrkCachePath)
	if ferr != nil {
		return fmt.Errorf("failed to download HRK: %v", err)
	}
	a.hrk = hrk
}
Defensive patterns

Strategy: retry

Validate before calling

// check reachability before attestation
resp, err := http.Head("https://cert.hygon.cn/hrk")
if err != nil {
	log.Printf("Hygon cert server unreachable: %v — will need pinned HRK", err)
}

Try / catch

if err := att.Verify(chipId); err != nil {
	if strings.Contains(err.Error(), "failed to download HRK") {
		// offline fallback: load pinned HRK and retry
		hrk, ferr := os.ReadFile("/etc/nhp/hrk.bin")
		if ferr == nil {
			att.HRK = hrk
			return att.Verify(chipId)
		}
	}
	return err
}

Prevention

When it happens

Trigger: First call to verifyCertChain when a.hrk is nil and http.Get("https://cert.hygon.cn/hrk") returns a non-nil error: offline machine, DNS resolution failure, blocked egress (firewall/proxy), TLS interception, or the host being unreachable.

Common situations: Running in an air-gapped/private datacenter without egress to cert.hygon.cn; corporate proxy required but not configured (HTTPS_PROXY unset); China-CDN connectivity issues from other regions; DNS misconfiguration in containers.

Related errors


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

Appendix: source

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

		Y:     yBig,
	}

	rBig := new(big.Int).SetBytes(r)
	sBig := new(big.Int).SetBytes(s)

	if VerifySignature(pubKey, msgAllDigest, rBig, sBig) {
		return nil
	} else {
		return fmt.Errorf("failed to verify signature")
	}
}

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 {

View on GitHub (pinned to 6e04ca5ff0)