Skip to content

feat(scwkm): add native ML-KEM wrapping with ml-kem-1024 as default - #15

Merged
euskadi31 merged 1 commit into
mainfrom
feat/scwkm-mlkem-1024
Sep 8, 2026
Merged

euskadi31 merged 1 commit into
mainfrom
feat/scwkm-mlkem-1024

Conversation

@euskadi31

@euskadi31 euskadi31 commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Contexte

Scaleway a ajouté une 4ᵉ classe d'usage key_encapsulation au Key Manager, avec ml_kem_768 et ml_kem_1024, plus deux endpoints WrapKey / UnwrapKey réservés aux clés ML-KEM.

Source Date Contenu
scaleway-sdk-go #3345 2026-09-07 split asymmetric Encryption and key encapsulation
scaleway-sdk-go #3361 2026-09-08 complete doc for mlkem
scaleway-cli #6077 / #6115 2026-08-30 → 09-07 add support for ml_kem / usage.key-encapsulation

Le provider Scaleway peut donc passer de cloud-classical à cloud-pq-native. C'est exactement la primitive qu'il faut pour envelopper un DEK de 32 octets (l'endpoint wrap accepte jusqu'à 2 Ko).

Changements

keymgmt/scwkm

  • ml-kem-1024 / ml-kem-768 mappés sur KeyUsage{KeyEncapsulation}, classe asymmetric_kem
  • CreateKey avec Algorithm vide → scwkm.DefaultAlgorithm = ml-kem-1024
  • PurposeKeyEncapsulation accepté, mais uniquement sur un algo KEM (purpose KEM + clé AES renvoie toujours ErrUnsupportedCapability)
  • SecurityLevel dérivé de la classe de clé : cloud_pq_native pour ML-KEM, cloud_classical pour AES/RSA
  • SupportsPQNatively: true
  • L'algorithme est porté par l'URI de référence via un paramètre alg, pour que le recipient résolu choisisse le chemin de wrapping sans aller-retour API supplémentaire

recipient/scwkm

  • Nouveaux identifiants scwkm+mlkem-768-wrap-v1 et scwkm+mlkem-1024-wrap-v1
  • WrapKey route vers l'endpoint natif pour les clés KEM, garde Encrypt sinon
  • UnwrapKey dispatche sur wk.WrapAlgorithm, pas sur la configuration du recipient

internal/scwkmapiWrapKey / UnwrapKey exposés sur l'interface Client.

Compatibilité

Le module est taggé v1.2.0, l'API publique est préservée :

  • BuildReference garde sa signature ; BuildReferenceWithAlgorithm est purement additif
  • recipient/scwkm.New produit une URI identique à l'octet près (aucun changement de comportement) ; NewWithAlgorithm est le nouveau constructeur explicite
  • Les conteneurs déjà chiffrés en scwkm+encrypt-v1 continuent de se déchiffrer via Decrypt, y compris depuis un recipient ML-KEM — c'est le rôle du dispatch sur l'algorithme stocké
  • Les références existantes sans alg résolvent vers le chemin classique
  • Le format de conteneur stocke type / capacité / algo de wrap en chaînes libres : pas de bump de version de format

Dépendance

ML-KEM est arrivé sur la branche main du SDK après le tag v1.0.0-beta.37 (31 juillet), donc go.mod épingle une pseudo-version de cette branche. Le diff beta.37 → main sur key_manager/v1alpha1 est purement additif : 11 déclarations ajoutées, 0 supprimée, 0 modifiée. Le retour à un tag stable est suivi dans docs/roadmap.md.

Point d'attention à l'usage

Le profil local-pq (défaut de document/field) continue de refuser les recipients cloud-pq-native : il affirme que la clé privée ne quitte jamais l'hôte, ce qu'une clé ML-KEM détenue par le KMS ne satisfait pas. Les recipients Scaleway ML-KEM utilisent cloud-balanced — documenté dans docs/backends/scaleway-kms.md.

Second point : alg fait partie de l'URI, donc du keyRef comparé à l'unwrap. Il faut persister la KeyReference renvoyée par le manager plutôt que la reconstruire à la main.

Tests

go test -race -timeout 300s ./... vert sur les 27 paquets. Nouveaux tests : algo par défaut, ML-KEM-768 + purpose encapsulation, mapping usage↔algo dans les deux sens, aller-retour d'URI avec alg et rejet d'un alg inconnu, round-trip wrap/unwrap ML-KEM mocké, dispatch legacy encrypt-v1 depuis un recipient KEM, mapping d'erreurs SDK, résolution de référence côté resolver.

golangci-lint : la factorisation de la map de métadonnées de recipient/scwkm fait tomber 4 des 5 findings goconst préexistants. Le dernier (recipient/localmlkem/localmlkem.go:161) est préexistant et hors périmètre.

Scaleway Key Manager gained a `key_encapsulation` usage (`ml_kem_768`,
`ml_kem_1024`) along with the `WrapKey`/`UnwrapKey` endpoints, so the
Scaleway backend can now wrap DEKs with a post-quantum KEM instead of
classical RSA/AES only.

- keymgmt/scwkm: map ML-KEM algorithms to the new key usage, default
  CreateKey to ml-kem-1024 when no algorithm is pinned, accept
  PurposeKeyEncapsulation for KEM algorithms only, derive SecurityLevel
  from the key class (cloud_pq_native vs cloud_classical) and report
  SupportsPQNatively.
- keymgmt/scwkm: carry the algorithm in the reference URI via a new
  `alg` parameter so a resolved recipient picks the wrapping path with
  no extra API round trip. BuildReference keeps its signature; the new
  BuildReferenceWithAlgorithm is additive.
- recipient/scwkm: add the scwkm+mlkem-{768,1024}-wrap-v1 identifiers,
  route WrapKey through the native endpoint for KEM keys, and dispatch
  UnwrapKey on the stored wrap algorithm so containers wrapped before
  this change keep resolving through Decrypt.
- internal/scwkmapi: expose WrapKey/UnwrapKey on the client interface.

ML-KEM landed on the SDK main branch after v1.0.0-beta.37 was tagged,
so go.mod pins a pseudo-version of that branch until v1.0.0-beta.38
ships. The diff against beta.37 is purely additive.

The local-pq profile still rejects cloud-pq-native recipients: it
asserts the private key never leaves the host, which a KMS-held ML-KEM
key does not satisfy. Scaleway ML-KEM recipients use cloud-balanced,
which is documented in docs/backends/scaleway-kms.md.

Claude-Session: https://claude.ai/code/session_01K5VTFstSmgvcXMZq5My3Fy
@euskadi31
euskadi31 merged commit a592171 into main Sep 8, 2026
1 check passed
@euskadi31
euskadi31 deleted the feat/scwkm-mlkem-1024 branch September 8, 2026 21:51
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.

1 participant