💡 Pełny działający przykład dostępny na GitHubie:
sign-word-with-ml-dsa-certificates-dotnet
Stara metoda była planem projektu
Zapytaj, co jest potrzebne, aby uczynić podpisywanie dokumentów odpornym na komputery kwantowe, a otrzymasz plan działania: ocenić algorytmy, wybrać bibliotekę, napisać warstwę abstrakcji nad kodem podpisu, zaplanować okres podwójnego podpisywania, przydzielić budżet na kwartał.
Większość z tego nadal dotyczy części organizacyjnej – pozyskiwania certyfikatów, polityki, wsparcia walidatorów. Część kodowa okazała się mniejsza niż sugeruje plan, co warto wiedzieć, zanim ktoś przydzieli na to kwartał budżetu.
Podpisywanie ML-DSA jest funkcją GroupDocs.Signature dla .NET, która podpisuje dokumenty Word certyfikatami opartymi na FIPS 204, standardzie podpisów post‑kwantowych NIST. Pojawiło się w wersji 26.9 i z perspektywy wywołującego kodu jest to inny plik PFX.
Istnieje lepszy sposób
Here is the whole of the code change:
using var signature = new Signature(sourcePath);
var options = new DigitalSignOptions(pfxPath)
{
Password = certificatePassword
};
SignResult result = signature.Sign(outputPath, options);
To jest to samo wywołanie używane dla certyfikatu RSA. Algorytm jest właściwością certyfikatu, więc nie ma opcji go wybierającej, nie jest potrzebna warstwa abstrakcji i nie pojawia się druga ścieżka kodu na okres przejściowy. Wskaż DigitalSignOptions na plik PFX ML-DSA, a wynik będzie podpisem ML-DSA.
Odczytanie certyfikatu z wyniku jest warte wykonania, gdy w grze jest kilka certyfikatów:
var created = result.Succeeded.OfType<DigitalSignature>().FirstOrDefault();
return created?.Certificate?.Subject ?? "(no certificate returned)";
Wybór poziomu, z liczbami zamiast opinii
ML-DSA występuje w trzech zestawach parametrów, odpowiadających kategoriom bezpieczeństwa NIST 2, 3 i 5. Silniejszy oznacza większy – zarówno klucz, jak i podpis – a rozsądny sposób podjęcia decyzji to podpisanie własnego dokumentu trzykrotnie i obserwacja:
var levels = new Dictionary<string, string>
{
["ML-DSA-44"] = MlDsa44Pfx,
["ML-DSA-65"] = MlDsa65Pfx,
["ML-DSA-87"] = MlDsa87Pfx
};
Przykład zapisuje jedną podpisaną kopię dla każdego poziomu i rejestruje jej rozmiar, więc kompromis jest pomiarem, a nie tabelą ze specyfikacji. Dla pojedynczego kontraktu różnica jest nieistotna; dla archiwum kilku milionów podpisanych dokumentów jest to kwestia pojemności, którą warto rozważyć przed standaryzacją na najwyższym poziomie.
ML-DSA-65 jest rozsądnym domyślnym wyborem, gdy żadna polityka nie określa innego. Profile takie jak CNSA 2.0 wymieniają wyraźnie ML-DSA-87, a ML-DSA-44 ma sens tylko wtedy, gdy rozmiar jest ważniejszy niż margines.
Weryfikacja wymaga tylko publicznego certyfikatu
Historia dystrybucji nie zmieniła się w porównaniu do RSA, co jest drugą dobrą wiadomością:
var options = new DigitalVerifyOptions(certificatePath);
if (password != null)
{
options.Password = password;
}
VerificationResult result = signature.Verify(options);
Odbiorca potrzebuje jedynie pliku .cer podpisującego i nic więcej. Wynik jest ważny tylko wtedy, gdy podpis zgadza się z treścią, a certyfikat pasuje pod numerem seryjnym i odciskiem palca, więc dokument podpisany przez inną stronę nie przejdzie weryfikacji – co przykład udowadnia, uruchamiając weryfikację dwukrotnie, raz z prawidłowym certyfikatem i raz z certyfikatem innej osoby.
Obok siebie: Oczekiwane vs. Rzeczywiste
| Co zakłada plan migracji | Co wymaga rzeczywiście 26.9 | |
|---|---|---|
| Zmiana kodu | warstwa abstrakcji nad podpisywaniem | inny ścieżka PFX |
| Powierzchnia API | nowe metody post‑kwantowe | DigitalSignOptions, niezmienione |
| Wybór poziomu | konfiguracja biblioteki | który certyfikat załadujesz |
| Weryfikacja | nowe narzędzia dla odbiorców | publiczny .cer podpisującego |
| Praca platformowa | obsługa kluczy per system operacyjny | brak – biblioteka wewnętrznie przełącza się |
| Obsługa formatów | wszystkie formaty | tylko formaty Word, na razie |
Ostatni wiersz jest tym, który ogranicza planowanie i prowadzi do szczerej części tego artykułu.
Co jeszcze nie działa
Dwa ograniczenia, które warto znać, zanim cokolwiek obiecasz.
Obsługa formatów w wersji 26.9 obejmuje tylko Word – DOCX, DOC, ODT i pozostałe formaty rodziny Word. PDF, arkusze kalkulacyjne i prezentacje nie mogą być podpisane przy użyciu ML-DSA. Dla pipeline’u skoncentrowanego na PDF ta wersja jest przeznaczona do prototypowania i pomiarów, a nie migracji.
Wsparcie walidatorów to drugie ograniczenie. Nie istnieje jeszcze standardowy identyfikator XML‑DSig dla ML-DSA, więc Microsoft Word może nie zgłaszać podpisu jako ważnego, mimo że jest kryptograficznie poprawny i weryfikuje się prawidłowo przez API. To luka w standardach, a nie wada, i oznacza, że weryfikacja powinna znajdować się w Twoim kodzie, a nie w recenzencie otwierającym plik i patrzącym na baner.
Istnieje także szczegół platformowy, który nie wymaga działania: .NET nie może odczytać kluczy ML-DSA wszędzie, w tym na Linuksie w .NET 8. Tam, gdzie nie może, GroupDocs.Signature odczytuje certyfikat przez silnik Word, więc ta sama kompilacja działa na laptopie dewelopera i w kontenerze Linux bez kodu warunkowego.
Czy warto to zrobić teraz, biorąc pod uwagę te ograniczenia?
Tak, z dwóch powodów niezwiązanych z kodem. Pozyskiwanie certyfikatów jest wolne – publiczne CA wciąż wprowadzają wydawanie ML-DSA – więc prace po stronie organizacji zyskują na wczesnym rozpoczęciu. A pytanie „czy możemy dziś wygenerować podpis post‑kwantowy” jest zadawane coraz częściej przez zespoły ds. zgodności; możliwość odpowiedzi podpisanym dokumentem zamiast planem jest warta popołudnia potrzebnego na to.
Co próbka faktycznie udowadnia
Cztery metody, uruchamiane kolejno, z kodem wyjścia powiązanym z wynikiem. Podpisuje kontrakt przy użyciu ML-DSA-65 i wypisuje temat użytego certyfikatu. Podpisuje ten sam kontrakt na wszystkich trzech poziomach i wypisuje uzyskane rozmiary. Weryfikuje podpisany plik dwukrotnie – raz z publicznym certyfikatem podpisującego, oczekując sukcesu, i raz z certyfikatem innego podpisującego, oczekując niepowodzenia. Następnie wymienia cyfrowe podpisy znalezione w wyniku.
Druga weryfikacja jest tą, którą warto skopiować. Procedura, której jedynie podano prawidłowe dane wejściowe, nie mówi nic o tym, czy odrzuci nieprawidłowe, a w przypadku podpisów to jest cała kwestia.
Przykład z rzeczywistości: Trzydziestoletni kontrakt
Archiwa o długim okresie przechowywania to miejsce, w którym przestaje to być teoretyczne. Kontrakt podpisany dziś i przechowywany przez trzydzieści lat musi pozostać weryfikowalny, niezależnie od zmian w kryptografii w tym okresie, a „zbieraj teraz, odszyfruj później” jest udokumentowanym modelem zagrożenia dla takiego materiału.
Dla takiego archiwum praktycznym działaniem już dziś jest podwójna ścieżka: zachować RSA dla formatów, które ML-DSA jeszcze nie obsługuje, rozpocząć podpisywanie wyjścia Word przy użyciu ML-DSA-65 lub 87 oraz rejestrować, który algorytm został użyty dla każdego dokumentu, aby przyszły audyt mógł je odróżnić bez otwierania plików.
Jedna rzecz do naprawienia w próbce przed jej skopiowaniem
Repozytorium dostarcza samopodpisane certyfikaty ML-DSA, więc demonstracja działa od razu, co oznacza cztery pliki PFX i zakodowane na stałe hasło w documents/. Dla jednorazowego certyfikatu testowego ważnego tylko w ramach tego przykładu jest to w porządku.
Nie jest to wzorzec, który powinno się przenosić do własnego repozytorium. Zamiast tego generuj certyfikaty testowe w czasie wykonywania, tak jak robi to przykład certyfikat‑validity GroupDocs, lub trzymaj je całkowicie poza kontrolą wersji. Zatwierdzony klucz jest trudny do odwołania i ma tendencję do przetrwania demonstracji, dla której został napisany.
Wnioski
Drogi elementy migracji post‑kwantowej to certyfikaty, polityka i walidatory. Kod, przynajmniej dla dokumentów Word w .NET, to inny plik PFX i to samo wywołanie DigitalSignOptions. Sklonuj przykład, skieruj go na jeden ze swoich kontraktów i w ciągu kilku minut będziesz mieć trzy podpisane pliki, dwa wyniki weryfikacji oraz porównanie rozmiarów – co stanowi lepszą podstawę planu migracji niż szacunek.