Skip to content

Add Experimental Post-Quantum Cryptography (MLDSA) Support to Tekton Chains Signing Workflow #1367

@jkhelil

Description

@jkhelil

Background
Quantum computers are expected to become powerful enough to break currently used cryptographic algorithms within the next few decades. Post-quantum cryptography (PQC) aims to address this challenge by introducing cryptographic algorithms that are secure against both classical and quantum computers.
The Commercial National Security Algorithm Suite 2.0 (CNSA 2.0), released by the NSA, mandates PQC support—covering both signatures and key exchanges—for web and cloud systems by the end of 2025.

In our context, this ongoing experimentation with Tekton Chains aims to evaluate the tool’s capabilities and identify the necessary changes required to support post-quantum cryptographic primitives.

Experiment Context & Standards
As of August 2024, NIST has finalized its first PQC standards:

  • FIPS 203 (ML-KEM): Key encapsulation for securing information over public networks.
  • FIPS 204 (ML-DSA): Digital signatures for identity authentication.
  • FIPS 205 (SLH-DSA): Stateless hash-based signatures.

OpenSSL 3.5.0, released on April 8, 2025, as an LTS version, introduces native support for PQC.
In this experiment, we use an MLDSA65 private key generated via OpenSSL 3.5.0.

Go Ecosystem Support

For signing using the MLDSA key, we rely on Cloudflare’s CIRCL library:
https://pkg.go.dev/github.com/cloudflare/circl@v1.6.1
This is used only for experimental evaluation, as using non-standard crypto libraries in production Go code can be problematic.

Steps

  1. Install and Configure Tekton Chains, Guide followed:
    https://gist.github.com/lcarva/f04ab77ad1e6685c61feb1d1da3eb6d8
  2. Generate MLDSA65 Private Key
    Using OpenQuantumSafe’s OpenSSL Docker image:
docker pull openquantumsafe/oqs-ossl3
docker run --rm -v "$PWD":/keys openquantumsafe/oqs-ossl3 /bin/sh -c "
  openssl genpkey -algorithm mldsa65 -out /keys/mldsa65.pem && \
  openssl pkey -in /keys/mldsa65.pem -pubout -out /keys/mldsa65-pub.pem
"

  1. Replace Classic Signing Secret with MLDSA Key
kubectl delete secret signing-secrets -n tekton-chains
kubectl create secret generic signing-secrets \
  --from-file=x509.pem.pub=mldsa65-pub.pem \
  --from-file=x509.pem=mldsa65.pem \
  -n tekton-chains
  1. Trigger a PipelineRun for Signing
kubectl apply -k minimal-container/tekton

tkn pipeline start simple-build \
  --param git-repo=https://github.com/jkhelil/minimal-container \
  --param git-revision=main \
  --param output-image=quay.io/jkhelil/minimal-container-pqc \
  --workspace name=shared,pvc,claimName="tekton-build" \
  --showlog

Issues
During the initial iteration process, I encountered several challenges that impacted the implementation. These issues surfaced early as we began integrating MLDSA into the signing workflow, highlighting gaps in compatibility, tooling, and existing cryptographic support.

Issue 1: MLDSA Key Not Recognized by Go's crypto/x509

{
  "level":"warn",
  "ts":"2025-06-03T06:12:35.857Z",
  "logger":"watcher",
  "caller":"chains/signing.go:75",
  "msg":"error configuring x509 signer: x509: PKCS#8 wrapping contained private key with unknown algorithm: 2.16.840.1.101.3.4.3.18"
}

Explanation

  • OpenSSL generates MLDSA keys in PKCS#8 format.
  • Go’s crypto/x509 package doesn’t recognize the MLDSA algorithm OID.
  • This leads to the error: x509: PKCS#8 wrapping contained private key with unknown algorithm: 2.16.840.1.101.3.4.3.18
    2.16.840.1.101.3.4.3.18 is OID (Object Identifier) assigned to ML-DSA-65

Fix

Issue 2: SSH Key Compatibility Error
After resolving PKCS#8 parsing, a new error occurred:

{
  "level":"error",
  "ts":"2025-06-03T11:48:31.368Z",
  "logger":"watcher",
  "caller":"taskrun/reconciler.go:295",
  "msg":"Returned an error",
  "error":"ssh: unsupported key type *mldsa65.PublicKey"
}

Explanation:

  • Somewhere in the Tekton Chains codebase, ssh.NewPublicKey(pub) is used for generating a key fingerprint.
  • However, the SSH package does not support MLDSA keys, leading to the error: ssh: unsupported key type *mldsa65.PublicKey

In the current implementation (e.g., wrap.go), the Wrap function handles:

  • Key Fingerprinting: Uses ssh.NewPublicKey(pub) and ssh.FingerprintSHA256(...) Works for RSA, ECDSA, etc.
  • Envelope Signing: Wraps the signer in a DSSE (Dead Simple Signing Envelope)

The SSH conversion was originally used because:

  • SSH has a well-established fingerprinting format
  • Most cryptographic keys used in Tekton (RSA, ECDSA, etc.) are compatible with SSH
  • The fingerprint provides a consistent way to identify keys across different formats
    However, this caused issues with MLDSA because:
  • MLDSA is a new post-quantum algorithm
  • The SSH package doesn't support MLDSA keys
  • There's no built-in way to convert MLDSA keys to SSH format

Fix

  • We introduced changes to decouple key fingerprinting from SSH:
  • Created a keyFingerprinter interface to abstract fingerprint generation.
  • Implemented custom fingerprint logic for MLDSA.
  • Implemented proper MLDSA signing using mldsa65.SignTo
  • Added SignWithOpts method to implement the crypto.Signer interface

After these changes,
I retried the signing process, and it completed successfully.
I was then able to download the attestation using the following command:

cosign download attestation quay.io/jkhelil/minimal-container-pqc > att.json

Summary of the changes

  • Introduced MLDSA parsing and signing support.
  • Decoupled fingerprinting from SSH dependency using a new interface.
  • Experiment supporting post-quantum cryptographic keys, specifically MLDSA65 on tekton chains

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions