Skip to content

Fix P-521 ECDSA verification and add curve coverage tests#1956

Open
nadahalli wants to merge 3 commits intomainfrom
tejaswi/fix-ecdsa-verify
Open

Fix P-521 ECDSA verification and add curve coverage tests#1956
nadahalli wants to merge 3 commits intomainfrom
tejaswi/fix-ecdsa-verify

Conversation

@nadahalli
Copy link
Copy Markdown
Contributor

Summary

  • Fix hashForCurve matching "P-512" instead of "P-521", which made the P-521 code path unreachable
  • Fix verifyECDSASignature using hash length to size signature components; P-521 COSE signatures use 66-byte components (ceil(521/8)), not 64 (SHA-512 digest size). Component size is now derived from the curve order via curveKeySize
  • Add verify_test.go with sign/verify roundtrips for all four NIST curves (P-224, P-256, P-384, P-521), negative tests (wrong key, wrong payload, tampered signature, wrong length, DER encoding rejected), and a targeted regression test proving P-521 key size != hash size

hashForCurve matched "P-512" instead of "P-521", making the P-521 path
unreachable. verifyECDSASignature used hash length (64 for SHA-512) to
determine signature component size, but P-521 COSE signatures use 66-byte
components (ceil(521/8)). Derive component size from the curve order instead.

Add verify_test.go with sign/verify roundtrips for all four NIST curves,
rejection tests (wrong key, wrong payload, tampered sig, wrong length,
DER format), and an explicit test proving P-521 key size != hash size.
@nadahalli nadahalli requested a review from a team as a code owner April 2, 2026 11:48
Copilot AI review requested due to automatic review settings April 2, 2026 11:48
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

👋 nadahalli, thanks for creating this pull request!

To help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team.

Once you're ready, you can mark it as "Ready for review" to request feedback. Thanks!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

📊 API Diff Results

No changes detected for module github.com/smartcontractkit/chainlink-common

View full report

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes ECDSA COSE signature verification for P-521 keys in the Nitro attestation verifier by correctly selecting the P-521 hash path and by sizing COSE signature components based on curve bit size (r||s component width), not hash digest length. It also adds a dedicated test suite to prevent regressions across supported NIST curves.

Changes:

  • Fix hashForCurve to match "P-521" (previously "P-512"), making the P-521 branch reachable.
  • Fix verifyECDSASignature to split COSE signatures using ceil(curveBitSize/8) component sizing (not len(hash)), rejecting incorrect signature lengths early.
  • Add verify_test.go with roundtrip and negative tests across P-224/P-256/P-384/P-521 plus a targeted P-521 regression.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
pkg/teeattestation/nitro/verify.go Corrects curve/hash selection for P-521 and fixes COSE ECDSA signature component sizing based on curve bit size.
pkg/teeattestation/nitro/verify_test.go Adds comprehensive curve coverage and regression tests for COSE ECDSA verification, including P-521 sizing edge case.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

r, s, err := ecdsa.Sign(rand.Reader, key, hash)
require.NoError(t, err)

keySize := (key.Curve.Params().BitSize + 7) / 8
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coseSign re-computes the COSE component size with (key.Curve.Params().BitSize + 7) / 8, duplicating the production helper curveKeySize. To avoid divergence if sizing logic changes again, consider calling curveKeySize(&key.PublicKey) here (or factoring a shared helper used by both prod + tests).

Suggested change
keySize := (key.Curve.Params().BitSize + 7) / 8
keySize := curveKeySize(&key.PublicKey)

Copilot uses AI. Check for mistakes.
Comment on lines +229 to +236
// marshalDER produces a minimal ASN.1 DER encoding of an ECDSA signature.
func marshalDER(r, s *big.Int) []byte {
encodeInt := func(v *big.Int) []byte {
b := v.Bytes()
if len(b) > 0 && b[0]&0x80 != 0 {
b = append([]byte{0x00}, b...)
}
return append([]byte{0x02, byte(len(b))}, b...)
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test builds a DER-encoded signature via a custom marshalDER implementation. Since the Go stdlib already supports DER ECDSA signatures (e.g., ecdsa.SignASN1 / asn1.Marshal), using that would simplify the test and reduce the chance of subtle DER encoding bugs (length handling, INTEGER=0 edge cases, etc.).

Copilot uses AI. Check for mistakes.
Verify the ECDSA signature pipeline (CBOR parse, Sig_structure build,
verifyECDSASignature) against official test vectors from the COSE Working
Group Examples repository (normative suite for RFC 9052/9053):

- ES256: RFC 8152 Appendix C.2.1 (sign-pass-03)
- ES384: ecdsa-sig-02
- ES512: ecdsa-sig-03 (exercises the P-521 fix from previous commit)
- Tampered payload: sign-fail-02
- Modified protected header: sign-fail-06
- Wrong key: valid ES256 vector verified with P-384 key
Comment on lines +223 to +224
// curveKeySize returns the byte length of one ECDSA signature component
// (r or s) for the given curve: ceil(bitSize / 8). This is the correct
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: maybe do float division -> ciel -> cast to int in case this helper is ever required for other curves with odd bit sizes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants