Beispiel #1
0
        /// <summary>
        /// Antrag versenden
        /// </summary>
        /// <param name="application">Antrag</param>
        /// <param name="p10Data">PKCS#10-Daten</param>
        /// <param name="certStore">Zertifikat-Speicher für die Bildung der Zertifikatskette und die Abfrage des Empfänger-Zertifikats</param>
        /// <param name="pfx">Zertifikat für die Verschlüsselung - wenn nicht gesetzt, dann wird ein Erstantrag erstellt</param>
        /// <param name="validator">The validator for the OSTC certificate request document</param>
        /// <returns>Das Ergebnis der Antragstellung</returns>
        public async Task <OstcApplicationResult> SendApplicationAsync([NotNull] OstcAntrag application, [NotNull] Pkcs10Data p10Data, [CanBeNull] IOstcCertificateStore certStore, [CanBeNull] Pkcs12Store pfx, [CanBeNull] IValidator validator)
        {
            var senderId = SenderId.FromBnrOrIk(application.Antragsteller.IK_BN);

            var    applicationData = OstcUtils.Serialize(application, Iso88591);
            string mimeType;

            if (pfx == null)
            {
                mimeType = "text/xml";
            }
            else
            {
                var alias = pfx.Aliases.Cast <string>().FirstOrDefault(pfx.IsKeyEntry);
                if (alias != null)
                {
                    var certEntry   = pfx.GetCertificate(alias);
                    var keyEntry    = pfx.GetKey(alias);
                    var certificate = certEntry.Certificate;
                    var key         = keyEntry.Key;
                    if (certStore == null)
                    {
                        throw new ArgumentNullException(nameof(certStore));
                    }
                    var certChain = certStore.GetChain(certificate).ToList();
                    Debug.Assert(certChain[0].SubjectDN.Equivalent(certificate.SubjectDN));
                    certChain.RemoveAt(0);
                    applicationData = OstcUtils.SignData(applicationData, key, certificate, certChain);
                    var receiverCert = certStore.GetCertificate(senderId.CommunicationServerReceiver);
                    applicationData = OstcUtils.EncryptData(applicationData, receiverCert);
                    mimeType        = "application/octet-stream";
                }
                else
                {
                    mimeType = "text/xml";
                }
            }

            var date        = DateTime.ParseExact(application.Antragsinfo.Datum, "dd.MM.yyyy", CultureDe);
            var p10FileName = $"{senderId.Id}.p10";
            var xmlFileName = $"{senderId}_{date:ddMMyyyy}.xml";

            var reqSendAppContent = new MultipartFormDataContent
            {
                { new StringContent("4000"), "MAX_FILE_SIZE_XML" },
                {
                    new ByteArrayContent(applicationData)
                    {
                        Headers =
                        {
                            ContentType = MediaTypeHeaderValue.Parse(mimeType),
                        }
                    },
                    "xml_Datei",
                    xmlFileName
                },
                { new StringContent("4000"), "MAX_FILE_SIZE_P10" },
                {
                    new ByteArrayContent(p10Data.CertRequestDer)
                    {
                        Headers =
                        {
                            ContentType = MediaTypeHeaderValue.Parse("application/octet-stream"),
                        }
                    },
                    "p10_Datei",
                    p10FileName
                }
            };

            var requestSendApp = new HttpRequestMessage(HttpMethod.Post, Network.Requests.Upload)
            {
                Content = reqSendAppContent,
            };

            var responseSendApp = await _client.SendAsync(requestSendApp);

            responseSendApp.EnsureSuccessStatusCode();

            var responseHtml    = DecodeResponse(await responseSendApp.Content.ReadAsStreamAsync());
            var responseFileUrl = GetResponseFileUrl(responseHtml);

            if (responseFileUrl == null)
            {
                throw new OstcException("Von der ITSG wurde kein Pfad zu einer Rückmeldungs-Datei geliefert.");
            }

            var downloadResponse = await _client.GetAsync(responseFileUrl);

            downloadResponse.EnsureSuccessStatusCode();
            var resultData = await downloadResponse.Content.ReadAsByteArrayAsync();

            var resultXml = XDocument.Load(new MemoryStream(resultData));

            var trustCenterNode = resultXml
                                  .Elements("OSTCAntrag")
                                  .Elements("Trustcenter")
                                  .FirstOrDefault();

            if (trustCenterNode == null)
            {
                throw new InvalidOperationException("Die von der ITSG zurückgelieferte Antwort lag in einem unbekannten Format vor.");
            }
            var returnCodeNode = trustCenterNode
                                 .Elements("Returncode")
                                 .FirstOrDefault();

            if (returnCodeNode == null)
            {
                throw new InvalidOperationException("Die von der ITSG zurückgelieferte Antwort lag in einem unbekannten Format vor.");
            }
            var returnCode    = Convert.ToInt32(returnCodeNode.Value.Trim(), 10);
            var errorCodeNode = trustCenterNode.Elements("Fehlercode").FirstOrDefault();

            if (errorCodeNode == null)
            {
                throw new InvalidOperationException("Die von der ITSG zurückgelieferte Antwort lag in einem unbekannten Format vor.");
            }
            var errorCodes = errorCodeNode.Value.Trim()
                             .Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)
                             .Select(x => Convert.ToInt32(x.Trim(), 10))
                             .ToList();

            var inputNumberNode = trustCenterNode.Elements("Eingangsnummer").FirstOrDefault();

            if (inputNumberNode == null)
            {
                throw new InvalidOperationException("Die von der ITSG zurückgelieferte Antwort lag in einem unbekannten Format vor.");
            }
            var inputNumber = inputNumberNode.Value.Trim();
            var result      = new OstcApplicationResult()
            {
                OrderId    = inputNumber,
                ReturnCode = returnCode,
                ErrorCodes = errorCodes,
            };

            return(result);
        }
Beispiel #2
0
        /// <summary>
        /// Antragstellung
        /// </summary>
        /// <param name="application">Antrag</param>
        /// <param name="certStore">Zertifikat-Speicher für die Ermittlung der Zertifikatskette des Absender-Zertifikats</param>
        /// <param name="pfx">Absender-Zertifikat für die Signierung des Antrags</param>
        /// <returns>Ergebnis der Antragstellung</returns>
        public async Task <OstcApplicationResult> SendApplicationAsync([NotNull] OstcAntrag application, [CanBeNull] IOstcCertificateStore certStore, [CanBeNull] Pkcs12Store pfx)
        {
            var now = DateTime.Now;

            application.Antragsteller.IK_BN = Sender.SenderId.ToString();

            RsaPrivateCrtKeyParameters rsaPrivateKey;
            AsymmetricCipherKeyPair    rsaKeyPair;
            X509Certificate            certificate;

            if (pfx != null)
            {
                var alias = pfx.Aliases.Cast <string>().First(pfx.IsKeyEntry);
                rsaPrivateKey = (RsaPrivateCrtKeyParameters)pfx.GetKey(alias).Key;
                var rsaPublicKey = new RsaKeyParameters(false, rsaPrivateKey.Modulus, rsaPrivateKey.PublicExponent);
                rsaKeyPair  = new AsymmetricCipherKeyPair(rsaPublicKey, rsaPrivateKey);
                certificate = pfx.GetCertificate(alias).Certificate;
            }
            else
            {
                var keyPairGen = new RsaKeyPairGenerator();
                keyPairGen.Init(new KeyGenerationParameters(new SecureRandom(), 2048));
                rsaKeyPair    = keyPairGen.GenerateKeyPair();
                rsaPrivateKey = (RsaPrivateCrtKeyParameters)rsaKeyPair.Private;
                certificate   = null;
            }

            var requester  = new Requester(application.Antragsteller.IK_BN, application.Antragsteller.Firma, application.Antragsteller.Nachname);
            var p10Creator = new Pkcs10Creator(requester, rsaKeyPair);
            var p10Data    = p10Creator.CreateRequest();

            application.Antragsinfo.Requestschlüssel = p10Data.CertRequestDer;

            var applicationData = OstcUtils.Serialize(application, Iso88591);

            ValidateData(applicationData, OstcMessageType.ApplicationData);

            var receiver = Sender.SenderId.CommunicationServerReceiver;

            if (certificate != null)
            {
                Debug.Assert(certStore != null, "certStore != null");
                var certChain = certStore.GetChain(certificate).ToList();
                Debug.Assert(certChain[0].SubjectDN.Equivalent(certificate.SubjectDN));
                certChain.RemoveAt(0);
                applicationData = OstcUtils.SignData(applicationData, rsaPrivateKey, certificate, certChain);
                var receiverCert = certStore.GetCertificate(receiver);
                applicationData = OstcUtils.EncryptData(applicationData, receiverCert);
            }

            var fileName = $"{application.Antragsteller.IK_BN}_{now.Date:ddMMyyyy}.xml";
            var message  = new TransportRequestType()
            {
                version         = SupportedVersionsType.Item11,
                profile         = ExtraProfileOstc,
                TransportHeader = CreateRequestHeader(now, OstcDataType.Application, ExtraScenario.RequestWithAcknowledgement),
                TransportBody   = new TransportRequestBodyType
                {
                    Items = new object[]
                    {
                        new DataType
                        {
                            Item = new Base64CharSequenceType()
                            {
                                Value = applicationData,
                            },
                        },
                    },
                },
            };

            if (certificate != null)
            {
                message.TransportPlugIns = new AnyPlugInContainerType
                {
                    Items = new object[]
                    {
                        new DataTransformsType
                        {
                            version    = "1.1",
                            Encryption = new[]
                            {
                                new EncryptionType
                                {
                                    order     = "1",
                                    Algorithm = new EncryptionAlgorithmType
                                    {
                                        id            = ExtraEncryption.Pkcs7,
                                        Specification = new SpecificationType
                                        {
                                            url  = "http://www.gkv-datenaustausch.de",
                                            name = "Security-Schnittstelle fuer den Datenaustausch im Gesundheitswesen",
                                        },
                                    },
                                },
                            },
                        },
                        new DataSourceType
                        {
                            version       = "1.1",
                            DataContainer = new DataContainerType
                            {
                                type             = ExtraContainerType.File,
                                name             = fileName,
                                created          = now,
                                createdSpecified = true,
                                encoding         = ExtraContainerEncoding.Utf8,
                            }
                        },
                    },
                };
            }

            ValidateRequest(message, OstcMessageType.Application);

            var messageData = OstcExtraSerializer.Iso88591.Serialize(message);
            var request     = CreateRequest(Network.Requests.Application);

            using (var requestStream = await Task.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, null))
            {
                requestStream.Write(messageData, 0, messageData.Length);
            }

            using (var response = await Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null))
            {
                var serializer   = new XmlSerializer(typeof(TransportResponseType));
                var responseData = (TransportResponseType)serializer.Deserialize(response.GetResponseStream());

                var flags = responseData.TransportHeader.GetFlags().ToList();
                if (flags.Any(x => x.weight == ExtraFlagWeight.Error))
                {
                    throw new Ostc2Exception(flags);
                }

                return(new OstcApplicationResult
                {
                    OrderId = responseData.TransportHeader.ResponseDetails.ResponseID.Value,
                    Pkcs10 = p10Data.CertRequestDer,
                    RSA = rsaPrivateKey,
                    Hash = p10Data.PublicKeyHashRaw,
                });
            }
        }