Source code for the AS2 Client C# example program posted at EDIINT AS2.  A detailed explanation of the algorithm can be read at "Creating an AS2 Client in Stages".

private void cmdSend_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            int nMdnResult = -1;
            string sErrorMsg = "";

            txtNotification.Text = "";
            txtNotification.Refresh();

            try
            {

                // Get internet mail document object
                mailDocument oMailDocument = oEdiDoc.GetMailDocument();

                //Setting so that syntax for the field "Disposition-Notification-To" is not validated, but treated as a text field
                oMailDocument.AddDefinedHeader("Disposition-Notification-To", MailMessageHeaderTypeConstants.HeaderType_FieldText, RequirementTypeConstants.Requirement_Optional);

                mailMessage oSubjMsg = oMailDocument.GetMessageContent();

                Label1.Text = "importing EDI...";
                Label1.Refresh();
                // For speed, import the EDI file instead of processing.
                if (oSubjMsg.Import(sPath + cmbFile.Text) != 1)
                {
                    MessageBox.Show("Failed to load document");
                }
                else 
                {
                    //specify content type of mesage
                    oSubjMsg.set_HeaderFieldValue("Content-Type", txtContentType.Text);


                    // Configure the security of this message.
                    ediSecurity oSecurity = oSubjMsg.GetSecurity();

                    // Specify the type of encryption and signing algorithm to use
                    oSecurity.EncryptionAlgorithm = sEncryptAlgorithm;
                    oSecurity.AssuranceAlgorithm = sSigningHash;

                    // Recipient's certificate to encrypt message.
                    oSecurity.SetCertSubjectNameByLocation(sRecCertSubjName, sRecCertStoreLocation, sRecCertStoreName, sRecServiceProvider);

                    // Sender's certificate to sign message.
                    oSecurity.SetCertSignerNameByLocation(sSignCertSubjName, sSignCertStoreLocation, sSignCertStoreName, sSignServiceProvider);

                    if (ckSendEncrypted.Checked == true)
                    {
                        oSecurity.EnableEncryption = true;
                    }
                    else
                    {
                        oSecurity.EnableEncryption = false;
                    }

                    if (ckSendSigned.Checked == true)
                    {
                        oSecurity.EnableAssurance = true;
                    }
                    else
                    {
                        oSecurity.EnableAssurance = false;
                    }

                    if (ckCompression.Checked == true)
                    {
                        oSecurity.EnableCompression = true;
                    }
                    else
                    {
                        oSecurity.EnableCompression = false;
                    }

                    //This is how the content of the file looks like before it is prepared with all
                    //the security configuration.  This is also how your trading partner would see
                    //the content of your file after he decrypts the AS2 message you send him.
                    //(This is the garbled section of the "Sent_SampleEdiX12_850.x12)"
                    oMailDocument.Save(sPath + "Output\\MessageContent.txt");

                    // Calculate the MIC value from the original message.
                    // string sSubjMicValue;

                    if (oSecurity.EnableEncryption || oSecurity.EnableAssurance)
                    {

                        //RFC4130: For any signed messages, the MIC to be returned is calculated
                        //on the RFC1767/RFC3023 MIME header and content.
                        //Canonicalization on the MIME headers MUST be performed before
                        //the MIC is calculated, since the sender requesting the signed
                        //receipt was also REQUIRED to canonicalize.

                        //RFC4130: For encrypted, unsigned messages, the MIC to be returned is
                        //calculated on the decrypted RFC 1767/RFC3023 MIME header and
                        //content.  The content after decryption MUST be canonicalized
                        //before the MIC is calculated.

                        sSubjMicValue = oSubjMsg.GenerateDigest(MailMessagePartTypeConstants.Message_All, EncodingMechanismTypeConstants.EncodeType_Base64);
                    }
                    else
                    {
                        //'RFC4130: For unsigned, unencrypted messages, the MIC MUST be calculated
                        //'over the message contents without the MIME or any other RFC
                        //'2822 headers, since these are sometimes altered or reordered by
                        //'Mail Transport Agents (MTAs).
                        sSubjMicValue = oSubjMsg.GenerateDigest(MailMessagePartTypeConstants.Message_Body, EncodingMechanismTypeConstants.EncodeType_Base64);
                    }

                    txtMIC.Text = sSubjMicValue;
                    txtMIC.Refresh();

                    // Prepare the message with the imported EDI file so that the security configurations
                    //   can be applied.
                    if (oSubjMsg.Prepare() != 1)
                    {
                        MessageBox.Show("Failed to prepare Message");
                    }
                    else
                    {

                        if (ckBase64.Checked == true)
                        {
                            oMailDocument.Save(sPath + "Output\\After_PrepBeforeBase64.txt");
                            oSubjMsg.set_HeaderFieldValue("Content-Transfer-Encoding", "base64");
                            oSubjMsg.Prepare();
                        }

                        // Put globally unique ID as Message-ID.
                        oSubjMsg.set_HeaderFieldValue("Message-ID", "1234567890@evalusercompany.com");  //txtMessageID.Text

                        // Put AS2 version.
                        oSubjMsg.set_HeaderFieldValue("AS2-Version", "1.0");
                        // Put AS2-To header value.
                        oSubjMsg.set_HeaderFieldValue("AS2-To", txtAs2To.Text);
                        // Put AS2-From header value.
                        oSubjMsg.set_HeaderFieldValue("AS2-From", txtAS2From.Text);


                        if (ckAsynchronous.Checked == true)
                        {
                            // For asynchronous, must set a syntactically correct URI at 'Receipt-delivery-option'.

                            oSubjMsg.set_HeaderFieldValue("Receipt-delivery-option", txtReceiptDeliveryOption.Text);
                        }


                        if (ckReceiveMdn.Checked == true)
                        {
                            // Request Acknowledgment by adding "Disposition-Notification-To" header.
                            //  Value must be present but holds no meaning in an AS2 environment.
                            oSubjMsg.set_HeaderFieldValue("Disposition-Notification-To", txtDispositionNotificationTo.Text);

                            if (ckReceiveSigned.Checked == true) 
                            {
                                // Request the MDN to be signed.
                                string sDnOpts;
                                sDnOpts = "signed-receipt-protocol=optional,pkcs7-signature;";
                                sDnOpts = sDnOpts + "signed-receipt-micalg=optional,sha1";
                                oSubjMsg.set_HeaderFieldValue("Disposition-Notification-Options", sDnOpts);
                            }
                        }  //ckReceiveMdn.Value = 1

                        //' Save the document before sending.
                        if (oMailDocument.Save(sPath + "Output\\Sent_File.txt") != 1)
                        {
                            MessageBox.Show("Failed to save message");
                        }
                        else
                        {
                            // Get the transports object for internet mail documents.
                            ediTransports oTransports = oMailDocument.GetTransports();

                            // Create a transport token, and set the information of the
                            //   HTTP server where to send the file.
                            ediTransport oTransport = oTransports.CreateTransport();
                            oTransport.SetHTTP();
                            // *** Note that FREDI requires the forward-slash (/) at the end of the HTTP URI for posting
                            oTransport.InternetUrl = cmbUrl.Text;
                            oTransport.TimeOut = 7200;

                            // Configure the ISAPI information in the HTTP config object.  These settings are specific
                            //   only to the FREDI ISAPI extension and the ActiveX components that it drives.
                            ediHttpCfg oHttpCfg = oTransport.GetHttpCfg();  
                            oHttpCfg.SendVerb = "POST";

                            // If there are no errors received from the HTTP server and data is
                            //   received, we want that data to be processed.
                            oHttpCfg.EnableProcessResponse = true;

                            // Specify the file name to save the received raw data from the server.
                            //   The raw data is saved only if the transfer is successful.
                            oHttpCfg.ResponseOutput = sPath + "output\\Receive.Mime.Txt";

                            // Send the file to the server. If it's a synchronous connection, then
                            //   wait for incoming data from the server.
                            //   Execution on the server side may take several minutes
                            //   which means that the Send() statement will be blocked for the
                            //   same period until processing the file has been completed and
                            //   then received, or if an error has occurred.
                            Label1.Text = "sending...";
                            Label1.Refresh();

                            oTransport.Send(cmbFile.Text);

                            if (ckReceiveMdn.Checked == true && ckAsynchronous.Checked == false ) //synchronous
                            {
                                // If the send is successful, we expect an MDN to be received from the server
                                //   during the Send call.  This is because this session is a synchronous session
                                //   and the MDN must be received in the same HTTP connection that the message
                                //   itself was sent.  Since the MDN is already received, get the MDN message and save
                                //   the MDN to an external file.
                                mailMessage oMDN = oMailDocument.GetMDN();
                                txtNotification.Text = oMDN.GetMsgString();
                                txtNotification.Refresh();

                                mailMessages oMdnMsgs = oMDN.GetMessages();

                                //Reading the MDN
                                for (int ii=1; ii <= oMdnMsgs.Count; ii++)
                                {
                                    mailMessage oMdnMsg = oMdnMsgs.GetMessageContent(ii);

                                    mailContentType oContentType = oMdnMsg.GetContentType();

                                    if (oContentType.MediaType == "message" && oContentType.SubType == "disposition-notification")
                                    {
                                        mailMessages oSubMessages = oMdnMsg.GetMessages();

                                        mailMessage oDisposition = oSubMessages.GetMessageContent(1);

                                        if (oDisposition != null)
                                        {
                                            mailHeaders oHeaders = oDisposition.GetHeaders();

                                            string sHeaders = "";
                                            sErrorMsg = "";
                                            mailHeader oHeader = null; 

                                            for (int i = 1; i <= oHeaders.Count; i++)
                                            {
                                                mailHeader.Set(ref oHeader, oHeaders.GetHeaderByIndex(i));      //oHeader = oHeaders.GetHeaderByIndex(i)
                                                sHeaders = sHeaders + oHeader.Name + " : " + oHeader.Value + "\r\n";
                                                if (oHeader.Name.ToLower()  == "disposition"  )
                                                {
                                                    nMdnResult = 0;
                                                }
                                                else if ( oHeader.Name.ToLower() == "warning")
                                                {
                                                    nMdnResult = 1;
                                                    sErrorMsg = sErrorMsg + oHeader.Value + "\r\n";
                                                }
                                                else if (oHeader.Name.ToLower() == "error")
                                                {
                                                    nMdnResult = 2;
                                                    sErrorMsg = sErrorMsg + oHeader.Value + "\r\n";
                                                }

                                            }    //Each oHeader In oHeaders

                                            // Verify MIC from the receiver.

                                            mailHeader.Set(ref oHeader, oHeaders.GetHeaderByName("Received-Content-MIC"));
                                            if (oHeader != null)
                                            {

                                                string sRecvMicFldValue;

                                                sRecvMicFldValue = oHeader.Value;

                                                int lPos;
                                                lPos = sRecvMicFldValue.IndexOf(",");
                                                if (lPos == 0 && sRecvMicFldValue.Length > 0)
                                                {
                                                    MessageBox.Show("Invalid Received-Content-MIC field value");
                                                }
                                                else
                                                {
                                                    string sMicValue;
                                                    string sMicAlg;

                                                    sMicValue = sRecvMicFldValue.Substring(0, lPos);
                                                    sMicAlg = sRecvMicFldValue.Substring(lPos);

                                                    // Compare the MIC of the subject document to MIC received by received.
                                                    if (sMicValue != sSubjMicValue )
                                                    {
                                                        MessageBox.Show("Recipient received invalid document. Subject MIC=" + sSubjMicValue + ", Recv MIC=" + sMicValue);
                                                    }
                                                }   //lPos == 0 && Len(sRecvMicFldValue) > 0


                                                oHeader.Dispose();
                                            }   //oHeader != null

                                            oHeaders.Dispose();

                                        }   //oDisposition != null

                                        oDisposition.Dispose();
                                        oSubMessages.Dispose();

                                    }   //oContentType.MediaType 

                                    oContentType.Dispose();
                                    oMdnMsg.Dispose();

                                }    // for ii

                                oMDN.Save(sPath + "Output\\Received_MDN.Txt");
                                oMdnMsgs.Dispose();
                                oMDN.Dispose();


                            }  //ckReceiveMdn.Value = 1 And ckAsynchronous.Value = 0

                            Label1.Text = "";
                            Label1.Refresh();

                            if (nMdnResult == 0 )
                            {
                                MessageBox.Show("Successfully sent.");
                            }
                            else if ( nMdnResult == 1 )
                            {
                                MessageBox.Show("The message was successfully sent but there were warnings.");
                                MessageBox.Show(sErrorMsg, "MDN Warning");
                            }
                            else if (nMdnResult == 2 )
                            {
                                MessageBox.Show("An error occurred during transmission");
                                MessageBox.Show(sErrorMsg, "MDN Error");
                            }

                            oHttpCfg.Dispose();
                            oTransport.Dispose();

                            oTransports.Clear();
                            oTransports.Dispose();

                        }  //oMailDocument.Save(sPath + "Output\Sent_File.txt") != 1

                    }  //oSubjMsg.Prepare != 1

                }  //oSubjMsg.Import(sPath + cmbFile.Text) != 1

                oSubjMsg.Dispose();
                oMailDocument.Dispose();

                oEdiDoc.Close();

                Cursor = Cursors.Default;
            }
            catch( System.Exception ex)
                {
                txtNotification.Text = txtNotification.Text + "\r\n" + "Severe error. " + ex.Message;
                txtNotification.Refresh();
                }

            Cursor = Cursors.Default;
        }

    Click here to download a trial version of the Framework EDI