Postup vydání certifikátu¶
V této kapitole je popsán postup volání jednotlivých komunikací se systémy I.CA, jak by měly být postupně za sebou provolány při procesu vydání certifikátu. Proces vydání lze rozdělit na dvě varianty vydání certifikátu, viz Varianty vydání certifikátu.
Tato kapitola popisuje postup pro vydání osobních certifikátů. Vydání serverového certifikátu se skládá ze stejných kroků, ale v některých krocích je odlišné naplnění požadavků odesílaných na systémy I.CA.
U obou typů procesů vydání certifikátu je proces zahájen tím že se načte žádost o certifikát. Prerekvizitou pro vydání certifikátu je mít nastavený kód RA a vlastnit certifikát (komerční nebo twins pár) s operátorským oprávněním.
Proces vydání certifikátu¶
1. Ověření operátorského certifikátu (BicaConnector.ControlOperatorAsync)¶
Před zahájením zpracování žádosti by se měl ověřit certifikát, kterým se podepisují těla http požadavků, má operátorské oprávnění a lze s ním vydávat nové certifikáty. Zavoláním této komunikace lze předejít budoucím chybným voláním následujících komunikací, kdy by všechny vracely chybu použití špatného certifikátu pro komunikaci s daným systémem.
Ověření probíhá na základě podpisu http těla požadavku komunikace BicaConnector.ControlOperatorAsync
, kdy BICA získá informace o podpisovém certifikátu a ověří jej, zda má operátorské oprávnění.
2. Získání ID pro žádost o certifikát (CaConnector.GetReqIdAsync)¶
Po načtení žádosti by se mělo nejprve žádosti přiřadit id. Id žádosti se přiřazuje na začátku procesu z důvodu, že je součástí protokolu, který je potřeba získat před odesláním žádosti na CA.
Metoda GetReqIdAsync
vrací poslední evidované číslo žádosti pro daný kód RA. Získané číslo žádosti tedy není možné ihned použít ale je potřeba jej inkrementovat do doby dokud se z něj nestane unikátní číslo žádosti (např. z CA se získá id žádosti 101, v RA jsou rozpracované žádosti 102 a 103, nově vytvářené žádosti je tedy potřeba přiřadit id 104)
Odpověď je zapouzdřena ve třídě GetReqIdResp. Číslo žádosti je uvedené ve vlastnosti GetReqIdResp.ReqID
.
Vlastnost GetReqIdResp.ReqIDTwin
slouží pro porovnání id žádostí párových certifikátů při vydávání certifikátů twins. Tato vlastnost je přidána z důvodu oddělené kvalifikované (QICA) a komerční CA (SICA). Slouží ke kontrole aby se twins žádosti nenastavili špatné id. Srovnává se ReqIdTwin získáné ze SICA s ReqId ziskáným ze QICA a naopak.
Pokud se vydává pár certifikátů TWINS, je potřeba potřeba získat id žádosti z QICA i SICA!
3. Získání protokolu o podání žádosti (BicaConnector.GetProtocolAsync)¶
Posledním krokem před odesláním žádosti na server CA je získání protokolu o podání žádosti, který je potřeba vytisknout a podepsat (v rámci elektronického vydávání pouze el. podepsat). Protokol je generován systémem BICA. Aplikace RA zašle dostupná data (data ze žádosti o certifikát a osobní údaje žadatele získané operátorem RA nebo jiným způsobem), která jsou k dispozici ve třídě GetProtocolReqBody a GetProtocolBodyData.
Komunikace BicaConnector.GetProtocolAsync
slouží pro vygenerování více druhů protokolů, z toho důvodu je naplnění instance třídy GetProtocolBodyData
velice variabilní. V rámci získání protokolu o podání žádosti o certifikát je potřeba nastavit tyto položky:
ChallengePassword
- heslo pro zneplatněníDate
- datum vytvoření protokoluDateAndTime
- datum podpisu protokoluFirmName
- název společnosti, je potřeba uvést pouze pokud je certifikát vydáván zaměstnanci nebo právnické osobě.Locality
- umístění kde protokol vznikl (lokalita kde se nachází RA)RaCode
- identifikační kód RARaOperator
- celé jméno operátora RAAddress
- adresa žadateleAlgorithm
- Algoritmus klíčového páruCertificateTransparency
- příznak o zveřejnění certifikátuIdentification
- rodné číslo nebo datum narozeníMpsv
- příznak o přidělení IK MPSVName
- křestní jméno žadatelePrimaryDocument
- primární doklad totožnosti (typicky občanský průkaz)SecondaryDocument
- sekundární doklad totožnosti (povinný pouze pro kvalifikované certifikáty)PublicCertificate
- příznak zda bude certifikát vydán jako veřejnýReqId
- číslo žádostiSurname
- Příjmení žadateleDn
- předmět žádosti o certifikát (Dictionary položek OID a seznam hodnot)San
- alternativní jméno předmětu (Dictionary položek OID a seznam hodnot) - pouze pokud je SAN k dispoziciEku
- rozšířené použití klíče (Dictionary položek OID a seznam hodnot) - pouze pokud žádost obsahuje EKUSigner
- podepisující (jméno žadatele, které se vkládá do závěrečné části pod kolonku pro podpis žadatele)
V případě párového certifikátu TWINS je potřeba nastavit ještě položky:
Algorithm2
- algoritmus klíče párové žádosti o certifikátDn2
- předmět žádosti o párový certifikátSan2
- alternativní jméno předmětu (Dictionary položek OID a seznam hodnot) pro párovou/ý žádost / certifikát - pouze pokud je SAN k dispoziciEku2
- rozšířené použití klíče (Dictionary položek OID a seznam hodnot) pro párovou/ý žádost / certifikát - pouze pokud žádost obsahuje EKU
Pro získání instance třídy GetProtocolBodyData je k dispozici builder třída GetProtocolBodyDataBuilder. Pro získání položek typu Dictionary{string, List{string}}
(např. Dn, San, Eku) lze využít builder třídu GetProtocolDictionaryBuilder.
Instance třídy GetProtocolBodyData se poté vkládá do objektu GetProtocolReqBody. Tento objekt obsahuje základní základní informace o žádosti:
CertType
- typ certifikátu (viz typy certifikátů)Language
- jazyk v jakém bude protokol vygenerován (hodnoty - cs, en, sk)PayParentId
- id plátce za certifikát (viz plátce za certifikát)Data
- instance objektu GetProtocolBodyDataTemplate
- typ šablony, zde vždy hodnota PROTOCOL
Pro vytvoření instance GetProtocolReqBody
lze využít builder třídu GetProtocolBodyBuilder
Instanci třídy GetProtocolReqBody
je potřeba převést do JSON a zakódovat do Base64String. Tuto hodnotu je potřeba vložit do objektu GetProtocolReq. Pro tvorbu instance GetProtocolReq
lze využít builder třídu GetProtocolReqBuilder, která přebírá instanci GetProtocolReqBody
a provede převedení do JSON a zakódování do Base64String.
Instanci třídy GetProtocolReq
již lze předat parametru funkce BicaConnector.GetProtocolAsync
, která zašle požadavek na vygenerování protokolu. Ten je navrácen ve třídě GetProtocolResp ve vlastnosti Protocol
, kde je zakódován v Base64String. Protokol je generován ve formátu PDF.
4. Odeslání protokolu o podání žádosti na systém STORAGE (StorageConnector.PutCertificateRequest)¶
Pokud je žádost o certifikát vyřizována papírovou formou, tento krok se musí přeskočit.
V případně elektronické formy vydání certifikátu je před odesláním žádosti na CA nejprve potřeba žádost zaevidovat v systému Storage, kde se pro žádost budou archivovat jednotlivé protokoly.
Funkce StorageConnector.PutCertificateRequest
na vstupu přebírá instanci třídy PutCertificateRequestReq, která musí mít inicializovány následující položky:
ReqId
- id žádosti o certifikát. Pokud se jedná o žádost pro párový certifikát TWINS, udává se id hlavní žádosti (id žádosti pro kvalifikovaný certifikát z páru TWINS).CertProfile
- typ profilu certifikátu (viz profily žadatelů)OperatorCertificate
- informace o kvalifikovaném certifikátu z páru TWINS operátora (sériové číslo a AKID)PayParent
- id plátce za certifikát (viz plátce za certifikát)CertType
- typ certifikátu (viz typy certifikátů)Documents
- seznam přiložených dokumentů. Seznam musí obsahovat dokument s typem PROTOCOL, který vznikl v kroku 2. Informace o dokumentu jsou zapouzdřeny ve třídě StorageDocumentObject.
Pro získání instance třídy PutCertificateRequestReq
je k dispozici builder třída PutCertificateRequestReqBuilder, která obsahuje metodu i pro vytvoření instance třídy StorageDocumentObject
a přidání do seznamu dokumentů.
Po úspěšném zavolání metody StorageConnector.PutCertificateRequest
lze pokračovat dále v odeslání žádosti na CA. Pokud v této komunikaci nastane chyba, nesmí být žádost odeslána na CA.
5. Odeslání žádosti na systém CA (CaConnector.PutReqAsync)¶
Funkce pro odeslání žádosti Caconnector.PutReqAsync
přebírá jako parametr instanci třídy PutReqReq, která se skládá z následujících položek:
KeyAndRequestData (KeyAndRequestDataObject)¶
Obsahuje samotnou žádost o certifikát, ID žádosti a další údaje týkající se žádosti (např. číslo karty, pokud byl klíč generován na kartě). Instanci třídy lze získat pomocí builder třídy KeyAndRequestDataBuilder a je potřeba inicializovat tyto položky:
Request
- data žádosti o certifikát v PEMReqId
- id žádosti
Další položky se nastavují v závislosti na typu certifikátu a kde je uložen klíčový pár (např. CardNumber
a QSCD
pokud bude certifikát uložen na čipové kartě, která má status QSCD).
Pokud se jedná o žádost pro párový certifikát TWINS je potřeba inicializovat seznam ReqIDInterconnections
, ve které jsou k uvedeny všechny párové žádosti (je potřeba uvést i id žádosti, které je zadáno ve vlastnosti ReqId
).
CertificateProperties PutReqCertProps¶
Parametry pro vytvářený certifikát. Pro získání instance třídy PutReqCertProps
lze využít builder třídu PutReqCertPropsBuilder. Objekt musí mít inicializovány alespoň tyhle hodnoty:
CertChallengePassword
- heslo pro zneplatnění certifikátuCertType
- typ certifikátu, viz typy certifikátůMpsvIk
- Příznak zda se má vložit do certifikátu IK MPSV (hodnoty - yes, no) (lze použít pouze pro kvalifikované certifikáty, komerční certifikáty musí mít hodnotu "no")
BillingData (BillingDataObject)¶
Informace o plátci za certifikát. Instanci BillingDataObject
lze získat pomocí builder třídy BillingDataBuilder. Instance musí mít inicializovanou hodnotu PayParentId
(viz plátce za certifikát).
UserData (PutReqUserData)¶
Osobní údaje a další vyžadované informace o žadateli. Instanci PutReqUserData
lze získat pomocí builder třídy PutReqUserDataBuilder, a musí mít inicializované následující vlastnosti:
Name
- křestní jméno žadateleSurname
- příjmení žadateleAddress
- adresa trvalého bydliště žadateleDocument
- Doklad totožnostiLanguage
- Jazyk (Hodnoty - cs, en, sk)
Ostatní položky jsou povinné pouze pro specifické typy nebo profily certifikátů, např.:
Document2
- vyžadováno pro kvalifikované certifikátySex
- pohlaví žadatele (M - muž, F - žena). Je potřeba zadat pouze pro kvalifikovaný certifikát, bude obsahovat IK MPSV (pohlaví je vyžadováno při přidělení IK MPSV).Company
- vyžadováno pro zaměstnanecké profily certifikátů (instanci třídy CompanyObject lze získat pomocí builder třídy CompanyBuilder).
Instanci třídy PutReqReq
lze získat pomocí builder třídy PutReqReqBuilder.
Pokud odeslání žádosti proběhne v pořádku není navrácena žádná návratová hodnota. V případě chyby je navrácena výjimka CAServerException.
Při odesílání žádosti je potřeba dbát na druh žádosti, zda se jedná o žádost pro kvalifikovaný nebo komerční certifikát. Žádost je podle tohoto druhu potřeba odeslat na správnou CA:
- Žádost o kvalifikovaný certifikát je potřeba odeslat na kvalifikovanou CA (QICA)
- Žádost o komerční certifikát je potřeba odeslat na komerční CA (SICA)
Při odesílání žádosti o párový certifikát TWINS je potřeba vytvořit požadavek na odeslání PutReqReq
pro každý certifikát z páru zvlášť a samostatně jej odeslat na danou CA.
6. Získání vydaného certifikátu ze systému CA (CaConnection.GetCertificateAsync)¶
Získání vydaného certifikátu probíhá pomocí volání komunikace CaConnection.GetCertificateAsync
. Metoda v parametru přebírá instanci třídy GetCertReqBody. Vyhledávat certifikát lze buď pomocí sériového čísla, čísla žádosti nebo SHA-1 otisku klíče.
Při vydávání prvotního certifikátu se využívá čísla žádosti, pro dotaz je tedy potřeba vytvořit instanci třídy GetCertReqBody
a inicializovat její vlastnost ReqId
. Pro inicializaci instance GetCertReqBody
lze využít builder třídu GetCertReqBodyBuilder.
Metoda CaConnections.GetCertificateAsync
vrací v odpovědi instanci třídy GetCertRespBody. V této instanci je nejprve potřeba zkontrolovat naplnění vlastnosti GetCertRespBody.RegInfo.State. Tato vlastnost indikuje aktuální stav zpracování žádosti o certifikát. Rozlišují se tři stavy:
inprocess
(CaConnection.GETCERT_STATE_INPROCESS) - žádost se zpracovává a certifikát ještě nebyl vydán. Vlastnosti GetCertRespBody.CertificateObject a GetCertRespBody.ReqRejectInfo mají hodnotu null. Objekt GetCertRespBody.RegInfo obsahuje ještě vlastnost StateCode, kde je uveden kód identifikující v jakém kroku se zpracování žádosti nyní nachází.certissued
(CaConnection.GETCERT_STATE_CERTISSUED) - certifikát byl vydán. Certifikát se nachází v objektu GetCertRespBody.CertificateObject.rejected
(CaConnection.GETCERT_STATE_REJECTED) - žádost o vydání certifikátu byla zamítnuta. Důvod zamítnutí žádosti je uveden v objektu GetCertRespBody.ReqRejectInfo, ve kterém jsou dostupné informace z jakého důvodu byla žádost zamítnuta.
Dotazy vzniklé v komunikaci GetCertificateAsync je možné cachovat, viz Obecný popis třídy CaConnector.
Pokud je stav žádosti inprocess
, je potřeba se po čase dotázat stejným způsobem na aktuální stav a tento dotaz opakovat dokud se stav žádosti nezmění na certissued
nebo rejected
.
Pokud se jedná o žádost o certifikát pro pár certifikátů TWINS, je potřeba se dotazovat samostatně na QICA i SICA v jakém stavu vydání se nachází každý z páru certifikátu TWINS.
7. Získání smlouvy o vydání certifikátu (BicaConnector.GetProtocolAsync)¶
K získání smlouvy o certifikát se používá funkce BicaConnector.GetProtocolAsync
podobně jako v kroku 3. Smlouvu je poté potřeba vytisknout a vlastnoručně podepsat nebo v případě elektronické formy vydání elektronicky podepsat (operátor i klient).
Pro vygenerování smlouvy je potřeba zaslat systému BICA informace pro vyplnění šablony smlouvy. Instance třídy GetProtocolBodyData by měla mít inicializované tyto vlastnosti:
CertDateTimeFrom
- Platnost certifikátu odCertDateTimeTo
- platnost certifikát doDate
- datum vytvoření protokoluDateAndTime
- datum a čas, který bude uveden v protokoluLocality
- umístění RARaCode
- identifikační kód RARaOperator
- jméno operátora RASerialNumber
- sériové číslo certifikátuAddress
- adresa trvalého bydliště žadateleAlgorithm
- algoritmus klíčového páru certifikátuIdentification
- rodné číslo / datum narozeníName
- křestní jméno majitele certifikátuReqId
- id žádosti o certifikátSurname
- Příjmení majitele certifikátuDn
- předmět certifikátu jako Dictionary{string, List{string}}DnIssuer
- předmět vydavatelského certifikátu jako Dictionary{string, List{string}}Signer
- jméno majitele certifikátu (je uvedeno v podpisové části smlouvy)
V případě párového certifikátu TWINS je potřeba nastavit ještě položky:
CertType2
- typ párového certifikátu, viz typy certifikátůCertDateTimeFrom2
- platnost párového certifikátu odCertDateTimeTo2
- platnost párového certifikátu doSerialNumber2
- sériové číslo párového certifikátuAlgorithm2
- algoritmus klíčového páru párového certifikátuDn2
- předmět párového certifikátu jako Dictionary{string, List{string}}DnIssuer2
- předmět vydavatelského certifikátu párového certifikátu jako Dictionary{string, List{string}}
Instance třídy GetProtocolBodyData
se poté vkládá do objektu GetProtocolReqBody. Tento objekt obsahuje základní základní informace o žádosti:
CertType
- typ certifikátu, viz typy certifikátůLanguage
- jazyk v jakém bude protokol vygenerován (hodnoty - cs, en, sk)PayParentId
- id plátce za certifikátData
- instance objektu GetProtocolBodyDataTemplate
- typ šablony, zde vždy hodnota AGREEMENT
Pro vytvoření instance GetProtocolReqBody
lze využít builder třídu GetProtocolBodyBuilder
Instance třídy GetProtocolReqBody
je potřeba převést do JSON a zakódovat do Base64String. Tuto hodnotu je potřeba vložit do objektu GetProtocolReq. Pro tvorbu instance GetProtocolReq
lze využít builder třídu GetProtocolReqBuilder, která převedení na json a zakódování do Base64String má implementováno.
Instanci třídy GetProtocolReq
již lze předat parametru funkce BicaConnector.GetProtocolAsync
, která zašle požadavek na vygenerování smlouvy. Ta je navrácena ve třídě GetProtocolResp ve vlastnosti Protocol
, kde je smlouva zakódována v Base64String. Po dekódování hodnoty je smlouva dostupná ve formátu PDF.
8. Uložení protokolu a smlouvy na úložiště dokumentů STORAGE (StorageConnector.PutCertificateAgreementAsync)¶
Pokud byl certifikát vydán papírovou formou, tento krok se neprovádí a proces vydání certifikátu je dokončen.
V případě vydání certifikátu el. formou, posledním krokem vydání certifikátu je nahrání el. podepsaného protokolu a smlouvy na úložiště dokumentů. Tento krok je nutno provést, v opačném případě se certifikát po definované době (1 měsíc) automaticky zneplatní.
StorageConnector.PutCertificateAgreementAsync
na vstupu přebírá instanci třídy PutCertAgreementReq. Instanci lze získat pomocí builder třídy PutCertAgreementReqBuilder a musí mít inicializovány tyto vlastnosti:
ReqId
- id žádosti o certifikát (v případě žádosti o párový certifikát TWINS se používá id hlavní žádosti o kvalifikovaný certifikát)ApplicantCertificate
- informace (sériové číslo a AKID) nově vydaného certifikátuIssuedCertificate
- informace (sériové číslo a AKID) nově vydaného certifikátu (stejné jako vlastnost ApplicantCertificate)OperatorCertificate
- iinformace o kvalifikovaném certifikátu z páru TWINS operátora (sériové číslo a AKID)CertType
- typ certifikátu, viz typy certifikátůAggreement
- smlouva o vydání certifikátu el. podepsaná operátorským kvalifikovaným certifikátem z páru TWINS a nově vydaným klientským certifikátem
Po úspěšném provedení komunikace StorageConnector.PutCertificateAgreementAsync je dokončen i proces el. vydání certifikátu.
Ukázka vydání certifikátu elektronicky pomocí unit testů¶
[TestClass]
public class IssueCertCompleteTests
{
ILogger<IssueCertCompleteTests> _log;
CaConnector _caConnector;
StorageConnector _storageConnector;
BicaConnector _bicaConnector;
HttpClient _httpClient;
ILoggerFactory _loggerFactory;
const string URL_SICA = "https://tests.ica.cz:443/cgi-bin/racom.cgi";
const string URL_QICA = "https://testq.ica.cz:443/cgi-bin/racom.cgi";
const string URL_BICA = "https://tbica.ica.cz/cgi-bin/BicaRaComAPI.cgi";
const string URL_STORAGE = "https://td.ica.cz/cgi-bin/StorageRaComAPI.cgi";
string _opraCertSN = "037ea08c17b870f6b4";
string _codeRA = "000";
string _certType = "Q-PE-CZ";
string _profile = "NATURAL-PERSON";
string _payParentId = "15705";
[TestInitialize]
public void Initialize()
{
_httpClient = new HttpClient();
_loggerFactory = LoggerFactory.Create((x) =>
{
var log4netProvider = new Log4NetProviderOptions("log4net.config");
x.AddLog4Net(log4netProvider);
x.SetMinimumLevel(LogLevel.Debug);
});
_log = _loggerFactory.CreateLogger<IssueCertCompleteTests>();
var clientName = "icara v5.0.0.0";
var getCertCache = new MemoryGetCertCache();
_caConnector = new CaConnector(_httpClient, _loggerFactory, clientName, getReqIdCache: null, getCertCache: getCertCache,
getProvCertCache: null);
_storageConnector = new StorageConnector(_loggerFactory, clientName, _httpClient);
_bicaConnector = new BicaConnector(_loggerFactory, clientName, _httpClient);
var opraSigner = new DefaultOperatorSigner(LoadCertificate());
_caConnector.ServerUrl = URL_QICA;
_caConnector.OperatorSigner = opraSigner;
_caConnector.SetRaCodeFromString(_codeRA);
_bicaConnector.ServerUrl = URL_BICA;
_bicaConnector.OperatorSigner = opraSigner;
_bicaConnector.SetRaCodeFromString(_codeRA);
_storageConnector.ServerUrl = URL_STORAGE;
_storageConnector.OperatorSigner = opraSigner;
_storageConnector.SetRaCodeFromString(_codeRA);
}
X509Certificate2 LoadCertificate(string certSN = null)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
string sn = certSN ?? _opraCertSN;
X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindBySerialNumber, sn, true);
if (certificates.Count > 0)
return certificates[0];
foreach (X509Certificate2 x509 in store.Certificates)
{
if (x509.Subject.IndexOf(sn) != -1)
return x509;
}
certificates = store.Certificates;
return certificates[0];
}
[TestMethod]
public async Task IssueCertPaperless_01_SendReq()
{
try
{
_log.LogInformation("IssueCertPaperless_01_SendReq START");
// 1 - ověření operátorského certifikátu
await _bicaConnector.ControlOperatorAsync();
// 2 - získání ID žádosti o certifikát
var lastReqId = await _caConnector.GetReqIdAsync();
var reqId = BigInteger.Parse(lastReqId.ReqId);
++reqId;
var newReqId = reqId.ToString();
File.WriteAllText("newReqId.txt", newReqId);
// 3 - Získání protokolu o podání žádosti
var dn = new GetProtocolDictionaryBuilder()
.AddItem("2.5.4.3", "RaCon UnitTest")
.AddItem("2.5.4.4", "UnitTest")
.AddItem("2.5.4.5", "IDCCZ-202080120")
.AddItem("2.5.4.5", "PASCZ-123456478")
.AddItem("2.5.4.6", "CZ")
.AddItem("2.5.4.42", "RaCon")
.Build();
var protocolData = new GetProtocolBodyDataBuilder()
.SetChallengePwd("xxxx")
.SetDate("14.7.2023")
.SetDateAndTime("14.7.2023 10:48")
.SetDn(dn)
.SetLocality("Zlín")
.SetRaCode(_codeRA)
.SetRaOperator("OPRA Jakub Maňák")
.SetReqId(newReqId)
.SetIdentification("700101123")
.SetAddress("Dlouhá 159, 76000 Zlín")
.SetAlgorithm("RSA")
.SetCertificateTransparency("ANO")
.SetMpsv("NE")
.SetName("RaCon")
.SetOtherDocument("LL 454544545")
.SetPrimaryDocument("OP CZ202080120")
.SetPublishCertificate("ANO")
.SetSecondaryDocument("PP CZ12345678")
.SetSurname("UnitTest")
.SetSigner("RaCon UnitTest")
.Build();
var getProtocolBody = new GetProtocolBodyBuilder()
.SetPayParentId(_payParentId)
.SetLanguage("cs")
.SetBodyData(protocolData)
.SetCertType(_certType)
.SetTemplate(RAConnection.BICA.GetProtocol.TemplateTypes.PROTOCOL)
.Build();
var getProtocolReq = new GetProtocolReqBuilder()
.SetProtocolRequest(getProtocolBody)
.Build();
var protocolResp = await _bicaConnector.GetProtocolAsync(getProtocolReq);
if (protocolResp is null or { Protocol: null or { Length: 0 } })
Assert.Fail("No Protocol returned");
var protocolPdfData = Convert.FromBase64String(protocolResp.Protocol);
File.WriteAllBytes("protocol.pdf", protocolPdfData);
// 4 - Odeslání žádosti na Storage
var pdfProtocolSigned = File.ReadAllText(@"..\..\..\TestFiles\pdf_signed_base64.txt");
var storagePutReqReq = new PutCertificateRequestReqBuilder()
.SetCertProfile(_profile)
.SetCertType(_certType)
.SetOperatorCertificate("64464679099687827124", "9afd0a8bd8921c72c67a1f86efb77e1f82f3fe7b")
.SetPayParent(_payParentId)
.SetProtocol(pdfProtocolSigned, RAConnection.Storage.PutCertificateRequest.StorageFileFormats.pdf)
.SetReqId(newReqId)
.Build();
await _storageConnector.PutCertificateRequestAsync(storagePutReqReq);
// 5 - odeslání žádosti na CA
var reqData = File.ReadAllText(@"..\..\..\TestFiles\PEMRequest.txt");
var keyAndReqData = new KeyAndRequestDataBuilder()
.SetReqID(newReqId.ToString())
.SetRequest(reqData)
.Build();
var certProps = new PutReqCertPropsBuilder()
.SetCertChallengePassword("xxxx")
.SetCertType(_certType)
.SetMpsvik(false)
.Build();
var billingData = new BillingDataBuilder()
.SetPaymentType(RAConnection.CA.PutReq.BillingDataPaymentType.invoice)
.SetPayParentId(_payParentId)
.Build();
var address = new AddressBuilder()
.SetCity("Zlín")
.SetCountry("CZ")
.SetStreetNumber("159")
.SetStret("Dlouhá")
.SetZipCode("76000")
.Build();
var userData = new PutReqUserDataBuilder()
.SetAddress(address)
.SetBirthNumber("701214101")
.SetDocument("idc", "636363663", "CZ")
.SetDocument2("PAS", "69696969", "CZ")
.SetLanguage("cs")
.SetName("RaCon")
.SetSex("M")
.SetSurname("UnitTest")
.SetPhoneNumber("+420654987321")
.Build();
var putReq = new PutReqReqBuilder()
.SetKeyAndRequestData(keyAndReqData)
.SetCertProps(certProps)
.SetBillingData(billingData)
.SetUserData(userData)
.Build();
await _caConnector.PutReqAsync(putReq);
// Pokračovat test metodou IssueCertPaperless_02_WaitForCert, kde proběhne čekání na certifikát
_log.LogInformation("IssueCertPaperless_01_SendReq SUCCESS");
}
catch (Exception ex)
{
_log.LogError(ex, "IssueCertPaperless_01_SendReq FAILED!!!");
throw;
}
}
[TestMethod]
public async Task IssueCertPaperless_02_WaitForCert()
{
try
{
_log.LogInformation("IssueCertPaperless_02_WaitForCert START");
var reqId = File.ReadAllText("newReqId.txt");
// 6 - Získání vydaného certifikátu ze systému CA
var getCertReq = new GetCertReqBodyBuilder()
.SetReqId(reqId)
.Build();
GetCertRespBody resp = null;
do
{
resp = await _caConnector.GetCertificateAsync(getCertReq);
}
while (resp is not null and { ReqInfo: not null and { State: CaConnector.GETCERT_STATE_INPROCESS } });
// Pokračovat test metodou IssueCertpaperless_03_SignAndSave
_log.LogInformation("IssueCertPaperless_02_WaitForCert SUCCESS");
if (resp.ReqInfo.State == CaConnector.GETCERT_STATE_CERTISSUED)
File.WriteAllText("issuedCert.cer", resp.Certificate.Pem);
}
catch (Exception ex)
{
_log.LogError(ex, "IssueCertPaperless_02_WaitForCert FAILED!!!");
throw;
}
}
[TestMethod]
public async Task IssueCertPaperless_03_SignAndSave()
{
try
{
_log.LogInformation("IssueCertPaperless_03_SignAndSave START");
// 6 - Získání certifikátu ze systému CA
var reqId = File.ReadAllText("newReqId.txt");
var getCertReq = new GetCertReqBodyBuilder()
.SetReqId(reqId)
.Build();
var getCertResp = await _caConnector.GetCertificateAsync(getCertReq);
// 7 - získání smlouvy o vydání certifikátu
var dn = new GetProtocolDictionaryBuilder()
.AddItem("2.5.4.3", "Jan Novák")
.AddItem("2.5.4.4", "Novák")
.AddItem("2.5.4.5", "IDCCZ-202080120")
.AddItem("2.5.4.5", "PASCZ-123456478")
.AddItem("2.5.4.6", "CZ")
.AddItem("2.5.4.42", "Jan")
.Build();
var issuerDn = new GetProtocolDictionaryBuilder()
.AddItem("2.5.4.3", "I.CA Development Public CA/RSA 05/2022")
.AddItem("2.5.4.6", "CZ")
.AddItem("2.5.4.10", "První certifikační autorita, a.s.")
.AddItem("2.5.4.5", "NTRCZ-26439395")
.AddItem("2.5.4.11", "Vývoj")
.AddItem("2.5.4.11", "Test")
.Build();
var protocolData = new GetProtocolBodyDataBuilder()
.SetCertDateTimeFrom("14.7.2023 10:45")
.SetCertDateTimeTo("14.7.2024 10:44")
.SetDate("14.7.2023")
.SetDateAndTime("14.7.2023 10:48")
.SetDn(dn)
.SetDnIssuer(issuerDn)
.SetLocality("Zlín")
.SetRaCode("000")
.SetRaOperator("OPRA Jakub Maňák")
.SetSerialNumber("1234123412341234")
.SetReqId("4848481000123")
.SetIdentification("700101123")
.SetAddress("Dlouhá 159, 76000 Zlín")
.SetAlgorithm("RSA")
.SetName("Jan")
.SetSecondaryDocument("PP CZ12345678")
.SetSurname("Novák")
.SetSigner("Jan Novák")
.Build();
var getProtocolBody = new GetProtocolBodyBuilder()
.SetPayParentId(_payParentId)
.SetLanguage("cs")
.SetBodyData(protocolData)
.SetCertType(_certType)
.SetTemplate(RAConnection.BICA.GetProtocol.TemplateTypes.AGREEMENT)
.Build();
var getProtocolReq = new GetProtocolReqBuilder()
.SetProtocolRequest(getProtocolBody)
.Build();
var protocolResp = await _bicaConnector.GetProtocolAsync(getProtocolReq);
if (protocolResp is null or { Protocol: null or { Length: 0 } })
Assert.Fail("No Agreement returned returned");
// 8 - Uložení protokolu a smlouvy na úložiště dokumentů STORAGE
var issuedCert = X509Certificate2.CreateFromPem(getCertResp.Certificate.Pem);
var issuedCertDecSN = TestUtils.HexSnToDec(issuedCert.SerialNumber);
var issuedCertAkid = issuedCert.GetAkid();
var putAgreementBody = new PutCertAgreementReqBuilder()
.SetAgreement(null, RAConnection.Storage.PutCertificateRequest.StorageFileFormats.pdf)
.SetApplicantCertificate(issuedCertDecSN, issuedCertAkid)
.SetCertType(_certType)
.SetIssuedCertificate(issuedCertDecSN, issuedCertAkid)
.SetOperatorCertificate("64464679099687827124", "9afd0a8bd8921c72c67a1f86efb77e1f82f3fe7b")
.SetProtocol(null, RAConnection.Storage.PutCertificateRequest.StorageFileFormats.pdf)
.SetReqId(reqId)
.Build();
await _storageConnector.PutCertificateAgreementAsync(putAgreementBody);
_log.LogInformation("IssueCertPaperless_03_SignAndSave SUCCESS");
}
catch (Exception ex)
{
_log.LogError(ex, "IssueCertPaperless_03_SignAndSave FAILED!!!");
throw;
}
}
}