p2w34 / e-democracy

MIT License
1 stars 1 forks source link

Dodaj weryfikację Podpisu Zaufanego dla petycji #2

Open p2w34 opened 5 months ago

p2w34 commented 5 months ago

Jednostki administracji publicznej mają możliwość integracji z serwerami oferującymi endpoint'y do operacji związanych z podpisem zaufanym. My takiej możliwości nie posiadamy, stąd weryfikacja musi być "offline".

Kancelaria Sejmu nie weryfikuje czy petycje są Podpisane Podpisem zaufanym. Weryfikacja ta jest dla nas samych, aby się upewnić, że nadesłane do nas petycje są poprawnie podpisane - stanowić do będzie dodatkowy dowód, że idea używania Podpisów Zaufanego ma jak najbardziej rację bytu.

Idealnie, aby użyć node.js'a jak reszta kodu, natomiast nic nie stoi na przeszkodzie, aby było to w innej technologii.

Format podpisanych plików: .xml. Format ten został wybrany dlatego, że łatwo jest wyekstraktować oryginalny dokument. W przypadku plików .pdf wydaje się to bardzo trudne.

p2w34 commented 5 months ago

Próba weryfikacji podpisu za pomocą xml-crypto kończy się niepowodzeniem. Certyfikat ściągam z ministerstwo cyfryzacji. Postępując wedle instrukcji z readme otrzymuję rezultat poniżej. Wypada sprawdzić inne podejścia/biblioteki.

const fs = require("fs");
const { DOMParser } = require("@xmldom/xmldom");
const xmlCrypto = require("xml-crypto");
const SignedXml = xmlCrypto.SignedXml;
const xpath = require("xpath");

var xml = fs.readFileSync("petycja_20240203_aecfen.pdf.xml").toString();
var doc = new DOMParser().parseFromString(xml);

var signature = xpath.select("//*[local-name(.)='Signature' and namespace-uri(.)='http://www.w3.org/2000/09/xmldsig#']", doc)[0];
var sig = new SignedXml({ publicCert: fs.readFileSync("/Users/myuser/Downloads/PL_CSCA_2022.pem") });

sig.loadSignature(signature.toString()); 
try {
  var res = sig.checkSignature(xml);
  if (res) {
    console.log("Podpis jest ważny.");
  } else {
    console.log("Podpis jest nieprawidłowy.");
    console.log(sig.validationErrors);
  }
} catch (ex) {
  console.log(ex);
}

otrzymujemy:

Error: canonicalization algorithm 'http://www.w3.org/TR/1999/REC-xpath-19991116' is not supported
    at SignedXml.findCanonicalizationAlgorithm (/Users/myuser/VSCodeProjects/test/node_modules/xml-crypto/lib/signed-xml.js:266:15)
    at /Users/myuser/VSCodeProjects/test/node_modules/xml-crypto/lib/signed-xml.js:708:40
    at Array.forEach (<anonymous>)
    at SignedXml.getCanonXml (/Users/myuser/VSCodeProjects/test/node_modules/xml-crypto/lib/signed-xml.js:705:20)
    at SignedXml.getCanonReferenceXml (/Users/myuser/VSCodeProjects/test/node_modules/xml-crypto/lib/signed-xml.js:232:21)
    at SignedXml.validateReference (/Users/myuser/VSCodeProjects/test/node_modules/xml-crypto/lib/signed-xml.js:345:31)
    at /Users/myuser/VSCodeProjects/test/node_modules/xml-crypto/lib/signed-xml.js:170:55
    at Array.every (<anonymous>)
    at SignedXml.checkSignature (/Users/myuser/VSCodeProjects/test/node_modules/xml-crypto/lib/signed-xml.js:170:35)
    at Object.<anonymous> (/Users/myuser/VSCodeProjects/test/test.js:17:17) {stack: 'Error: canonicalization algorithm 'http://www…myuser/VSCodeProjects/test/test.js:17:17)', message: 'canonicalization algorithm 'http://www.w3.or…TR/1999/REC-xpath-19991116' is not supported'}
Kasztan404 commented 1 month ago

alternatywnie widzę, że działa API POST na: https://puesc.gov.pl/wer/api

json:

{
    "action": "verFile",
    "file": "xml zakodowany w Base64",
    "file_name": "nazwaPliku.xml"
}
p2w34 commented 1 month ago

alternatywnie widzę, że działa API POST na: https://puesc.gov.pl/wer/api

json:

{
    "action": "verFile",
    "file": "xml zakodowany w Base64",
    "file_name": "nazwaPliku.xml"
}

Ciekawe. Chociaż na: https://puesc.gov.pl/uslugi/zweryfikuj-podpis-elektroniczny można przeczytać, że "Usługa nie może być używana do zautomatyzowanych walidacji podpisów."

Najprostsze wydaje się użycie gotowych bibliotek - mi bezproblemowo zadziałały te od chilkata (https://tools.chilkat.io/xmlDsigVerify.cshtml -> wkleić dokument a następnie wybrać język, ja poszedłem w javę). Nie jest to jednak tania sprawa - 300$ per developer (+upgrade'y przez rok).

Jestem pewien, że da się to zakodować samemu, jako że kroki które trzeba wykonać podczas walidacji są zestandaryzowane. W ostateczności można ją zrobić nie wtedy kiedy użytkownik uploaduje dokument, ale potem gdzieś w tle. Jakbym istniała taka działająca platforma i miała użytkowników, to i czas by się znalazł, żeby się z tym uporać.