I am a student totally new to C# programming. I am currently doing a mini security project using MVC. The project: Allow users to upload a csv file containing accounts but password not hash and salt. (Done) Then I will send the file to virustotal and scan it before saving to the server (Done) After saving, I need to insert the data in the csv file and hash and salt the password into the database. (Need help)
My Controller
public ActionResult Upload(HttpPostedFileBase file)
{
if (System.IO.Path.GetExtension(file.FileName).Equals(".csv"))
{
//{0} = Y, {1} = M, {2} = D, {3} = H, {4} = min, {5} = Sec
string datetime = string.Format("{0}{1}{2}-{3}{4}{5}", DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);
string fileName = string.Format("{0}_{1}.csv", file.FileName.Substring(0, (file.FileName.Length - 4)), datetime);
var fileStream = new System.IO.MemoryStream();
file.InputStream.CopyTo(fileStream);
var vtObj = new VirusTotal("%API KEY%");
vtObj.UseTLS = true;
try
{
var fileResults = vtObj.ScanFile(fileStream, fileName);
var report = vtObj.GetFileReport(fileResults.ScanId);
int resPos = report.Positives;
if (resPos == 0)
{
string savePath = Server.MapPath("~/CSV/" + fileName);
file.SaveAs(savePath);
try
{
//removing the first row
insertDB(fileName, savePath);
ViewBag.error = "Updated successfully";
return View();
}
catch (Exception ex)
{
ViewBag.error = "Unable to update DB" + ex;
return View("Index");
}
}
else
{
ViewBag.error = "Unable to upload";
return View("Index");
}
}
catch (Exception ex)
{
ViewBag.error = string.Format("Unable to upload | One min only can upload 4 times | {0} | {1}", ex, fileName);
return View("Index");
}
}
else
{
ViewBag.error = "Unable to upload";
return View("Index");
}
}
public void insertDB(string fileName, string savePath)
{
using (DB01Entities dbc = new DB01Entities())
{
string sql = string.Format(@"CREATE TABLE [dbo].[TempImport]
(
Name varchar(255),
Password VARBINARY(50)
)
bulk insert [dbo].[TempImport] from '%MyPATH%\CSV\{0}' with (ROWTERMINATOR = '\n')
INSERT INTO dbo.Employee
(
Name
Password
)
SELECT name
FROM dbo.TempImport
DROP TABLE dbo.TempImport", fileName);
dbc.Database.ExecuteSqlCommand(sql);
dbc.SaveChanges();
}
}
}
}
My Index
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" name="File" id="file" accept=".csv"/>
<input type="submit" value="Upload" />
<div class="error">@ViewBag.error</div>
}
Upload
@{
ViewBag.Title = "Upload";
}
<div class="success">@ViewBag.error</div>
<a href="/Home/Index">Back to Index>></a>
Assuming a bulk insert via SQL is not a requirement:
Since you're using ASP.NET, use the Crypto class to hash your passwords:
var hashedPassword = Crypto.HashPassword(plainTextPassword);
When you want to verify the plain text version later, use
bool matches = Crypto.VerifyHashedPassword(hashedPassword, plainTextPassword);
The hashed password contains the salt used when hashing, and Crypto knows how to extract the salt from the password hash.
Since you have a stream to read from:
using(var reader = new StreamReader(fileStream))
{
using (DB01Entities dbc = new DB01Entities())
{
while(reader.Peek != -1)
{
var parts = reader.ReadLine().Split(',');
var hashedPassword = Crypto.HashPassword(parts[1]);
dbc.Employees.Add(new Employee { Name = parts[0], Password = hashedPassword });
}
dbc.SaveChanges();
}
}
This also has the advantage of not requiring the file to be saved anywhere, as you can just use the bytes you already have in memory.