/// <summary> /// Signs a message and returns a MIME encoded array of bytes containing the signature. /// </summary> /// <param name="arMessage"></param> /// <param name="bPackageHeader"></param> /// <returns></returns> public static byte[] Sign(byte[] arMessage, string signerCert, string signerPassword, out string sContentType) { byte[] bInPKCS7 = new byte[0]; // get a MIME boundary string sBoundary = MIMEBoundary(); // Get the Headers for the entire message. sContentType = "multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=\"sha1\"; boundary=\"" + sBoundary + "\""; // Define the boundary byte array. byte[] bBoundary = ASCIIEncoding.ASCII.GetBytes(Environment.NewLine + "--" + sBoundary + Environment.NewLine); // Encode the header for the signature portion. byte[] bSignatureHeader = ASCIIEncoding.ASCII.GetBytes(MIMEHeader("application/pkcs7-signature; name=\"smime.p7s\"", "base64", "attachment; filename=smime.p7s")); // Get the signature. byte[] bSignature = AS2Encryption.Encode(arMessage, signerCert, signerPassword); // convert to base64 string sig = Convert.ToBase64String(bSignature) + MESSAGE_SEPARATOR; bSignature = System.Text.ASCIIEncoding.ASCII.GetBytes(sig); // Calculate the final footer elements. byte[] bFinalFooter = ASCIIEncoding.ASCII.GetBytes("--" + sBoundary + "--" + Environment.NewLine); // Concatenate all the above together to form the message. bInPKCS7 = ConcatBytes(bBoundary, arMessage, bBoundary, bSignatureHeader, bSignature, bFinalFooter); return(bInPKCS7); }
/// <summary> /// Processes AS2 wrapped EDI message /// </summary> /// <param name="request">The request.</param> /// <param name="dropLocation">The drop location.</param> public void Process(HttpRequest request, string dropLocation) { string sTo = request.Headers["AS2-To"]; string sFrom = request.Headers["AS2-From"]; string dtf = $"{sFrom}_{sTo}_" + DateTime.Now.ToString("ddMMyyyy_hh_mm_ss") + ".txt"; string filename = $"AS2_transaction_{dtf}"; string extractfilename = $"AS2_transaction_extract_{dtf}"; byte[] data = request.BinaryRead(request.TotalBytes); bool isEncrypted = request.ContentType.Contains("application/pkcs7-mime"); bool isSigned = request.ContentType.Contains("application/pkcs7-signature"); string message = string.Empty; Log.DebugFormat($"Process\n" + $"\tFrom : {sFrom}\n" + $"\tTo : {sTo}\n" + $"\tIs Signed : {isSigned}\n" + $"\tIs Encrypted : {isEncrypted}\n" + $"\tContentType string : {request.ContentType}\n" + $"Dump file name : {filename}\n"); if (!isSigned && !isEncrypted) // not signed and not encrypted { message = System.Text.ASCIIEncoding.ASCII.GetString(data); } if (isEncrypted) // encrypted and signed inside { byte[] decryptedData; try { Log.Debug("Decrypting......"); decryptedData = AS2Encryption.Decrypt(data); Log.Debug("Decrypting SUCCESS."); } catch (Exception ex) { Log.Error($"Exception during decrypting {ex.Message}"); if (ex.InnerException != null) { Log.Error($"Inner Exception during decoding {ex.InnerException.Message}"); } throw; } string messageWithContentTypeLineAndMIMEHeaders = System.Text.ASCIIEncoding.ASCII.GetString(decryptedData); // when encrypted, the Content-Type line is actually stored in the start of the message // Require multi split done by 'ExtractPayload' // First segment is data payload - THIS IS EDIFACT/XML data // Second payload is a public key file [Not essential] int firstBlankLineInMessage = messageWithContentTypeLineAndMIMEHeaders.IndexOf(Environment.NewLine + Environment.NewLine); string contentType = messageWithContentTypeLineAndMIMEHeaders.Substring(0, firstBlankLineInMessage); message = AS2MIMEUtilities.ExtractPayload(messageWithContentTypeLineAndMIMEHeaders, contentType); try { System.IO.File.WriteAllText($"{Util.ConfigValues.DropLocation}\\{extractfilename}", message); Log.Debug($"Message Extract written to file {Util.ConfigValues.DropLocation}\\{extractfilename}"); } catch (Exception ex) { Log.Error($"Failed to write message extract to file : {Util.ConfigValues.DropLocation}\\{extractfilename}\n" + $"Exception : {ex.Message}\n"); } string signature = ""; if (isSigned) { //int SecondBlankLineInMessage = message.IndexOf(Environment.NewLine + Environment.NewLine); int signatureHeaderStart = message.IndexOf(Environment.NewLine + "--_"); string messageWithSignature = message; Log.DebugFormat($"Message with embedded signature\n" + $"\tSignature start found at : {signatureHeaderStart}\n" + $"\tSignature start found invalid format : {message.IndexOf('\n' + "--_")}\n"); message = message.Substring(0, signatureHeaderStart); string signaturePart = messageWithSignature.Substring(signatureHeaderStart); int signatureStart = signaturePart.IndexOf(Environment.NewLine + Environment.NewLine); signature = signaturePart.Substring(signatureStart + 4); Log.Debug($"\n----------------------------------------------------------------------------------------------------------------------------------\n" + $"Extracted EDI Message\n {message}\n" + $"----------------------------------------------------------------------------------------------------------------------------------\n"); //TODO :: Kavisha - uncomment after testing if (AS2Encryption.validateSignature(signature) == false) { Log.Error($"Invalid signature {signature}"); return; } } else { int signatureHeaderStart = message.IndexOf(Environment.NewLine + "--_"); // Check if it is marked inside the mesage payload if (signatureHeaderStart >= 0) { //int SecondBlankLineInMessage = message.IndexOf(Environment.NewLine + Environment.NewLine); string messageWithSignature = message; Log.DebugFormat($"Message with embedded signature\n" + $"\tSignature start found at : {signatureHeaderStart}\n" + $"\tSignature start found invalid format : {message.IndexOf('\n' + "--_")}\n"); message = message.Substring(0, signatureHeaderStart); string signaturePart = messageWithSignature.Substring(signatureHeaderStart); int signatureStart = signaturePart.IndexOf(Environment.NewLine + Environment.NewLine); signature = signaturePart.Substring(signatureStart + 4); Log.Debug($"\n----------------------------------------------------------------------------------------------------------------------------------\n" + $"Extracted EDI Message\n {message}\n" + $"----------------------------------------------------------------------------------------------------------------------------------\n"); //TODO :: Kavisha - uncomment after testing if (AS2Encryption.validateSignature(signature) == false) { Log.Error($"Invalid signature {signature}"); return; } } else { Log.Error("Invalid payload [Not signed]"); } } } else { Log.Debug("Non-Encrypted.."); if (isSigned) { Log.Debug("Non-Encrypted signed.."); string messageWithMIMEHeaders = System.Text.ASCIIEncoding.ASCII.GetString(data); message = AS2MIMEUtilities.ExtractPayload(messageWithMIMEHeaders, request.Headers["Content-Type"]); Log.Debug($"Extracted message {message}"); string signaturePart = messageWithMIMEHeaders.Substring(message.Length); string signature = AS2MIMEUtilities.ExtractPayload(signaturePart, request.Headers["Content-Type"]); Log.Debug($"Extracted signature {signature}"); if (AS2Encryption.validateSignature(signature) == false) { Log.Error($"Invalid signature {signature}"); return; } } } try { System.IO.File.WriteAllText($"{Util.ConfigValues.DropLocation}\\{filename}", message); } catch (Exception ex) { Log.Error($"Failed to write dump to file : {Util.ConfigValues.DropLocation}\\{filename}\n" + $"Exception : {ex.Message}\n"); } var grammar = EdiGrammar.NewEdiFact(); var interchange = default(Interchange); using (var stream = new StreamReader($"{Util.ConfigValues.DropLocation}\\{filename}")) { Quote quoteMessage = null; try { interchange = new EdiSerializer().Deserialize <Interchange>(stream, grammar); quoteMessage = interchange.QuoteMessage; } catch (Exception ex) { Log.Error($"Content to EDI deserialization error : {ex.Message}\n" + $"Payload File : {Util.ConfigValues.DropLocation}\\{filename}\n"); throw; } try { if (quoteMessage != null) { if (quoteMessage.MessageName != "220") { return; } WebOrderHeaderModel webOrder = new WebOrderHeaderModel(); webOrder.AS2Identifier = request.Headers["AS2-From"]; quoteMessage.fillWebOrder(webOrder, interchange); InsertOrderToDB(webOrder); Log.Info("Order inserted ----------------"); Log.Info(webOrder.ToString()); } } catch (Exception ex) { Log.Error($"Order insertion error : {ex.Message}"); if (ex.InnerException != null) { Log.Error($"\tInner Exception : {ex.InnerException.Message}"); } throw; } } }
public HttpStatusCode SendFile(Uri uri, string filename, byte[] fileData, string from, string to, ProxySettings proxySettings , int timeoutMs, string signingCertFilename, string signingCertPassword, string recipientPubCertFilename /*with public key*/) { if (String.IsNullOrEmpty(filename)) { throw new ArgumentNullException("filename"); } if (fileData.Length == 0) { throw new ArgumentException("filedata"); } byte[] content = fileData; //Initialise the request HttpWebRequest http = (HttpWebRequest)WebRequest.Create(uri); if (!String.IsNullOrEmpty(proxySettings.Name)) { WebProxy proxy = new WebProxy(proxySettings.Name); NetworkCredential proxyCredential = new NetworkCredential(); proxyCredential.Domain = proxySettings.Domain; proxyCredential.UserName = proxySettings.Username; proxyCredential.Password = proxySettings.Password; proxy.Credentials = proxyCredential; http.Proxy = proxy; } //Define the standard request objects http.Method = "POST"; http.AllowAutoRedirect = true; http.KeepAlive = true; http.PreAuthenticate = false; //Means there will be two requests sent if Authentication required. http.SendChunked = false; http.UserAgent = "PEERCORE AGENT"; //These Headers are common to all transactions http.Headers.Add("Mime-Version", "1.0"); http.Headers.Add("AS2-Version", "1.2"); http.Headers.Add("AS2-From", from); http.Headers.Add("AS2-To", to); http.Headers.Add("Subject", filename); http.Headers.Add("Message-Id", "<AS2_" + DateTime.Now.ToString("hhmmssddd") + ">"); http.Timeout = timeoutMs; string contentType = (Path.GetExtension(filename) == ".xml") ? "application/xml" : "application/EDIFACT"; bool encrypt = !string.IsNullOrEmpty(recipientPubCertFilename); bool sign = !string.IsNullOrEmpty(signingCertFilename); if (!sign && !encrypt) { http.Headers.Add("Content-Transfer-Encoding", "binary"); http.Headers.Add("Content-Disposition", "inline; filename=\"" + filename + "\""); } if (sign) { // Wrap the file data with a mime header content = AS2MIMEUtilities.CreateMessage(contentType, "binary", "", content); content = AS2MIMEUtilities.Sign(content, signingCertFilename, signingCertPassword, out contentType); http.Headers.Add("EDIINT-Features", "multiple-attachments"); } if (encrypt) { if (string.IsNullOrEmpty(recipientPubCertFilename)) { throw new ArgumentNullException(recipientPubCertFilename, "if encrytionAlgorithm is specified then recipientCertFilename must be specified"); } byte[] signedContentTypeHeader = System.Text.ASCIIEncoding.ASCII.GetBytes("Content-Type: " + contentType + Environment.NewLine); byte[] contentWithContentTypeHeaderAdded = AS2MIMEUtilities.ConcatBytes(signedContentTypeHeader, content); string ba2Str = System.Text.Encoding.Default.GetString(content); string s1 = System.Text.Encoding.Default.GetString(signedContentTypeHeader); string s2 = System.Text.Encoding.Default.GetString(contentWithContentTypeHeaderAdded); content = AS2Encryption.Encrypt(contentWithContentTypeHeaderAdded, recipientPubCertFilename, EncryptionAlgorithm.DES3); contentType += "application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\""; } http.ContentType += contentType; http.ContentLength = content.Length; SendWebRequest(http, content); return(HandleWebResponse(http)); }
public HttpStatusCode SendMDN(HttpRequest request, int timeoutMs, string signingCertFilename, string signingCertPassword) { try { string fileData = "This is an automated MDN"; byte[] content = Encoding.ASCII.GetBytes(fileData); OrderDataService OrderDataServ = new OrderDataService(); AS2CommunicationModel commDetails = OrderDataServ.GetAS2CommunicationDetials(request.Headers["AS2-From"]); //Initialise the request HttpWebRequest http = (HttpWebRequest)WebRequest.Create(commDetails.AS2MDNURL); string recipientPubCertFilename = commDetails.CertificateName; //Define the standard request objects http.Method = "POST"; http.AllowAutoRedirect = true; http.KeepAlive = true; http.PreAuthenticate = false; //Means there will be two requests sent if Authentication required. http.SendChunked = false; //http.UserAgent = "PEERCORE AGENT"; //These Headers are common to all transactions http.Headers.Add("Mime-Version", "1.0"); http.Headers.Add("AS2-Version", "1.2"); //http.Headers.Add("Date", DateTime.Now.ToString()); http.Headers.Add("AS2-From", request.Headers["AS2-To"]); http.Headers.Add("AS2-To", request.Headers["AS2-From"]); http.Headers.Add("Subject", "PO MDN"); http.Headers.Add("Message-Id", request.Headers["Message-Id"] != null? request.Headers["Message-Id"]:"0"); http.Timeout = timeoutMs; string contentType = "message/disposition-notification"; bool encrypt = !string.IsNullOrEmpty(recipientPubCertFilename); bool sign = !string.IsNullOrEmpty(signingCertFilename); if (!sign && !encrypt) { http.Headers.Add("Content-Transfer-Encoding", "binary"); http.Headers.Add("Content-Disposition", "inline"); } if (sign) { // Wrap the file data with a mime header content = AS2MIMEUtilities.CreateMessage(contentType, "binary", "", content); content = AS2MIMEUtilities.Sign(content, signingCertFilename, signingCertPassword, out contentType); http.Headers.Add("EDIINT-Features", "multiple-attachments"); } if (encrypt) { string certificateFullPath = ""; if (string.IsNullOrEmpty(recipientPubCertFilename)) { throw new ArgumentNullException(recipientPubCertFilename, "if encrytionAlgorithm is specified then recipientCertFilename must be specified"); } else { certificateFullPath = ConfigValues.CertificateFilePath + recipientPubCertFilename; } byte[] signedContentTypeHeader = System.Text.ASCIIEncoding.ASCII.GetBytes("Content-Type: " + contentType + Environment.NewLine); byte[] contentWithContentTypeHeaderAdded = AS2MIMEUtilities.ConcatBytes(signedContentTypeHeader, content); string ba2Str = System.Text.Encoding.Default.GetString(content); string s1 = System.Text.Encoding.Default.GetString(signedContentTypeHeader); string s2 = System.Text.Encoding.Default.GetString(contentWithContentTypeHeaderAdded); content = AS2Encryption.EncryptMDN(contentWithContentTypeHeaderAdded, certificateFullPath, EncryptionAlgorithm.DES3); // contentType += "multipart/report; report-type=disposition-notification; boundary=\"fredi.boundary.mult.sig.mdn\"; charset=utf-8"; } http.ContentType += contentType; http.ContentLength = content.Length; SendWebRequest(http, content); return(HandleWebResponse(http)); } catch (Exception ex) { Log.Error($"Exception during sending MDN :: {ex.Message}"); throw; } }