Manifest-025 'ChecksumAugmentationNum' Issue on .net - c#

I am submitting the ACA forms(tax year:2016) to the IRS, getting the below error
<ns3:FormBCTransmitterSubmissionDtl xmlns="urn:us:gov:treasury:irs:ext:aca:air:ty16" xmlns:ns2="urn:us:gov:treasury:irs:common" xmlns:ns3="urn:us:gov:treasury:irs:msg:form1094-1095BCtransmittermessage">
<ACATransmitterSubmissionDetail>
<TransmitterErrorDetailGrp>
<ns2:ErrorMessageDetail>
<ns2:ErrorMessageCd>MANIFEST-025</ns2:ErrorMessageCd>
<ns2:ErrorMessageTxt>Manifest 'ChecksumAugmentationNum' must match the IRS-calculated 'ChecksumAugmentationNum' value of the transmission</ns2:ErrorMessageTxt>
</ns2:ErrorMessageDetail>
</TransmitterErrorDetailGrp>
</ACATransmitterSubmissionDetail>
Attached is our MTOM format we are using to send it through A2A.
https://www.dropbox.com/home?preview=samplemtom.txt
I am also tried the ChecksumAugmentationNum value set as Lower case also.

Have you successfully transmitted for Tax Year 2015? I have seen another post related to this issue, but have not run into this issue while sending TY2015 (to AATS or Production) or TY2016 records to AATS. My checksum calculation has not changed, and is very simple.

I have two methods I use to create the checksum: GetChecksum(string) and GetMD5Hash(MD5, string). This approach worked for TY2015, and I expect it to work for TY2016. IIRC, I took this approach directly from MSDN.
The string I pass into the GetChecksum method is the contents of the Form Data Attachment. In my process, I output the XML document into the file system for audit purposes, so the attachment is a physical file for me to use and reference. I read the attachment into a string variable using File.ReadAllText(string path) method.
After generating the checksum my process also will check the checksum against the database and return whether or not that checksum exists (meaning it was used by another form). In the case where this is true, then I update the Contact Suffix, regenerate the Form Data and then regenerate the checksum; this is per the IRS rules for transmission.
This is what is currently working for me, and hopefully this helps you.
Application Callers:
This is what I am doing to call the Checksum calculation functions/routines. It should be noted, I am physically writing each Form Data XML file to the File System, then reading from that.
string AttachmentFileContents = "";
AttachmentFileContents = File.ReadAllText(FormDataFilePath);
string checkSumAugmentationNumber = new Checksum().GetChecksum(AttachmentFileContents);
Checksum Methods:
These are the two methods I use for Checksum Calculation.
public string GetChecksum(string stringToEncrpyt)
{
string hash = "";
using(MD5 md5Hash = MD5.Create())
{
hash = GetMD5Hash(md5Hash, stringToEncrpyt);
}
return hash;
}
private string GetMD5Hash(MD5 md5Hash, string input)
{
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.Length; i++)
{
sb.Append(data[i].ToString("x2"));
}
return sb.ToString();
}

Related

Trouble with replacing bytes in binary files

There are two programs involved. The first one has a string like "##########". The second one is a config tool to find "##########" and replace this string with user input from a textbox.
Now I have trouble in the replacing part. Here is the code.
//This is code from first program:
string myIP = "####################";
string myPort = "%%%%%%%%";
int port = Int32.Parse(myIP );
tcpClient.Connect(myIP , port);
//This is code from second program:
//Get bytes from textbox:
byte[] byte_IP = new byte[60];
byte_IP = System.Text.Encoding.ASCII.GetBytes(textBox1_ip.Text);
//Get all bytes in the first program:
byte[] buffer = File.ReadAllBytes(#"before.exe");
//Replace string with textbox input, 0x1c00 is where the "#" starts:
Buffer.BlockCopy( byte_IP, 0, buffer, 0x1c00, byte_IP.Length);
//Build a new exe:
File.WriteAllBytes(#"after.exe", buffer);
However, I get "127.0.0.1#.#.#.#.#.#." in the new exe. But I need "1.2.7...0...0...1........." to process as a valid host.
First I'd like to reiterate what has already been said in the comments: there are simpler ways to handle this stuff. That's what config files are for, or registry settings.
But if you absolutely must...
First, you have to match the encoding that the framework expects. Is the string stored as UTF8? UTF16? ASCII? Writing data in the wrong encoding will turn it into pure garbage, almost every time. Generally for strings in code like you're looking for you'll be wanting to use Encoding.UNICODE.
Next, you need some way to deal with strings of different lengths. The buffer you define needs to be large enough to contain the widest string you want to be able to set - 15 bytes for dotted numeric IPv4 addresses - but you have to allow for the minimum of 7 characters. Padding the remainder and removing that padding before using the value will probably suffice.
The minimum program I could think to use for testing this was:
class Program
{
static void Main(string[] args)
{
var addr = "###.###.###.###".TrimEnd();
Console.WriteLine("Address: [{0}]", addr);
}
}
Now in your patcher you will need to locate the starting position in the file and overwrite the bytes with the new string's bytes. Here's a Patch method, which calls a FindString method that you will have to write yourself:
static void PatchFile(string filename, string searchString, string replaceString)
{
// Open the file
using (var file = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
{
// Locate the search string in the file (needs to be implemented)
long pos = FindString(file, searchString);
if (pos < 0)
return;
// Pad and limit replacement string, then convert to bytes
string rep = string.Format("{0,-" + searchString.Length + "}", replaceString).Substring(0, searchString.Length);
byte[] replaceBytes = Encoding.Unicode.GetBytes(rep);
// Overwrite the located bytes with the replacement
file.Position = pos;
file.Write(replaceBytes, 0, replaceBytes.Length);
}
}
Hopefully it makes sense.

Change the hash of a PE executable by changing the checksum header

I am writing a code that calculates the MD5/SHA256 of a program and later I want to be able to change it.
I wrote the code for calculating the MD5/SHA256, which is:
using (var md5 = MD5.Create())
{
using (var stream = File.OpenRead(textBox1.Text))
{
MessageBox.Show(BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", ""));
}
}
using (var sha256 = SHA256.Create())
{
using (var stream = File.OpenRead(textBox1.Text))
{
MessageBox.Show(BitConverter.ToString(sha256.ComputeHash(stream)).Replace("-", ""));
}
}
Next I want to be able to change the values of MD5/SHA256 for the specified file. I have searched and all I found was this class:
class FileUtils
{
#region VARIABLES
private const int OFFSET_CHECKSUM = 0x12;
#endregion
#region METHODS
public static ushort GetCheckSum(string fileName)
{
if (!File.Exists(fileName))
throw new FileNotFoundException("Invalid fileName");
return GetCheckSum(File.ReadAllBytes(fileName));
}
public static ushort GetCheckSum(byte[] fileData)
{
if (fileData.Length < OFFSET_CHECKSUM + 1)
throw new ArgumentException("Invalid fileData");
return BitConverter.ToUInt16(fileData, OFFSET_CHECKSUM);
}
public static void WriteCheckSum(string sourceFile, string destFile, ushort checkSum)
{
if (!File.Exists(sourceFile))
throw new FileNotFoundException("Invalid fileName");
WriteCheckSum(File.ReadAllBytes(sourceFile), destFile, checkSum);
}
public static void WriteCheckSum(byte[] data, string destFile, ushort checkSum)
{
byte[] checkSumData = BitConverter.GetBytes(checkSum);
checkSumData.CopyTo(data, OFFSET_CHECKSUM);
File.WriteAllBytes(destFile, data);
}
#endregion
}
Which I don't really understand how it works and only changes the MD5. Is there an easier way to do this, for not so advanced users? If this class works for what I need, could someone explain to me how can I use it?
Edit: I am aware that the MD5 of the file can't be changed, my goal is not to change the MD5 of the actual file, I want to add some contents to the file which would change the MD5 and by doing that I want the file to remain unchanged in functionalities.
As far as I understand, you have or want two copies of the same PE executable file. Now you want to change either or both of these files, so that when you calculate a hash of the file's contents, they are different.
If you change the checksum, chances are the executable won't run anymore. If you're OK with that, you can easily use the class that you showed. It seems to assume a checksum consists of two bytes and is offset at byte 0x12 in the executable. I can't verify right now that it is correct, but at a glance it doesn't seem to be.
Anyway you can create your unique checksum per file and set it:
FileUtils.WriteCheckSum(sourceFile, destFile1, 1);
FileUtils.WriteCheckSum(sourceFile, destFile2, 2);
Now the two files will bear different contents, so the hash of their contents will be different.
You can't just decide that you want your file to have a different hash because the hash is a direct result of the data stored in that file. Two identical files, in terms of what they contain, will always produce the same hash, regardless of what their names are.
Any changes to the content the file itself will result in an entirely different hash value.
MD5 is computed by passing bytes(a file for example) and representing them uniquely in hexadecimal, You don't change the "MD5" of a file, the result MD5 will change as the file changes.

Md5 Password in AS3

I have a problem recreating a password that's hashed in C#. In an online project when a user do the registration process his password is save after passing for this function:
private static string ToMD5Hash(string inputString)
{
using (MD5 md5 = MD5.Create())
{
byte[] data = Encoding.Unicode.GetBytes(inputString);
byte[] hash = md5.ComputeHash(data);
return Convert.ToBase64String(hash);
}
}
I'm working on an offline version that at some point will do a sync with the online version and I can't reproduce the same results on AS3 (Adobe Air). For example the password "1234" after passing to the C# code will be "DwN1hMmef9T0+MWVUPj1Bw==".
Can someone help me out?
My AS3 code is like this:
private function encode():void
{
var ba:ByteArray = new ByteArray();
ba.writeMultiByte("1234","unicode");
var str:String = MD5.hash(ba.toString());
var ba2:ByteArray = new ByteArray();
ba2.writeMultiByte(str.toString(),"unicode");
var encoder:Base64Encoder = new Base64Encoder();
encoder.encodeUTFBytes(ba2.toString());
trace(encoder.toString());
}
When I do the ba.writeMultiByte("1234","unicode"); I get exactly the same ByteArray as in the C# but when I do the MD5.hash(ba.toString()); the new ByteArray is different.
So it looks like it may be a bug in as3corelib's implementation of writing the bits to the digest ByteArray.
It seemingly writes them in big endian format, rather than little endian. Or more specifically, it writes the bits as a collection of 4 integers rather than a collection of bytes, and in the process it mangles the byte order of the bits (which is why you are seeing different Base64 results -- the bytes are in a different order).
You can address this bug by adding on line 184 of MD5.as, in as3corelib, insert the following one line of code:
digest.endian = Endian.LITTLE_ENDIAN;
Also make sure you add an import at the top of the file for import flash.utils.Endian. I've created a public gist of the changes available here
Then it should generate the same byte order as c#, and then it should Base64 encode the same way. I verified it using the following as3 function:
private function encode():void
{
var ba:ByteArray = new ByteArray();
ba.endian = Endian.BIG_ENDIAN
ba.writeMultiByte("1234","unicode");
var str:String = MD5.hashBytes(ba);
var encoder:Base64Encoder = new Base64Encoder();
encoder.encodeBytes(MD5.digest);
trace(encoder.toString()); // DwN1hMmef9T0+MWVUPj1Bw==
}
Look at this.
Be aware that the original download mentioned in that site has a few bugs, so that you have to use the corrected vesion that you can find in the same post.
If you're using AS3CoreLib, do it this way:
Different MD5 with as3corelib.

Write to CSV file and export it?

In C# ASP.net, could someone show me how I can write entries from an Array/List to a CSV file on the server and then open the file? I think the second part would be something like - Response.Redirect("http://myserver.com/file.csv"), however not sure on how to write the file on the server.
Also if this page is accessed by many users, is it better to generate a new CSV file every time or overwrite the same file? Would there be any read/write/lock issues if both users try accessing the same CSV file etc.?
Update:
This is probably a silly question and I have searched on Google but I'm not able to find a definitive answer - how do you write a CSV file to the webserver and export it in C# ASP.net? I know how to generate it but I would like to save it to www.mysite.com/my.csv and then export it.
Rom, you're doing it wrong. You don't want to write files to disk so that IIS can serve them up. That adds security implications as well as increases complexity. All you really need to do is save the CSV directly to the response stream.
Here's the scenario: User wishes to download csv. User submits a form with details about the csv they want. You prepare the csv, then provide the user a URL to an aspx page which can be used to construct the csv file and write it to the response stream. The user clicks the link. The aspx page is blank; in the page codebehind you simply write the csv to the response stream and end it.
You can add the following to the (I believe this is correct) Load event:
string attachment = "attachment; filename=MyCsvLol.csv";
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "text/csv";
HttpContext.Current.Response.AddHeader("Pragma", "public");
var sb = new StringBuilder();
foreach(var line in DataToExportToCSV)
sb.AppendLine(TransformDataLineIntoCsv(line));
HttpContext.Current.Response.Write(sb.ToString());
writing to the response stream code ganked from here.
Here's a very simple free open-source CsvExport class for C#. There's an ASP.NET MVC example at the bottom.
https://github.com/jitbit/CsvExport
It takes care about line-breaks, commas, escaping quotes, MS Excel compatibilty... Just add one short .cs file to your project and you're good to go.
(disclaimer: I'm one of the contributors)
Here is a CSV action result I wrote that takes a DataTable and converts it into CSV. You can return this from your view and it will prompt the user to download the file. You should be able to convert this easily into a List compatible form or even just put your list into a DataTable.
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Data;
namespace Detectent.Analyze.ActionResults
{
public class CSVResult : ActionResult
{
/// <summary>
/// Converts the columns and rows from a data table into an Microsoft Excel compatible CSV file.
/// </summary>
/// <param name="dataTable"></param>
/// <param name="fileName">The full file name including the extension.</param>
public CSVResult(DataTable dataTable, string fileName)
{
Table = dataTable;
FileName = fileName;
}
public string FileName { get; protected set; }
public DataTable Table { get; protected set; }
public override void ExecuteResult(ControllerContext context)
{
StringBuilder csv = new StringBuilder(10 * Table.Rows.Count * Table.Columns.Count);
for (int c = 0; c < Table.Columns.Count; c++)
{
if (c > 0)
csv.Append(",");
DataColumn dc = Table.Columns[c];
string columnTitleCleaned = CleanCSVString(dc.ColumnName);
csv.Append(columnTitleCleaned);
}
csv.Append(Environment.NewLine);
foreach (DataRow dr in Table.Rows)
{
StringBuilder csvRow = new StringBuilder();
for(int c = 0; c < Table.Columns.Count; c++)
{
if(c != 0)
csvRow.Append(",");
object columnValue = dr[c];
if (columnValue == null)
csvRow.Append("");
else
{
string columnStringValue = columnValue.ToString();
string cleanedColumnValue = CleanCSVString(columnStringValue);
if (columnValue.GetType() == typeof(string) && !columnStringValue.Contains(","))
{
cleanedColumnValue = "=" + cleanedColumnValue; // Prevents a number stored in a string from being shown as 8888E+24 in Excel. Example use is the AccountNum field in CI that looks like a number but is really a string.
}
csvRow.Append(cleanedColumnValue);
}
}
csv.AppendLine(csvRow.ToString());
}
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = "text/csv";
response.AppendHeader("Content-Disposition", "attachment;filename=" + this.FileName);
response.Write(csv.ToString());
}
protected string CleanCSVString(string input)
{
string output = "\"" + input.Replace("\"", "\"\"").Replace("\r\n", " ").Replace("\r", " ").Replace("\n", "") + "\"";
return output;
}
}
}
A comment about Will's answer, you might want to replace HttpContext.Current.Response.End(); with HttpContext.Current.ApplicationInstance.CompleteRequest(); The reason is that Response.End() throws a System.Threading.ThreadAbortException. It aborts a thread. If you have an exception logger, it will be littered with ThreadAbortExceptions, which in this case is expected behavior.
Intuitively, sending a CSV file to the browser should not raise an exception.
See here for more Is Response.End() considered harmful?
How to write to a file (easy search in Google) ... 1st Search Result
As far as creation of the file each time a user accesses the page ... each access will act on it's own behalf. You business case will dictate the behavior.
Case 1 - same file but does not change (this type of case can have multiple ways of being defined)
You would have logic that created the file when needed and only access the file if generation is not needed.
Case 2 - each user needs to generate their own file
You would decide how you identify each user, create a file for each user and access the file they are supposed to see ... this can easily merge with Case 1. Then you delete the file after serving the content or not if it requires persistence.
Case 3 - same file but generation required for each access
Use Case 2, this will cause a generation each time but clean up once accessed.
check out csvreader/writer library at http://www.codeproject.com/KB/cs/CsvReaderAndWriter.aspx

Scripting.FileSystemObject Write method fails

So in my program I'm using COM Auotmation (AutomationFactory in Silverlight 4) to create a FileSystemObject, to which I write a string (theContent). theContent in this case is a small UTF-8 XML file, which I serialized using MemoryStream into the string.
The string is fine, but for some reason whenever I call the FileSystemObject's Write method I get the error "HRESULT 0x800A0005 (CTL_E_ILLEGALFUNCTIONCALL from google)." The strangest part is that if I pass another simple string, like "hello," it works with no problems.
Any ideas?
Alternatively, if there's a way to expose a file/text stream with FileSystemObject that I could serialize to directly, that would be good as well (I can't seem to find anything not in VB).
Thanks in advance!
string theContent = System.Text.Encoding.UTF8.GetString(content, 0, content.Length);
string hello = "hello";
using (dynamic fsoCom = AutomationFactory.CreateObject("Scripting.FileSystemObject"))
{
dynamic file = fsoCom.CreateTextFile("file.xml", true);
file.Write(theContent);
file.Write(hello);
file.Close();
}
I solved the same problem today using ADODB.Stream instead of Scripting.FileSystemObject.
In a Silverlight 4 OOB App (even with elevated trust), you cannot access files in locations outside of 'MyDocuments' and a couple of other user related special folders. You have to use the workaround 'COM+ Automation'. But the Scripting.FileSystemObject, which works great for text files, cannot handle binary files. Fortunately you can also use ADODB.Stream there. And that handles binary files just fine. Here is my code, tested with Word Templates, .dotx files:
public static void WriteBinaryFile(string fileName, byte[] binary)
{
const int adTypeBinary = 1;
const int adSaveCreateOverWrite = 2;
using (dynamic adoCom = AutomationFactory.CreateObject("ADODB.Stream"))
{
adoCom.Type = adTypeBinary;
adoCom.Open();
adoCom.Write(binary);
adoCom.SaveToFile(fileName, adSaveCreateOverWrite);
}
}
A file read can be done like this:
public static byte[] ReadBinaryFile(string fileName)
{
const int adTypeBinary = 1;
using (dynamic adoCom = AutomationFactory.CreateObject("ADODB.Stream"))
{
adoCom.Type = adTypeBinary;
adoCom.Open();
adoCom.LoadFromFile(fileName);
return adoCom.Read();
}
}
Why not just:
File.WriteAllText("file.xml", theContent, Encoding.UTF8);
or even
File.WriteAllBytes("file.xml", content);

Categories