apiVersion: jenkins.io/v1 kind: PipelineActivity metadata: annotations: lighthouse.jenkins-x.io/cloneURI: https://github.com/greencapitaltrade/deadpool.git lighthouse.jenkins-x.io/job: release pipeline.jenkins-x.io/traceID: b7cce9f78cf4895c7b0859b1365c723f creationTimestamp: "2026-05-16T20:15:35Z" generation: 8 labels: branch: main build: "28" context: release created-by-lighthouse: "true" event-GUID: dafba3f6-5163-11f1-9f3f-2e145bef2cfd lighthouse.jenkins-x.io/baseSHA: 8375ff69eae7af8a218b99a16a13a6007c0f5b4d lighthouse.jenkins-x.io/branch: main lighthouse.jenkins-x.io/buildNum: "1778962535297" lighthouse.jenkins-x.io/context: release lighthouse.jenkins-x.io/id: pitaltrade-deadpool-main-release-v5kff lighthouse.jenkins-x.io/job: release lighthouse.jenkins-x.io/lastCommitSHA: 8375ff69eae7af8a218b99a16a13a6007c0f5b4d lighthouse.jenkins-x.io/refs.org: greencapitaltrade lighthouse.jenkins-x.io/refs.repo: deadpool lighthouse.jenkins-x.io/type: postsubmit owner: greencapitaltrade podName: pitaltrade-deadpool-main-release-ccjjd-from-build-pack-pod provider: github repository: deadpool tekton.dev/pipeline: pitaltrade-deadpool-main-release-ccjjd managedFields: - apiVersion: jenkins.io/v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:labels: f:branch: {} f:context: {} f:owner: {} f:provider: {} f:repository: {} f:spec: f:lastCommitMessage: {} f:releaseNotesURL: {} f:version: {} manager: jx-changelog-0.10.18 operation: Update time: "2026-05-16T20:23:06Z" - apiVersion: jenkins.io/v1 fieldsType: FieldsV1 fieldsV1: f:metadata: f:annotations: .: {} f:lighthouse.jenkins-x.io/cloneURI: {} f:lighthouse.jenkins-x.io/job: {} f:pipeline.jenkins-x.io/traceID: {} f:labels: .: {} f:build: {} f:created-by-lighthouse: {} f:event-GUID: {} f:lighthouse.jenkins-x.io/baseSHA: {} f:lighthouse.jenkins-x.io/branch: {} f:lighthouse.jenkins-x.io/buildNum: {} f:lighthouse.jenkins-x.io/context: {} f:lighthouse.jenkins-x.io/id: {} f:lighthouse.jenkins-x.io/job: {} f:lighthouse.jenkins-x.io/lastCommitSHA: {} f:lighthouse.jenkins-x.io/refs.org: {} f:lighthouse.jenkins-x.io/refs.repo: {} f:lighthouse.jenkins-x.io/type: {} f:podName: {} f:tekton.dev/pipeline: {} f:spec: .: {} f:baseSHA: {} f:batchPipelineActivity: {} f:build: {} f:buildLogsUrl: {} f:completedTimestamp: {} f:context: {} f:gitBranch: {} f:gitOwner: {} f:gitRepository: {} f:gitUrl: {} f:lastCommitSHA: {} f:message: {} f:pipeline: {} f:startedTimestamp: {} f:status: {} f:steps: {} manager: jx-build-controller operation: Update time: "2026-05-16T20:23:50Z" name: greencapitaltrade-deadpool-main-28 namespace: jx resourceVersion: "24885868" uid: 1e3464ad-1200-457a-9ee1-41c73ee7cb09 spec: baseSHA: 8375ff69eae7af8a218b99a16a13a6007c0f5b4d batchPipelineActivity: {} build: "28" buildLogsUrl: s3://logs-gct-prod-20260425045301534100000007/jenkins-x/logs/greencapitaltrade/deadpool/main/28.log completedTimestamp: "2026-05-16T20:23:44Z" context: release gitBranch: main gitOwner: greencapitaltrade gitRepository: deadpool gitUrl: https://github.com/greencapitaltrade/deadpool.git lastCommitMessage: |- feat(crypto): migrate Ed25519 → ECDSA P-256 (#37) * feat(crypto): migrate Ed25519 → ECDSA P-256 (signers + verifier) Companion to wasp PR #5 — the production secure element only supports the NIST P-256 curve, not Ed25519. Hard cutover, no backwards-compat: per Amit there is no deployed Ed25519 fleet to preserve. What changed: Dependencies - ed25519-dalek 2.1 → p256 0.13 + ecdsa 0.16 + sha2 0.10 All RustCrypto pure-Rust crates — no new C/openssl deps. Build adds ~30s on a clean cache. Signing path Both signers (server_cmd_signer = capability-token, command_signer = legacy 11+N Terra) now produce: - hash: SHA-256(message), explicit prehash - sign: P-256 ECDSA, raw r||s, 64 bytes big-endian - key: 32-byte big-endian scalar from VC_SERVER_CMD_PRIV_KEY_HEX / TERRA_SIGNING_KEY (same hex shape as before — only the scalar interpretation changes from Ed25519 seed to P-256 private value) Frame size unchanged: signature slot is still 64 B, so the 92+N capability-token frame is byte-identical to the Ed25519 layout. Verifier (test-only) verify_frame() uses p256's VerifyingKey + verify_prehash to match what micro-ecc does device-side. Wire encoding (raw r||s, raw X||Y) is the contract that lets both ends agree without a DER detour. Public key encoding Public keys travel as 64 B raw X||Y — same as the firmware embeds in server_root_key.c and the capability-token wire. Internally we wrap to 0x04||X||Y when calling p256's VerifyingKey::from_sec1_bytes, but that prefix never crosses the wire. Tests (20/20 pass, `cargo test -p iot-common --lib server_cmd_signer`): - frame layout (header offsets, params length, pin_proof zeros) - sign + verify round-trip (matching key) - tampered params / tampered nonce / wrong key rejections - RFC 6979 §A.2.5 deterministic vector (msg="sample"): → byte-identical to the firmware smoke test in wasp/a7677s-firmware/auth/vendor/smoke_test.c → proves both ends agree on raw r||s + SHA-256 prehash + BE scalars - nonce-tracker monotonicity (5 cases) + Redis-key + Lua sanity - env-missing → KeyNotConfigured `cargo build --workspace` clean. Co-Authored-By: Claude Opus 4.7 * test(server_cmd_signer): add ECDSA edge cases (k-determinism, sig-length, roundtrip) Six new tests covering failure modes the RFC 6979 cross-end vector didn't exercise. Each anchored to a real risk: two_signs_with_same_inputs_produce_different_signatures p256 crate uses RFC 6979 *deterministic* k (SafeCurves-recommended) so identical inputs DO produce identical signatures. Asserted explicitly so a future swap to randomised k is a visible test failure, not a silent property change. different_nonce_changes_signature_bytes Even with deterministic k, changing the signed payload must change the signature. Sanity check that the nonce field is inside the SHA-256 input (not skipped by an off-by-one in the frame builder). verify_rejects_signature_of_wrong_length verify_frame splits at frame.len() - SIG_LEN. A frame shorter than SIG_LEN must Err, not panic on the negative split. frame_with_all_zero_signature_rejected Canary against a future bug where the signature slot is left zero (e.g. an early return that skips the sign step). FIPS 186-4 §6.4.1 requires r,s > 0. full_roundtrip_max_params Frame with MAX_PARAMS_LEN params produces a 228-byte signed prefix — well above SHA-256's 64-byte single-block boundary. Verifies the prehash path handles multi-block messages with no length-counter bug. key_loader_rejects_wrong_length_hex SigningKey::from_bytes panics on wrong-length input (typed GenericArray cast). The loader's `if bytes.len() != 32` guard prevents that panic from reaching production. Test asserts the guard is present via source inspection (LazyLock can't be reset mid-process for a behavioural test). Why these and not others: TDD-first would have surfaced exactly these risks (signature contracts, length boundaries, panics on bad input). 26/26 pass via `cargo test -p iot-common --lib server_cmd_signer`. Co-Authored-By: Claude Opus 4.7 --------- Co-authored-by: Claude Opus 4.7 lastCommitSHA: 8375ff69eae7af8a218b99a16a13a6007c0f5b4d message: 'Tasks Completed: 1 (Failed: 0, Cancelled 0), Skipped: 0' pipeline: greencapitaltrade/deadpool/main releaseNotesURL: https://github.com/greencapitaltrade/deadpool/releases/tag/v0.47.0 startedTimestamp: "2026-05-16T20:15:35Z" status: Succeeded steps: - kind: Stage stage: completedTimestamp: "2026-05-16T20:23:44Z" name: from build pack startedTimestamp: "2026-05-16T20:15:47Z" status: Succeeded steps: - completedTimestamp: "2026-05-16T20:15:48Z" name: Git Clone startedTimestamp: "2026-05-16T20:15:47Z" status: Succeeded - completedTimestamp: "2026-05-16T20:15:53Z" name: Next Version startedTimestamp: "2026-05-16T20:15:52Z" status: Succeeded - completedTimestamp: "2026-05-16T20:15:56Z" name: Jx Variables startedTimestamp: "2026-05-16T20:15:54Z" status: Succeeded - completedTimestamp: "2026-05-16T20:22:49Z" name: Build Cargo Install startedTimestamp: "2026-05-16T20:16:08Z" status: Succeeded - completedTimestamp: "2026-05-16T20:22:51Z" name: Check Registry startedTimestamp: "2026-05-16T20:22:49Z" status: Succeeded - completedTimestamp: "2026-05-16T20:22:53Z" name: Build Server Image startedTimestamp: "2026-05-16T20:22:52Z" status: Succeeded - completedTimestamp: "2026-05-16T20:22:54Z" name: Build Consumer Image startedTimestamp: "2026-05-16T20:22:53Z" status: Succeeded - completedTimestamp: "2026-05-16T20:22:56Z" name: Build Mqtt Image startedTimestamp: "2026-05-16T20:22:55Z" status: Succeeded - completedTimestamp: "2026-05-16T20:23:06Z" name: Promote Changelog startedTimestamp: "2026-05-16T20:22:57Z" status: Succeeded - completedTimestamp: "2026-05-16T20:23:10Z" name: Promote Helm Release startedTimestamp: "2026-05-16T20:23:07Z" status: Succeeded - completedTimestamp: "2026-05-16T20:23:44Z" name: Promote Jx Promote startedTimestamp: "2026-05-16T20:23:10Z" status: Succeeded - kind: Promote promote: environment: staging pullRequest: pullRequestURL: https://github.com/greencapitaltrade/mcu/pull/3885 startedTimestamp: "2026-05-16T20:23:27Z" status: Succeeded startedTimestamp: "2026-05-16T20:23:27Z" status: Succeeded - kind: Promote promote: environment: production pullRequest: pullRequestURL: https://github.com/greencapitaltrade/mcu/pull/3886 startedTimestamp: "2026-05-16T20:23:41Z" status: Succeeded startedTimestamp: "2026-05-16T20:23:41Z" status: Succeeded version: 0.47.0 status: {}