Tak pobraną Javę należy zainstalować. Celowo pobrana została wersja x86 64-bit.
Używana przez SecureFile2 biblioteka do obsługi podpisu elektronicznego autorstwa KIR nie ma wersji obsługującej procesory Apple Silicon.
MacOS użyje Rossetta do uruchomienia tej Javy, to podobno działa (ale jedyne jabłuszko, jakie udostępnono mi do testów ma procesor Intela, więc powtarzam jedynie opinie zasłyszane telefonicznie).
NIE ROZPAKOWUJĘ używając narzędzi graficznych (klikając na archiwum).
Mac na którym testowałem, uniemożliwił mi uruchomienie plików jar, które wypakowałem graficznie.
Rozpakowanie
Rozpakowuję z terminala. Terminal otwieram z Launchpada w Docku wpisując term. W terminalu wydaję komendę:
1
cd ~/Downloads/
i jestem witany poniższym zapytaniem, które zatwierdzam OK.
następnie rozpakowuję SecureFile2 i uruchamiam:
1 2 3
tar xzf SecureFile2_macosx.tar.gz cd SecureFile2_macosx java -jar SecureFile2-macosx.jar
Jeśli nie będzie problemów, to powinno pojawić się okno programu:
Jeśli będą problemy to do maila ze zgłoszeniem błędu należy skopiować zawartość terminala, od polecenia java -jar ... do końca.
Ponowne uruchomienie
Jeśli udało się w poprzednim kroku zainstalować i uruchomić SecureFile2. To kolejne uruchomienie można wykonać w terminalu komendą:
1
cd ~/Downloads/SecureFile2_macosx && java -jar SecureFile2-macosx.jar
Dodatkowy hint
Walidator transakcji wygląda jak program Windowsowy,
ale to tylko złudzenie. W środku jest to taki sam plik jar jak SecureFile2. Po pobraniu można go uruchomić w terminalu:
** Konfiguracja jest ściśle powiązana ze środowiskiem.** Konfiguracja ze środowiska testowego dotyczy włącznie środowiska testowego i nie ma wpływu na środowisko produkcyjne. Podobnie konfiguracja środowiska produkcyjnego dotyczy wyłącznie środowiska produkcyjnego i nie ma wpływu na środowisko testowe. Konfiguracja jest przechowywana wewnątrz przeglądarki, konfiguracja dla Firefoxa nie wpływa na Chrome, podobnie konfiguracja przeprowadzona na koncie Administrator nie wpływa na konta użytkowników.
Konfiguracja Szafir SDK
Szafir SDK korzysta z pliku konfiguracjynego settings.xml, w którym wskazane są certyfikaty kwalifikowanych urzędów certyfikacji oraz biblioteki PKCS#11 do komunikacji z kartami z podpisami elektronicznymi.
Domyślnie konfiguracja pobierana jest z serwera, ale można ją nadpisać. W tym celu w sekcji Szafir SDK zmieniamy rodzaj ustawień z ustawienia domyślne na ustawienia lokalne, to powinno włączyć edycję w textarea podpisanym Ustawienia kontrolki.
W tymże textarea znajduje się treść pliku settings.xml.
Domyślnie pod koniec tego pliku, są taki podobne do poniższych:
1 2 3 4 5
<HardwareProvider> <Name>PKCS#11 Type A</Name> <URI>SimplySignPKCS64.dll</URI> </HardwareProvider> </CryptoProviders>
Modyfikujemy ten tekst tak, aby przypominał poniższy:
Oczywiście w miejsce e: wstawiamy literę dysku, na którym znajduje się plik pieczęci, katalog zastępujemy ścieżką, a pieczec.p12 zastępujemy nazwą pliku z pieczęcią. Wewnątrz tagu URI nie stosujemy Windowsowego backslasha \\, ale slash / taki jak w adresach stron www.
Po modyfikacji pliku klikamy przycisk Zapisz ustawienia Szafir SDK.
Przed kilkoma dniami musiałem skorzystać z obywatel.gov.pl
i zainstalowałem aplikację Podpis Kwalifikowany. Po jej zainstalowaniu przestało działać podpisywanie
dokumentów na stronie GIIFa z użyciem karty Certum. Podobny problem może dotknąć użytkowników nowo wystawionych przez Certum kart, w tym wypadku Szafir SDK widzi podpis na karcie, ale próba podpisania dokumentu kończy się błędem.
Geneza problemu
Wraz z instalacją aplikacji Podpis Kwalifikowany w moim katalogu tymczasowym:
c:\Users\ksm\AppData\Local\Temp pojawiły się pliki cryptoCertum3PKCS.dll oraz cryptoCertum3PKCS-64.dll.
Przy próbie podpisania czegokolwiek na stronie GIIF, w konsoli Szafir SDK pojawia się poniższy błąd (około linii 175):
1 2
Wed Dec 09 11:45:04 CET 2020 C:\Users\ksm\AppData\Local\Temp\cryptoCertum3PKCS.dll- PKCS11Exception: %1 nie jest prawidlowa aplikacja systemu Win32. C:\Users\ksm\AppData\Local\Temp\cryptoCertum3PKCS.dll
Powyższy błąd oznacza, że plik cryptoCertum3PKCS.dll ma inną architekturę niż domyślna Java w komputerze.
W moim przypadku jest zainstalowana Java dla architektury x64, a biblioteka cryptoCertum3PKCS.dll wrzucona przez
Podpis Kwalifikowany jest dla architektury x86, razem tworzą mieszankę wybuchową.
Dla nowych kart wystawionych przez Certum, problemem jest zbyt stara wersja biblioteki cryptoCertum3PKCS.dll w katalogu tymczasowym.
Obejście problemu.
Użytkownicy zgłosili, że dla nowych kart Certum wymagany jest restart komputera, co wydaje mi się logiczne, Szafir SDK ma załadowaną starą bibliotekę i dopiero przy kolejnym uruchomieniu SzafiirHosta wczyta biblotekę Certum ze wskazanej lokalizacji.
Udostępniliśmy do pobrania off-line’owy walidator plików.
Jest to aplikacja uruchamiana z linii poleceń, do jej uruchomienia wymagana jest Java w wersji 1.8 lub wyższej.
Pod Windows można ją uruchomić jako:
1
giif-xml2018-cli.exe --help
Pod Linuksem i OS-X jako:
1
java -jar giif-xml2018-cli.exe --help
W rezultacie otrzymujemy wynik podobny do tego:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
maj 20, 2020 1:46:30 PM org.jboss.weld.bootstrap.WeldStartup <clinit> INFO: WELD-000900: 2.4.8 (Final) maj 20, 2020 1:46:30 PM org.jboss.weld.environment.deployment.discovery.ReflectionDiscoveryStrategy processAnnotatedDiscovery INFO: WELD-ENV-000014: Falling back to Java Reflection for bean-discovery-mode="annotated" discovery. Add org.jboss:jandex to the classpath to speed-up startup. maj 20, 2020 1:46:30 PM org.jboss.weld.bootstrap.WeldStartup startContainer INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously. maj 20, 2020 1:46:31 PM org.jboss.weld.environment.se.WeldContainer fireContainerInitializedEvent INFO: WELD-ENV-002003: Weld SE container STATIC_INSTANCE initialized Usage: <main class> [-hV] [COMMAND] Prosta apka do walidacji plików. -h, --help Show this help message and exit. -V, --version Print version information and exit. Commands: validate Walidacja zgodno?ci z regu?ami i schem?. rule-validate Walidacja zgodno?ci z regu?ami. xsd-validate Waliduj zgodno?? z XSD. Weld SE container STATIC_INSTANCE shut down by shutdown hook
Linie od 1 do 8 to log uruchamiania programu, jest on wypisywany na STDERR więc można go przekierować do /dev/null.
Logi są wypisywane przez java.utils.logging, więc można je skonfigurować jak w każdym innym programie javowym przez,
przez dodanie -Djava.util.logging.config.file=logging.properties przed -jar
Usage: <main class> validate [-hqV] [-f=<outputFormat>] [-o=<outputFile>] plik... Walidacja zgodno?ci z regu?ami i schem?. plik... Pliki do walidacji. -f, --format=<outputFormat> Format wyniku walidacji: TEXT, JSON, CSV, domy?lnie TEXT. -h, --help Show this help message and exit. -o, --output=<outputFile> Plik wynikowy, domy?lnie STDOUT. -q, --quiet Nie wypisuj komunikatów na STDOUT. -V, --version Print version information and exit. Weld SE container STATIC_INSTANCE shut down by shutdown hook
Przykład użycia
1 2 3 4 5 6 7 8 9 10 11 12 13
$ java -jar giif-xml2018-cli.exe validate /tmp/test.xml test.xml: { położenieKarty: Dokument/TrescDokumentu/Karta[2]/DanePodmiotu[2]/ZleceniodawcaOsobaFizyczna/OsobaFizyczna/AdresZamieszkania/KodPocztowy aktualnaKarta: Rekord 1 » 1 wyjątek: cvc-complex-type.2.4.b: The content of element 't:KodPocztowy' is not complete. One of '{"http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/":KodPL, "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/":Kod}' is expected. } { położenieKarty: po tagu zamykającym Dokument/TrescDokumentu/Karta[2]/DanePodmiotu[2]/ZleceniodawcaOsobaFizyczna/OsobaFizyczna/AdresZamieszkania aktualnaKarta: Rekord 1 » 1 wyjątek: cvc-complex-type.2.4.a: Invalid content was found starting with element 'OsFizycznaOsobaUpowazniona'. One of '{"http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/":DzialalnoscGosp, "http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/":KrajUrodzeniaOsoby}' is expected. } Plik niepoprawny: /tmp/test.xml Weld SE container STATIC_INSTANCE shut down by shutdown hook
Usage: <main class> xsd-validate [-hqV] [-f=<outputFormat>] [-o=<outputFile>] plik... Waliduj zgodność z XSD. plik... Pliki do walidacji. -f, --format=<outputFormat> Format wyniku walidacji: TEXT, JSON, CSV, domyślnie TEXT. -h, --help Show this help message and exit. -o, --output=<outputFile> Plik wynikowy, domyślnie STDOUT. -q, --quiet Nie wypisuj komunikatu błędu na STDOUT. -V, --version Print version information and exit. Weld SE container STATIC_INSTANCE shut down by shutdown hook
Jeżeli żaden plik nie zawierał błędu aplikacja zwróci status 0.
Jeżeli co najmniej jeden z przetwarzanych plików zawierał błędy aplikacja zwróci 1.
Przykład
1 2 3
$ java -jar xml2018-cli-1.0.1.jar xsd-validate ~/Downloads/wymiana_export_0000000000_Transakcja_testowa\(1\).xml 2> /dev/null Plik poprawny: /home/ksm/Downloads/wymiana_export_0000000000_Transakcja_testowa(1).xml Weld SE container STATIC_INSTANCE shut down by shutdown hook
Przykład z błędem
1 2 3
$ java -jar giif-xml2018-cli.exe xsd-validate -f CSV -o wymiana.csv ~/Downloads/wymiana_export_0000000000_Transakcja_testowa\(1\).xml 2> /dev/null Plik niepoprawny: /home/ksm/Downloads/wymiana_export_0000000000_Transakcja_testowa(1).xml Weld SE container STATIC_INSTANCE shut down by shutdown hook
Powyższe polecenie sprawdza plik i zapisuje napotkane błędy do pliku wymiana.csv w formacie CSV. Utworzony plik wymiana CSV
1 2
Plik,Typ,Położenie karty,Karta po tagu,Identyfikator karty,Poprzedni identyfikator,Położenie błędu,Błąd po tagu,Komunikat,Dotyczy tagów,Wartość,Wyjątek wymiana_export_0000000000_Transakcja_testowa(1).xml,BŁĄD,,/Dokument,Rekord Transakcja testowa,Przed pierwszym rekordem.,,,,,,"cvc-complex-type.2.4.a: Invalid content was found starting with element 't:DokumentTozsamosci'. One of '{""http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/"":PESEL, ""http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/"":DataUrodzenia}' is expected."
Usage: <main class> rule-validate [-hqV] [-f=<outputFormat>] [-o=<outputFile>] plik... Walidacja zgodności z regułami. plik... Pliki do walidacji. -f, --format=<outputFormat> Format wyniku walidacji: TEXT, JSON, CSV, domyślnie TEXT. -h, --help Show this help message and exit. -o, --output=<outputFile> Plik wynikowy, domyślnie STDOUT. -q, --quiet Nie wypisuj komunikatu błędu na STDOUT. -V, --version Print version information and exit. Weld SE container STATIC_INSTANCE shut down by shutdown hook
Jeżeli żaden plik nie zawierał błędu aplikacja zwróci status 0.
Jeżeli co najmniej jeden z przetwarzanych plików zawierał błędy aplikacja zwróci 1.
Komenda validate wykonuje teraz sprawdzenie zgodności ze schemą,
a następnie sprawdzenie zgodności z regułami.
Zmiana nazwy komendy validate na rule-validate.
Stara komenda validate wykonująca wyłącznie sprawdzenie zgodności z regułami
występuje pod nazwą rule-validate
Poprawka do lokalizacji błędu schemy
Walidator poda element nadrzędny do miejsca wystąpienia błędu,
oraz poprzednio przetwarzany (właśnie zamknięty) element.
Walidacja formatu numeru IBANu.
Dotychczas walidator, sprawdzał poprawnośc numeru IBAN wyłącznie na podstawie weryfikacji
sumy kontrolnej. Umożliwiało to przesyłanie jako numerów IBAN numerów rachunków, które na
na trzeciej lub czwartej pozycji zawierały litery. Aktualnie sprawdzena będzie poprawnośc numeru (wg. wzorca [A-Z]{2}[0-9]{2}[A-Z0-9]{1,30}) i suma kontrolna.
Poprawka dla walidacji numeru PESEL.
Element PESEL, jeżeli jest użyty nie może być pusty.
Poprawki w walidacji kodów pocztowych
W adresach, wewnątrz elementu KodPocztowy wymagany jest niepusty element Kod lub KodPL.
Najczęściej występujące błędy w walidacji XSD
Włączenie walidacji XSD, może spowodować pojawienie się nowych błędów, najczęstsze z nich to:
cvc-pattern-valid
Znak końca linii w polu tekstowym
Objawia się parą błędów:
1 2
cvc-pattern-valid: Value 'KILKA LINIJEK TEKSTU' is not facet-valid with respect to pattern '.*' for type 'TUwagi'. cvc-type.3.1.3: The value 'Te same KILKA LINIEJEK TEKSTU' of element 'Uwagi' is not valid.
Może dotyczyć pola TytulTr i Uwagi na kartach transakcji, jak również pola Nazwa dla osoby prawnej i danych uproszczonych
beneficjenta, DaneAdresowe w danych uproszczonych beneficjenta.
W polach tekstowych, dla których schema narzuca wzorzec wyrażenia regularnego .*, nie mogą występować znaki nowej linii.
Polecam wykonanie normalizacji białych znaków, tj. zastąpienie tabulatorów i znaków końca linii spacjami,
a następnie zastąpienie powtórzonych spacji, pojedynczą spacją.
Niezgodność treści ze wzorcem.
Objawia się parą błędów:
1 2
cvc-pattern-valid: Value '' is not facet-valid with respect to pattern '\d{11}' for type 'TPESEL'. cvc-type.3.1.3: The value '' of element 't:PESEL' is not valid.
Należy dostosować pisownię treści do wzorca.
Warto zwrócić uwagę, że podanie pustego elementu, nie jest równoważne pominięciu elementu.
Element, który ma w schemie atrybut minOccurs="0" ale ma ustawiony wzorzec dla typu,
musi być pominięty lub mieć wartość zgodną ze wzorcem.
cvc-complex-type.2.4.a
Niewłaściwa kolejność elementów
Objawia się parą błędów, na przykład:
1 2
cvc-complex-type.2.4.d: Invalid content was found starting with element 't:KodPocztowy'. No child element is expected at this point. cvc-complex-type.2.4.a: Invalid content was found starting with element 't:Ulica'. One of '{""http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/"":KodPocztowy}' is expected.
W schemie używane jest grupowanie elementów przy użyciu typu xsd:sequence,
nakłada to na implementację obowiązek zachowania tej samej kolejności elementów co w schemie.
Należy sprawdzić w schemie w jakim typie elementu występuje element, który spowodował błąd,
i dostosować kolejność elementów do schemy.
Niewłaściwy namespace elementu
Objawia się poniższym błędem, proszę zwrócić uwagę na brak prefixu w elemencie AdresZamieszkania:
1
cvc-complex-type.2.4.a: Invalid content was found starting with element 'AdresZamieszkania'. One of '{""http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/"":AdresZamieszkania, ""http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/"":DzialalnoscGosp, ""http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/"":KrajUrodzeniaOsoby}' is expected.
Należy uzupełnić element o prefix lub deklaracje namespace.
Niewłaściwy element
Objawia się takim samym komunikatem jak błąd powyżej.
Może oznaczać:
literówkę w nazwie elementu, warto zwrócić uwagę na OsFizycznaOsobaUpowaniona w karcie transferu i OsFizycznaOsobaUpowa**z**niona na innych kartach,
umieszczenie elementu na niewłaściwym poziomie struktury, np. osoby upoważnionej wewnątrz danych osoby fizycznej, a nie obok.
Należy poprawić pisownię lub przenieść elementy na właściwy poziom struktury.
cvc-complex-type.2.4.b
Objawia się błędem podobnym do:
1
cvc-complex-type.2.4.b: The content of element 't:KodPocztowy' is not complete. One of '{""http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/"":KodPL, ""http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2018/10/10/giif/typy/"":Kod}' is expected.
Brakuje zawartości w miejscu gdzie jest ona wymagana, należy uzupełnić zawartość,
lub jeśli element jest opcjonalny (ma minOccur="0" w schemie) zupełnie go pominąć.
cvc-complex-type.3.2.2
Objawia się błędem podobnym do:
1
cvc-complex-type.3.2.2: Attribute 'Korekta' is not allowed to appear in element 'Karta'.
Może być spowodowany błędną pisownią nazwy atrybutu,
nazwy atrybutów są wrażliwe na wielkość znaków!!!
cvc-datatype-valid.1.2.1
Objawia się błędem:
1
cvc-datatype-valid.1.2.1: '1970-01-01T00:00:00' is not a valid value for 'date'.
W polach typu xsd:date, można umieszczać wyłącznie datę, nie może być ona uzupełniona o czas,
czyli nie wolno dodawać tam T00:00:00.
Zmiany w systemie testowym
W systemie testowym została uruchomiona taka sama walidacja plików jak w walidatorze off-line.
Pliki przesłane przez API mają pustą nazwę (a na stronie www nazwa prezentowana jest jako null).
Przyczyna problemu
Ani aktualna Ustawa, ani rozporządzenia wykonawcze nie narzucają nazewnictwa plików
przesyłanych do GIIF. Dlatego API nie wymusza podawania nazwy pliku.
Plik przesłany przez przeglądarkę ma domyślnie przekazaną nazwę pliku,
ale przy wywołaniach API, oprogramowanie musi wprost wskazać nazwę pliku.
Rozwiązanie
W dokumentacji API
znajdziemy wzmiankę wskzaującą na wykorzystanie nagłówka Content-Disposition:
„Nazwę pliku można przekazać ustawiając nagłówek Content-Disposition
na attachment z nazwą pliku w polu filename lub filename*”.
Przykład
Bez polskich znaków
W tym miejscu odwołam się do kwietniowego wpisu Flow-część-3
W tamtym wpisie wysyłałem plik o nazwie gotowka.xml.enc do instytucji o nipie 0123456789,
jednakże oryginalne wywołanie:
Powyższy przykład działa wyłącznie wtedy, gdy nazwa pliku
ogranicza się do znaków ASCII. Zastosowanie polskich znaków
w nazwach plików jest możliwe, ale wymaga zastosowania
atrybutu filename*
w nagłówku Content-Disposition.
Atrybut filename* zawiera nazwę kodowania, a następnie nazwę pliku w tym kodowaniu,
z bajtami spoza zakresu drukowalnych znaków ASCII zapisanymi jako hex encoded binary.
Na przykład nazwa pliku: test-aącćeęlłnńoósśzźzż-AĄCĆEĘLŁNŃOÓSŚZŹZŻ.xml
zostanie zamieniona na: UTF-8''test-a%c4%85c%c4%87e%c4%99l%c5%82n%c5%84o%c3%b3s%c5%9bz%c5%baz%c5%bc-A%c4%84C%c4%86E%c4%98L%c5%81N%c5%83O%c3%93S%c5%9aZ%c5%b9Z%c5%bb.xml
Warto zwrócić uwagę na użycie cudzysłowów zamiast apostrofów do otoczenia nagłówka Content-Disposition.
Atrybut filename* używa apostrofów, a w bashu cytowanie apostrofami wyłącza escape-sequences.
Zamiast tego użyłem cydzysłowów i zacytowałem cudzysłowy w atrybucie filename. Po przetworzeniu
przez basha, faktyczna wartość przekazana po parametrze --header będzie miała postać:
Content-Disposition: attachment; filename="test-aacceel_nnoosszzzz-AACCEEL_NNOOSSZZZZ.xml"; filename*=UTF-8''test-a%c4%85c%c4%87e%c4%99l%c5%82n%c5%84o%c3%b3s%c5%9bz%c5%baz%c5%bc-A%c4%84C%c4%86E%c4%98L%c5%81N%c5%83O%c3%93S%c5%9aZ%c5%b9Z%c5%bb.xml
/** * Tworzy zawartość nagłówka Content-Disposition dla załącznika o wskazanej nazwie. * * @param fileName nazwa pliku, którego nazwa ma być przekazana * @return treść nagłówka Content-Disposition dla wskazanej nazwy pliku */ publicstatic String buildContentDispositionFromFileName(String fileName) { return"attachment; filename=\"" + ApiUtils.toAscii(fileName) + "\";" + " filename*=" + ApiUtils.encodeRFC5987(fileName); }
Kontytnuję opis korzystania z podpisu elektronicznego w Linuksie.
Poniższy wpis odwołuje się do przykładowej implementacji, którą umieściłem
na githubie.
PKCS#11 w Java
Implementacja SunPKCS11
Java od wersji 1.5 ma wbudowaną implementację interfejsów kryptograficznych
(JCE) korzystającą z PKCS#11. Jest to klasa sun.security.pkcs11.SunPKCS11
w implementacji Sun/Oracle oraz OpenJDK.
Implementacja ta jest nieco ułomna.
brakuje w niej obsługi szyfrowania RSAES-OAEP. Ten problem wymusił
stosowanie Szafir SDK do szyfrowania kart transakcji na stronie GIIF,
nawet dla transakcji bez podpisu elektronicznego).
nawet dostęp do publicznych obiektów na tokenie PKCS#11,
wymaga zalogowania się do tokena (podania PINu).
KeyStore odnajduje wyłącznie te wpisy, dla których certyfikat
jest przechowywany na karcie (tak konfigurowane są wszystkie
obecnie wystawiane podpisy na kartach kryptograficznych,
ale w HSMach nCipher i Gemalto na których pracowałem konieczne
było dogranie certyfikatów do HSMa.)
Pomimo powyższych problemów wbudowana implementacja jest wystarczająca
do składania podpisów.
Implementacja IAIK
Istnieje również komercyjna implementacja JCE korzystająca z PKCS#11,
stworzona w Austrii.
Wrapper jest niskopoziomy, pozwala na wywoływanie poszczególnych
funkcji z PKCS#11 API. Użycie wrappera nie jest jednak przedmiotem
poniższego wpisu.
BouncyCastle PKIX
Interfejsy kryptograficzne w Java, udostępniają podstawowe operacje
kryptograficzne, ale nie umożliwiają tworzenia plików CAdES,
czy plików zaszyfrowanych CMS Enveloped.
BouncyCastle PKIX jest biblioteką, służącą (między innymi)
do tworzenia plików CMS (Crypto Message Syntax,
specyfikacja budowy plików podpisanych i/lub zaszyfrowanych,
na tejże specyfikacji oparto format pliku CAdES).
W przykładzie będę wykorzystywał bibliotekę w wersji
org.bouncycastle:bcpkix-jdk15on:1.64.
Biblioteka udostępnia dwie wersje narzędzi do tworzenia
plików CMS: zwykłą i strumieniową.
Wersja zwykła wymaga aby zarówno cały źródłowy dokument do podpisania,
jak i cały wynikowy dokument podpisany znalazły się
się na stosie (heap) JVM.
Wersja strumieniowa jest nieco mniej intuicyjna w konfiguracji,
ale nie nakłada takiego ograniczenia.
Przegląd kodu
Zaszyta konfiguracja
Starałem się jak najbardziej uprościć kod, dlatego pliku Main.java w kodzie zaszyłem:
// Tutaj możesz wstawić swój numer PIN, jeżeli pozostawisz tekst "USTAW_PIN", // to użyty zostanie ConsoleCallbackHandler, który zapyta o PIN w terminalu. privatestaticfinalStringTOKEN_PIN_STRING="USTAW_PIN"; privatestaticfinalchar[] TOKEN_PIN = TOKEN_PIN_STRING.toCharArray();
// Tutaj wstaw numer Twojego certyfikatu kwalifikowanego. privatestaticfinalBigIntegerCERT_SERIAL=newBigInteger("0123456789abcdef", 16);
UWAGA, po trzeciem niepoprawnym podaniu PINu karta zostanie zablokowana!!!
Odnalezienie aliasu dla certyfikatu
KeyStore przypomina trochę słownik (Map), w którym aliasom typu String
przypisane są obiekty typu Certificate oraz Key.
W implementacji SunPKCS11, alias jest pobierany z atrybutu CKA_LABEL.
Jeżeli ten atrybut zawiera polskie znaki diakrytyczne, to alias jest
nieprawidłowo dekodowany, co utrudnia pobranie aliasu wprost.
Zamiast tego przekazuję do metody numer seryjny certyfikatu,
a w metodzie iteruję po wszystkich aliasach, aż znajdę certyfikat,
o takim numerze seryjnym jak przekazałem.
Podpisywanie wykonywane jest w trybie strumieniowym.
Jest to implementacja wzorca projektowego dekorator.
Biblioteka BouncyCastle tworzy strumień (OutputStream), który konfiguruję,
wskazując strumień, do którego zapisany zostanie podpisany plik,
certyfikat i klucz prywatny używany do podpisu, algorytm podpisu
i kilka innych szczegółów. Do tak utworzonego strumienia zapisuję
dane, które chę podpisać.
Magia kryje się w metodzie SigningStreamBuilder::build.
Poniższy kod opiera się głównie na przykładzie z metody testSHA1WithRSAEncapsulated
w klasie NewSignedDataStreamTest.
podpisywacza contentSigner, który złoży podpis RSA z użyciem klucza prywatnego z karty.
kalkulatora sumy kontrolnej digestCalculatorProvider, który wyliczy sumę kontrolną
z wiadomości i dodatkowych podpisanych atrybutów.
generatora podpisywanej zawartości signerInfoGenerator,
który połączy sumę kontrolną wiadomości,
dodatkowych podpisywanych atrybutów i wywoła na niej podpisywanie.
listy certyfikatów do załączenia w podpisanym dokumencie.
SigningCertificateV2
Dodatkowo przy tworzeniu signerInfoGenerator pojawia się metoda
buildSignedAttributeTableGenerator.
Jej kod opiera się tej odpowiedzi ze StackOverflow.
Europejski podpis elektroniczny wymaga aby jednym z podpisanych atrybutów
podpisu był identyfikator certyfikatu kwalifikowanego użytego do podpisu.
Wymaga to zbudowania elementu ESSCertIDv2 i umieszczenia go wewnątrz
SigningCertificateV2, co robi metoda constructSigningCertificateV2.
Tak przygotowany element, w metodzie buildSignedAttributeTableGenerator,
opakowuje jako atrybut o OID wskazanym przez
PKCSObjectIdentifiers.id_aa_signingCertificateV2 czyli 1.2.840.113549.1.9.16.2.47.
Ten atrybut umieszczam w obiekcie klasy DefaultSignedAttributeTableGenerator.
DefaultSignedAttributeTableGenerator łączy atrybuty przekazane
przez użytkownika z domyślnymi wymaganymi atrybutami (np. signingTime).
Szyfrowanie również wykonywane jest metodą strumieniową, i również wykorzystuje wzorzec dekoratora.
1. Otwieram strumień wyjściowy result.
2. Konfiguruję i otwieram strumień szyfrujący encrypted, zapisuje on wynik do strumienia result.
3. Konfiguruję i otwieram strumień kompresujący compressed, zapisuje on wynik do strumienia encrypted.
4. Konfiguruję i otwieram strumień podpisujący signed, zapisuje on wynik do strumienia compressed.
5. Otwieram strumień z danymi wejściowymi source.
6. Kopiuję dane ze strumienia source do signed.
contentOID czyli informację jakiego typu dane zostały skompresowane,
domyślnie jest to CMSObjectIdentifiers.data czyli typ nieokreślony,
wskazanie wprost CMSObjectIdentifiers.signedData pozwala oprogramowaniu
rozszyfrowującemu na użycie parsera dla danych podpisanych CAdES bez konieczności
rozpoznawania typu danych na podstawie zawartości.
outputCompressor jedynym dostępnym kompresorem jest ZLibCompressor
Generowany jest losowy klucz symetryczny do zaszyfrowania danych.
Klucz symetryczny jest szyfrowany kluczem publicznym certyfikatu odbiorcy,
informacja o certyfikacie odbiorcy (wystawca i numer seryjny) i zaszyfrowany klucz symetryczny
są zapisywane na początku pliku zaszyfrowanego.
Dane zapisywane, które trafiają do strumienia szyfrującego są szyfrowane z użyciem
klucza symetrycznego.
Konfigurując strumień przekazuję:
symmetricEncryptionAlgorithm, algorytm dla szyfrowania symetrycznego,
domyślnie AES o długości klucza 256 pracujący w trybie CBC.
recipientCertificate, certyfikat odbiorcy, jeśli zmodyfikujemy kod, tak aby dodać
kolekcję certyfikatów, to możemy stworzyć jeden plik zaszyfrowany do dwóch lub więcej
odbiorców, na przykład do siebie, w ten sposób będziemy w stanie sami rozpakować dokładnie
taki plik jaki został przesłany do GIIF.
contentOID czyli informację jakiego typu dane zostały skompresowane,
domyślnie jest to CMSObjectIdentifiers.data czyli typ nieokreślony,
wskazanie wprost CMSObjectIdentifiers.signedData lub CMSObjectIdentifiers.compressedData
pozwala oprogramowaniu rozszyfrowującemu na użycie odpowiedniego parsera bez konieczności
rozpoznawania typu danych na podstawie zawartości.
W podobnym tonie jak w poprzednim wpisie umieszczę tutaj kilka spostrzeżeń na temat użycia podpisu
elektronicznego w systemie Linux.
Podpis elektroniczny a karta kryptograficzna
Z przepisów prawa wynika, że materiał kryptograficzny konieczny
do złożenia podpisu elektronicznego musi znajdować się na komponencie
technicznym. W praktyce oznacza to, że klucz prywatny do podpisu
elektronicznego musi znajdować się na karcie kryptograficznej (lub HSM),
z którego nie może on zostać wyciągnięty (w rozwiązaniu SimplySign taka
karta/HSM jest przechowywana w serwerowni u operatora usługi).
PKCS#11
PKCS#11 to API udostępniające funkcje potrzebne do implementacji
kryptografii z wykorzystaniem kluczy przechowowanych w sprzęcie
oraz akceleratorów kryptografii. Nie jest to jedyne API do realizacji
tej funkcji w Java bywa używane JCE (providery JCE są dostępne dla HSMów
nCipher oraz Gemalto), Microsoft również ma własne API dostępu
do kart kryptograficznych wbudowane w Windows (sterowniki dla tego
API są instalowane przy instalacji oprogramowania do podpisu).
PKCS#11 zostało opracowane w latach 90tych, dla języka C.
Jest to API niezależne od platformy, obecnie istnieją wrappery
pozwalające na wywoływanie tego API w różnych językach programowania.
Producenci kart kryptograficznych dostarczają bibliotekę, która
implementuje API PKCS#11 i komunikuje się z kartą kryptograficzną
aby użyć materiału kryptograficznego przechowywanego na karcie.
Dostępne biblioteki
Biblioteki PKCS#11 są specyficzne dla modelu karty kryptograficznej.
Na dzień 3 grudnia 2019 dostępność bibliotek przedstawia się następująco:
CenCert udostępnia program PEM-HEART na swojej stronie
w nim jest biblioteka PKCS#11.
Ze swojej strony mogę napisać, że testowałem podpisywanie kartami Certum, KIR Carbon i CenCert
w systemie Linux i nie miałem problemów. Osobiście nie testowałem podpisu SimplySign (z kartą „w chmurze”).
Niedostępne biblioteki
NIE znalazłem bibliotek PKCS#11 dla systemu Linux do następujących kart:
KIR Graphite
Sigillum Dark, jest to dziwne, bo pod Windows karta korzysta ze sterowników Athena NXP IDProtect Client,
a Athena-SCS chwali się w zakładce
„Products”, że IDProtect Client ma Windows, Mac OSX and LINUX support.
EuroCert, to też jest dziwne, bo pod Windows i MacOS karty EuroCert korzystają ze sterowników CSSI
firmy Charismathics, która chwali się,
że ich middleware jest Fully Windows Compliant plus support for Mac, Linux, Embedded and Mobile platforms.
Sprawdzenie czy karta działa
Do sprawdzenia wykorzystuję polecenie pkcs11-tool dla ClearLinux wymaga
ono skompilowanie ze źródeł programu OpenSC, a w Ubuntu i RHEL jest
dostępne w pakiecie opensc.
ksm@ksm-7530/tmp $ pkcs11-tool --module /tmp/libencardp11-4.1.1.9.so -I Cryptoki version 2.11 Manufacturer ENIGMA SOI Sp. z o.o. Library ENCARD PKCS#11 (ver 4.1) Using slot 0 with a present token (0x0)
Jak widać rozpoznał i wygrył obsługiwaną kartę.
Dla porównania bez karty.
1 2 3 4 5
ksm@ksm-7530/tmp $ pkcs11-tool --module /tmp/libencardp11-4.1.1.9.so -I Cryptoki version 2.11 Manufacturer ENIGMA SOI Sp. z o.o. Library ENCARD PKCS#11 (ver 4.1) No slot with a token was found.
ksm@ksm-7530/tmp $ pkcs11-tool --module /tmp/libencardp11-4.1.1.9.so -L Available slots: Slot 0 (0x0): Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00 token label : ENCARD token manufacturer : Enigma SOI Sp. z o.o. token model : IAS-ECC token flags : login required, rng, token initialized, PIN initialized hardware version : 5.14 firmware version : 7.0 serial num : 63XXXXXXXXXXXX04 pin min/max : 4/127 Slot 1 (0x1): Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00 token label : ENCARD 2 token manufacturer : Enigma SOI Sp. z o.o. token model : IAS-ECC token flags : login required, rng, token initialized hardware version : 5.14 firmware version : 7.0 serial num : 63XXXXXXXXXXXX04 pin min/max : 4/127 Slot 2 (0x2): Broadcom Corp 5880 [Contacted SmartCard] (0123456789ABCD) 00 00 token label : ENCARD 3 token manufacturer : Enigma SOI Sp. z o.o. token model : IAS-ECC token flags : login required, rng, token initialized hardware version : 5.14 firmware version : 7.0 serial num : 63XXXXXXXXXXXX04 pin min/max : 4/127
Ta karta ma 3 sloty, każdy slot może mieć przypisany inny PIN.
Wyświetlam listę obiektów publicznych w slocie (0x0), numer slotu podawany jest w notacji szestnastkowej,
a w linni poleceń należy podać numer dziesiętnie!!!
1 2 3 4 5 6 7 8 9 10
ksm@ksm-7530/tmp $ pkcs11-tool --module /tmp/libencardp11-4.1.1.9.so --slot 0 -O Public Key Object; RSA 2048 bits label: ID: 518XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX32bca Usage: none Access: local Certificate Object; type = X.509 cert label: Imię Nazwisko subject: DN: C=PL, GN=Imi\xC4\x99, SN=Nazwisko, CN=Imi\xC4\x99 Nazwisko/serialNumber=PESEL: 00010100009, O=Ministerstwo Finans\xC3\xB3w, ST=mazowieckie, L=Warszawa/postalAddress=0*\x0C\x16ul. \xC5\x9Awi\xC4\x99tokrzyska 12\x0C\x0600-916\x0C\x08Warszawa ID: 518XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX32bca
Dodanie opcji logowania -l pozwala na wyświetlenie także obiektów prywatnych.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
ksm@ksm-7530/tmp $ pkcs11-tool --module /tmp/libencardp11-4.1.1.9.so --slot 0 -O -l Logging in to "ENCARD". Please enter User PIN: Private Key Object; RSA label: ID: 518XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX32bca Usage: sign Access: sensitive, always sensitive, never extractable, local Public Key Object; RSA 2048 bits label: ID: 518XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX32bca Usage: none Access: local Certificate Object; type = X.509 cert label: Imię Nazwisko subject: DN: C=PL, GN=Imi\xC4\x99, SN=Nazwisko, CN=Imi\xC4\x99 Nazwisko/serialNumber=PESEL: 00010100009, O=Ministerstwo Finans\xC3\xB3w, ST=mazowieckie, L=Warszawa/postalAddress=0*\x0C\x16ul. \xC5\x9Awi\xC4\x99tokrzyska 12\x0C\x0600-916\x0C\x08Warszawa ID: 518XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX32bca
Proszę zauważyć, że ID dla obiektów klucza publicznego, klucza prywatnego i certyfikatu jest takie samo.
Jest to bardzo ważne, wrapper dla PKCS#11 używany w Javie łączy te trzy obiekty, w jeden wpis w KeyStore
i robi to na podstawie ID (a nie label).
KIR Carbon
Sprawdzam czy pkcs11-tool rozpoznaje bibliotekę.
1 2 3 4 5
ksm@ksm-7530/tmp $ pkcs11-tool --module /tmp/libccpkip11-2.01.00161.so -I Cryptoki version 2.1 Manufacturer CryptoTech Library Cryptoki DLL (ver 2.1) Using slot 0 with a present token (0x0)
ksm@ksm-7530/tmp $ pkcs11-tool --module /tmp/cryptoCertum3PKCS-2.0.0.43.r2-MS.so --slot 1 -O -l Logging in to "profil bezpieczny". Please enter User PIN: Private Key Object; RSA label: Imię Nazwisko ID: 1bXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX6e Usage: decrypt, sign, unwrap warning: PKCS11 function C_GetAttributeValue(ALWAYS_AUTHENTICATE) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12)
Access: sensitive, always sensitive, never extractable, local Public Key Object; RSA 2048 bits label: Imię Nazwisko ID: 1bXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX6e Usage: encrypt, verify, wrap Access: local Private Key Object; RSA label: ID: 94XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX97 Usage: decrypt, sign, unwrap warning: PKCS11 function C_GetAttributeValue(ALWAYS_AUTHENTICATE) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12)
Access: sensitive, always sensitive, never extractable, local Public Key Object; RSA 2048 bits label: ID: 94XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX97 Usage: encrypt, verify, wrap Access: local Private Key Object; RSA label: ID: 28XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4e Usage: decrypt, sign, unwrap warning: PKCS11 function C_GetAttributeValue(ALWAYS_AUTHENTICATE) failed: rv = CKR_ATTRIBUTE_TYPE_INVALID (0x12)
Access: sensitive, always sensitive, never extractable, local Public Key Object; RSA 2048 bits label: ID: 28XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX4e Usage: encrypt, verify, wrap Access: local Certificate Object; type = X.509 cert label: Imię Nazwisko subject: DN: CN=Imi\xC4\x99 Nazwisko, GN=Imi\xC4\x99, SN=Nazwisko/serialNumber=PNOPL-00010100009, C=PL ID: 1bXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX6e
Podsumowanie
pkcs11-tool można użyć aby sprawdzić, czy biblioteka pkcs11, którą posiadamy współpracuje
z naszą kartą. Należy sprawdzić pod jakim numerem slotu jest zapisany nasz certyfikat kwalifikowany
lub pieczęć elektroniczna. Należy też sprawdzić czy klucz prywatny i certyfikat mają takie same
ID (na kartach podpisu elektronicznego, które widziałem tak było, ale klucze generowane na HSM,
mogą nie mieć tej informacji).
Linki do pobrania rozszerzenia są zdefiniowane w pliku szafirsdk-module.js dostarczanym przez KIR wraz z biblioteką.
Zadanie rozszerzenia
Rozszerzenie przeglądarki jest konieczne aby używać mechanizmu native messaging
(patrz MDN). Ten mechanizm pozwala
przegladarce na uruchomienie zewnętrznej aplikacji, z którą rozszerzenie może komunikować się wysyłając tekstowe komendy
i odbierając tekstowe odpowiedzi na te komendy, ta komunikacja jest asynchroniczna!!!
Konsola Szafir SDK
Na stronach, które mają znacznik włączający rozszerzenie, w pobliżu paska adresu pojawia się granatowy kwadrat
z ikoną „KIR”, po kliknięciu w niego można otworzyć konsolę Szafir SDK.
SzafirHost
Zewnętrzną aplikacją z którą komunikuje się rozszerzenie jest SzafirHost.
Linki do pobrania aplikacji SzafirHost są zaszyte w rozszerzeniu. W chwili pisania tego wpisu były to:
dla Windows,
dla Linux i MacOS.
Instalację dla MacOS opisałem w poprzednim wpisie
instalacja w systemie Linux jest przeprowadzana analogicznie do instalacji w MacOS.
Zadania aplikacji
Aplikacja składa się z pliku SzafirHost.jar oraz skryptu uruchamiania SzafirHost.sh lub SzafirHost.bat który służy,
do uruchomienia SzafirHost.jar z wykorzystaniem maszyny wirtualnej Java (JVM) zainstalowanej na komputerze
użytkownika.
Prawdziwa magia aplikacji ukryta jest jednak w instalatorze, który dogrywa pliki manifestu aplikacji natywnej
do konfiguracji przegladarki. Aplikacja natywna nazywa się pl.com.kir.szafirhost. Manifestu należy szukać
w poniższych lokalizacjach: Chrome,
Firefoxpatrz na NativeMessagingHosts.
Modyfikacja sposobu uruchamiania
Skrypty wykorzystują JVM dostępne na ścieżce uruchamiania. Można wskazać inną maszyną wirtualną Java poprzez
poprzez modyfikację zmiennej systemowej PATH lub bezpośrednie wskazanie programu java lub java.exe.
Uruchomienie SzafirHost
Rozszerzenie przeglądarki po wykryciu znacznika w kodzie strony dodaje zmienną globalą pozwalającą
JS na stronie komunikować się z rozszerzeniem.
JS wywołuje inicjalizację wywołuje połączenie z natywną aplikacją, na co przeglądarka reaguje uruchomieniem
aplikacji wskazanej w pliku manifestu.
Może się zdarzyć, że proces SzafirHost pracujący w tle zostanie ubity,
co skutkuje błędem braku komunikacji z SzafirHost,
Wystąpił błąd: Szafir SDK Chrome Host nie został uruchomiony,
po wystąpieniu takiego błędu można jedynie zapisać XML
z aktualnie edytowanego formularza, zamknąć wszystkie okna przeglądarki i ubić procesy przeglądarki,
które pozostały w tle, o ile takie będą, a następnie ponownie uruchomić przeglądarkę (wylogowanie
i ponowne zalogowanie użytkownika lub ponowne uruchomienie komputera również zadziała ale jest bardziej
inwazyjne)
JS przekazuje do rozszerzenia konfigurację, konfiguracja zawiera
URL z katalogiem, w którym na stronie GIIF znajdują się pliki Szafir SDK
nazwę manifestu versions.xml z listą plików do pobrania i ich wielkościami.
czy debugowanie jest włączone
czy używać proxy systemowych
adres proxy dla http
adres proxy dla https
lista nazw/adresów serwerów dla których nie należy używać proxy
Pozycje zaznaczone italiką można ostrożnie modyfikować na teście,
na produkcji. Ustawienia dla testu i dla produkcji są rozdzielne.
Mechanizm do modyfikacji konfiguracji SzafirHost i pliku settings.xml jest zaszyty w kodzie JS stron
giif.mofnet.gov.pl.
Według mojego stanu wiedzy na dzieć 2019-11-27, SzafirHost nie jest wstanie przebić się przez proxy wymagające
autoryzacji. Kod aplikacji został zabezpieczony przed dekompilacją, co znacznie utrudnia analizę.
SzafirHost pobiera plik versions.xml, następnie pobiera do katalogu tymczasowego pliki tam wymienione.
JS wysyła do SzafirHost plik settings.xml, zawiera on listę certyfikatów urzędów kwalifikowanych,
listę certyfikatów wystawców UPO, wskazuje algorytm użyty do wyliczania sumy kontrolnej przy podpisie
elektronicznym oraz listę bibliotek PKCS#11.
Należy zwrócić uwagę, że przekazujemy URL do biblioteki a nie położenie pliku. Czyli zamiast:
C:\Program Files (x86)\CryptoTech\CryptoCard\CCPkiP11.dll musimy wpisać:
file:///C:/Program%20Files%20(x86)/CryptoTech/CryptoCard/CCPkiP11.dll. W elemencie URL można też
wpisać samą nazwę biblioteki, w takim wypadku SzafirHost będzie jej szukał w katalogu tymczasowym
do którego pobrał elementy Szafir SDK ze strony, a następnie w ścieżce wyszukiwania bibliotek
(patrz na zmienną java.library.path w wywołaniu java -XshowSettings:properties -version).
Do tak zainicjalizowanego SzafirHosta, JS wysyła żądanie podpisania danych.
SzafirHost iteruje po liście bibliotek PKCS#11, jeśli biblioteki nie ma we wskazanej lokalizacji lub na ścieżce,
to w konsoli wyrzuca błąd otwarcia strumienia.
Dla każdej znalezionej biblioteki, wywołuje wyszukiwanie kart, jeżeli nie ma czytnika lub karty w czytniku,
to w konsoli wyrzuca błąd TOKEN_NOT_FOUND.
Dla każdej znalezionej karty wywołuje wyszukiwanie certyfikatów, domyślnie ukrywa certyfikaty przeterminowane,
nie pozwala na podpisywanie przeterminowanym certyfikatem.
SzafirHost wyświetla okno podpisu, ze znalezionym certyfikatem (lub bez niego). A po podpisaniu zwraca wynik
lub błąd do rozszerzenia (a ono do JS).
Problemy z SzafirHost
Po instalacji SzafirHost, rozszerzenie nadal domaga się instalacji SzafirHost
Najprawdopodobniej przeglądarka nie może uruchomić SzafirHost. Należy sprawdzić czy użytkownik może uruchomić
skrypt startowy rozszerzenia, po starcie powinna wyświetlić się wersja rozszerzenie, np. 1.0.7 i kilka innych
znaków.
Jeśli nie, to należy sprawdzić czy zainstalowano Java i czy użytkownik ma uprawnienia do uruchomienia tego programu.
Zatrzymuje się na pobieraniu versions.xml, „Trwa inicjalizowanie komponentów podpisu elektronicznego”.
Upewnić się czy czytnik jest dobrze podłączony do komputera (ekipa sprzątająca potrafi wysunać każdy kabel).
jeżeli to nie pomogło, to można wskazać ręcznie bibliotekę PKCS#11 lub przystąpić do debugowania.
Sprawdzić w konsoli Szafir SDK czy biblioteki PKCS#11 zostały znalezione,
jeżeli nie zostały znalezione, to można zmodyfikować plik settings.xml aby je odnajdywał.
jeżeli zostały odnalezione, to trzeba sprawdzić w jakiej lokalizacji, może zdarzyć się, że 32 bitowe JVM
odnalazło 64 bitowe biblioteki, lub 64 bitowe JVM odnalazło 32 bitowe biblioteki. Aby to naprawić należy
posprzątać biblioteki, zmodyfikować settings.xml (wskazać bibliotekę w prawidłowej architekturze),
lub zmodyfikować skrypt startowy (wskazać JVM w prawidłowej architekturze).
jeżeli znajduje kartę (nie wyświetla błędu braku karty), to być może na karcie są wyłącznie przeterminowane
certyfikaty, należy wtedy zmienić kartę lub przedłużyć certyfikat. (tik w dialogu pozwala wyłączyć
odfiltrowywanie przeterminowanych certyfikatów, po jego zaznaczeniu widać certyfikaty ale nadal nie można
ich użyć).