|
Hello
I am hoping to use the following code in my VS 2017 project (register.aspx.vb) to hash/salt a password:
Public Function GetSalt() As String
Dim saltSize = 32
Dim Salt As RNGCryptoServiceProvider = New RNGCryptoServiceProvider()
Dim randomBytes(saltSize - 1) As Byte
Salt.GetBytes(randomBytes)
Return Convert.ToBase64String(randomBytes)
End Function
Public Function HashedPassword(ByVal Salt As String, ByVal providedPassword As String) As String
Dim passWithSalt = String.Concat(Salt, providedPassword)
Dim rawPasswordData() As Byte = Encoding.UTF8.GetBytes(passWithSalt)
Dim SHA512 As New SHA512CryptoServiceProvider()
Dim resultingHash As Byte() = SHA512.ComputeHash(rawPasswordData)
Return Convert.ToBase64String(resultingHash)
End Function
followed by:
Protected Sub btnReg_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnReg.Click
Try
Using connection As New OleDbConnection("connectionString")
Dim Sql As String = "INSERT INTO university (username,strEmail,Hash) VALUES (@username,@strEmail,@Hash)"
Dim cmd As New OleDbCommand(Sql)
cmd.Connection = connection
cmd.Parameters.AddWithValue("@username", username.Text)
cmd.Parameters.AddWithValue("@strEmail", strEmail.Text)
cmd.Parameters.AddWithValue("@Hash", "Production based on simple ciphers and fixed encryption keys")
connection.Open()
cmd.ExecuteNonQuery()
End Using
Dim target = String.Format("~/success.aspx?Name={0}", username.Text)
Response.Redirect(target, True)
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Sub
How would I relate the GetSalt and HashedPassword functions, please, to the button click, in order to make this code work?
Thank you.
|
|
|
|
|
You need to store the Hash and the salt. When authenticating the password, you need both parts to make a match.
Your really better off using a package like BCrypt to do it for you. I've done it your way but stored the values as byte[] and not string.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Thanks jkirkerx, for your reply.
I am not familiar at all with BCrypt but, following your advice about 'You need to store the Hash and the salt', I take it that I would need two columns in my database to do that, namely, 'Salt', and 'Hash' (where 'Hash' would replace the plain password column), and I would need to alter my code to:
Dim Sql As String = "INSERT INTO university (username,strEmail,Salt,Hash) VALUES (@username,@strEmail,@Salt,@Hash)"
and
cmd.Parameters.AddWithValue("@username", username.Text)
cmd.Parameters.AddWithValue("@strEmail", strEmail.Text)
cmd.Parameters.AddWithValue("@Salt")
cmd.Parameters.AddWithValue("@Hash", "Production based on simple ciphers and fixed encryption keys") (I am not sure about how to code those last two parameters).
Thanks again.
|
|
|
|
|
Yup!
The Hash is the password that has been generated with Salt.
If you don't store the Salt, you can't verify the Hash
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Very many thanks again - you have been a great help.
Regards
|
|
|
|
|
Since you are in the context of ASP.NET, you may want to look at System.Web.Helpers.Crypto class as it provides a few handy functions to do Hashing for you. For example:
using System.Web.Helpers;
public void SavePassword(string unhashedPassword)
{
string hashedPassword = Crypto.HashPassword(unhashedPassword);
}
The Crypto.HashPassword function takes care of creating a salt for you. The returned value of that function already contains both the salt and the hashed password in a single value. All you need to do is store the username and hashed password in your database and you're done.
More info, read: Password management made easy in ASP.NET with the Crypto API | brockallen[^]
|
|
|
|
|
Very many thanks for your post, Vincent. That must be the simplest hash/salt I have seen! Thanks, to, for the link which discusses password verification for use on a log-in page.
I will give it a try.
I am assuming that, for the new user registration page, I would use (as above):
Public Sub CreateAccount(ByVal username As String, ByVal password As String)
Dim hashedPassword = Crypto.HashPassword(password)
CreateAccountInDatabase(username, hashedPassword)
End Sub
and then my 'Submit' button:
Private Sub BtnReg_Click(sender As Object, e As EventArgs) Handles BtnReg.Click
'Dim hashedPasswordText As New Label With {.Text = (Hash512(password.Text, CreateRandomSalt))}
Using connection As New OleDbConnection("connectionString")
Dim Sql As String = "INSERT INTO university (username,strEmail,hashed,salted) VALUES (@username,@strEmail,@hashed,@salted)"
Dim cmd As New OleDbCommand(Sql)
cmd.Connection = connection
cmd.Parameters.AddWithValue("@username", username.Text)
cmd.Parameters.AddWithValue("@strEmail", strEmail.Text)
Dim hashed As Boolean
cmd.Parameters.AddWithValue("@hashed", hashed)
Dim salted As Boolean
cmd.Parameters.AddWithValue("@salted", salted)
connection.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
Does that look as if it may work?
Thanks again!
|
|
|
|
|
You don't need to store the salt anymore in your database as the returned value of the Crypto.HashPassword already has a Salt on it.
Dim hashedPassword = Crypto.HashPassword(password)
For example, the variable hashedPassword already contains the Hash + Salt
So your code would now be something like:
Private Sub CreateAccount(ByVal username As String, ByVal password As String, ByVal email As String)
Dim hashedPassword = Crypto.HashPassword(password)
Using connection As New OleDbConnection("connectionString")
Dim Sql As String = "INSERT INTO university (username,strEmail,hashed) VALUES (@username,@strEmail,@hashed)"
Dim cmd As New OleDbCommand(Sql)
cmd.Connection = connection
cmd.Parameters.AddWithValue("@username", username)
cmd.Parameters.AddWithValue("@strEmail", email)
cmd.Parameters.AddWithValue("@hashed", hashedPassword)
connection.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
Private Sub BtnReg_Click(sender As Object, e As EventArgs) Handles BtnReg.Click
CreateAccount(username.Text,password.Text,strEmail.Text)
End Sub
PS: My apology as I'm not good at VB.NET 
|
|
|
|
|
 That's great, Vincent. Thank you for your time. I got one or two errors ('not declared') in VS 2017, which I have attempted to correct via the application's 'light-bulb', so the code now looks like this:
Public Sub CreateAccount(ByVal username As String, ByVal password As String)
Dim hashedPassword = Crypto.HashPassword(password)
CreateAccountInDatabase(username, hashedPassword)
End Sub
Private Sub CreateAccountInDatabase(username As String, hashedPassword As Object)
Throw New NotImplementedException()
End Sub
Private Sub CreateAccount(ByVal username As String, ByVal password As String, ByVal email As String)
Dim hashedPassword = Crypto.HashPassword(password)
Using connection As New OleDbConnection("connectionString")
Dim Sql As String = "INSERT INTO university (username,strEmail,hashed) VALUES (@username,@strEmail,@hashed)"
Dim cmd As New OleDbCommand(Sql)
cmd.Connection = connection
cmd.Parameters.AddWithValue("@username", username)
cmd.Parameters.AddWithValue("@strEmail", email)
cmd.Parameters.AddWithValue("@hashed", hashedPassword)
connection.Open()
cmd.ExecuteNonQuery()
End Using
End Sub
Private Sub BtnReg_Click(sender As Object, e As EventArgs) Handles BtnReg.Click
'Do some forms validation here
CreateAccount(username.Text, password.Text, strEmail.Text)
End Sub
I still get one compilation error while trying to load the page I my browser and that relates to Crypto which, VS tells me, is not declared. Again, the light-bulb pops up with a few alternatives including 'generate Crypto as class'. Not sure if that's what I should opt for as I am in unfamiliar territory here.
Thanks again.
|
|
|
|
|
You need to add a reference to the System.Web.Helpers assembly, and add Imports System.Web.Helpers to the top of your code file.
You'll also want to remove CreateAccount(ByVal username As String, ByVal password As String) and CreateAccountInDatabase(username As String, hashedPassword As Object) , since they're not used, and calling either of them will result in an exception.
NB: Don't remove CreateAccount(ByVal username As String, ByVal password As String, ByVal email As String) , since that's the one you're using.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
You need to add a reference to System.Web.Helpers . If it's not present in your project references then add it. You will find this assembly in the Extensions group under Assemblies in Visual Studio 2010, 2012 & 2013 (Reference Manager). You can also add it via NuGet package manager.
Once you've added that reference to your project, then declare the following in your code:
Imports System.Web.Helpers
|
|
|
|
|
how to hold browsing path in fileupload control(i want to choose my choice folder) & How to get uploaded file path ,while click on show in folder(Show in Folder)?
Select Saving path: Fileupload1(Holds saving path)
Select File: Fileupload2 (file)
Show in folder(link Button)(sucessfull uploaded file show in folder)
Thanks in Advance..
|
|
|
|
|
You can't get that for security reasons.
|
|
|
|
|
I've been going to programmer seminars over the last month and learning more about .Net Core, and the concepts of breaking up my programs into smaller pieces and processes. My plan going forward is to start running my .Net Core apps in Docker Containers in my little data center first, then Azure later. So we were talking about Azure and Web Jobs, which Segway into sending email as a separate process. Rob Rich, the speaker was talking about making email more durable and stateless by making it a separate process that works off a message queue. I get the concept as if it was an illustration, but can't grasp the code architecture of it.
I currently just have classes that handle email in a separate project that is attached to the main project. The email classes just generates the email message and then calls SendMailAsync in the same external project. I'm thinking perhaps I should create a new project that just handles email. Something completely modular that I could use over and over with little configuration or integration.
My first thought is take the SendMailAsync, and create a .Net Core console app for it. Pass the mail to it, send it, if it fails add it back to the queue.
Second thought is to take all the email stuff, and create another program for it and use dependency injection to generate the message, and send it.
As an exercise towards writing better architected code, I would like to get it right this time. I'm asking for help on this.
Thanks.
Richard:
Is this what you meant by console apps?
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Wasn't he talking about using some kind of queuing broker (e.g. Apache Kafka)? From your explanation, that is what it sounds to me.
If that's the case, you will have an application that would send a message to the queue with an email object and another application that would take those objects, send the emails and, if successful, remove them from the queue.
The broker is the specialized middle-ware responsible for saving those messages until needed and delivering them, guaranteeing that no messages are lost due to applications crashing, servers not available, etc.
|
|
|
|
|
Hi everyone
I am fairly new to MVC and I've only done simple projects without security before. I am now working in a new, more complex project that requires a security model based on role + organization.
The authorization will be based on Windows user. Once the users are validated, they will be marked as working with their default organization, but the can change the organization at any time. We are imagining a drop-down with the organizations the user belong to, and stored the current one as a session variable.
The simplest part of the projects consists of several CRUDs. We have users that are either viewers or editors in these CRUDs, but their role may vary depending on the organization they are working on.
E.g. for the "Branches" table, User "Peter" may be an editor for organization 1 and a viewer for organizations 2 and 3.
If I ignore the organization, I can easily manage the security by extending System.Web.Security.RoleProvider and handling the logic within that class. I believe I could read the current organization from the session variable (haven't tried that yet) in order to add that to the class logic, but I'm pretty sure there must be a better solution.
Can anyone suggest a better solution? Ideally it should be following the ASP.NET System.Web.Security model. Any Visual Studio integrated framework that makes this security handling easier is also very welcomed.
Thank you
|
|
|
|
|
I'm no expert at this by far. But I'll mention the HttpContext. It has a lifespan of one cycle and is stateless.
So I made a Attribute that you decorate the controller ActionResult with. It runs run before the ActionResult is fired, and passes everything downstream. Basically it's session free so you don't have to worry about restarts or what server you hit. I do remember this being a little buggy, in terms of having to erase the cookie a couple of times when exiting debug and starting again, but I think I fixed it.
[AdminCheck]
public IActionResult SomeEditor()
The AdminCheck reads the cookie with special data in it, and if the user authenticates, it creates a new HttpContext.User using a GenericIdentity and GenericPrincipal
I wrote this for .Net Core
[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class AdminCheckAttribute : ActionFilterAttribute, IActionFilter
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var controller = filterContext.Controller as Controller;
var httpContext = controller.HttpContext;
Model_Admin_Login pResult = SecurityCookies.CookieRead_Admin_Login(httpContext);
if (pResult.AccountName != null)
{<br />
Model_Admin_Login model = new Model_Admin_Login();
bool result = EF_Website_Users.AdminCheck_AccountName(pResult.AccountName, ref model);
if (true == result)
{
String[] newRoles = { "Administrator" };
GenericIdentity newIdentity = new GenericIdentity(pResult.AccountName);
GenericPrincipal newPrincipal = new GenericPrincipal(newIdentity, newRoles);
httpContext.User = newPrincipal;
System.Threading.Thread.CurrentPrincipal = httpContext.User;
controller.ViewData["Admin_Menu"] = true;
controller.ViewData["Admin_UserID"] = model.ID;
controller.ViewData["Admin_UserName"] = pResult.AccountName.ToLower();
controller.ViewData["Admin_ImageUrl"] = model.Avatar.Url;
controller.ViewData["Admin_ImageAlt"] = model.Avatar.Alt;
controller.ViewData["Admin_Base64"] = model.Avatar.Data != null ? Convert.ToBase64String(model.Avatar.Data, 0, model.Avatar.Data.Length) : null;
}
else
{
controller.ViewData["Admin_Menu"] = false;
}<br />
}
else
{
controller.ViewData["Admin_Menu"] = false;<br />
}
base.OnActionExecuting(filterContext);
}
}
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Thanks for your reply Jim. I will look into the example you provided.
When you said "It has a lifespan of one cycle and is stateless.", you mean that it won't survive a IIS/Server reboot? As long as it keeps track of sessions (which I'm pretty sure it does), we are OK with it.
Thanks you
|
|
|
|
|
On the contrary quite the opposite.
Because it reads the cookie you set with say the user name and a special token you craft when validated or authenticated the first time, the attribute will revalidate the authentication being stateless and durable, it will survive a server reboot, or say a worker process recycle and can be used in multiple Docker containers using Kubernetes.
Just add another column to your user database table to store a token that you carefully craft.
Using Sessions to store a value or to maintain authentication is dangerous and not durable in an environment that is suppose to be stateless. It may work today, but can be the cause of your worst mistake ever.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|
Hi,
I received a security issue recently.It seems to be "Man in the middle attack".
Suppose browser send a request to UI server and receive the response.
But before response is received by browser, it is intercepted by some proxy (like fiddler or burpproxy), the hacker who hold the response, he first change it and then send to the browser.
The actual user doesn't know that the response has been changed.
The application is running on https (SSL), then also it is getting changed.
I tried below things.
1- I analyzed HPKP (http public key pinning). It is aimed to fix these types of issues but it is not supported by all the browser (IE Safari).
It is supported by Chrome but i read an article that even chrome is planning to stop its support for HPKP.
2- I thought to send the encrypted data and decrypt at browser using javascript.
But javascript logic is not possible to hide from hacker.
I heard several article where it is said that javascript logic can be tried to hide, but we can not be sure that it can't be found by hacker.
Please provide some guidance where I should look for the solution to prevent this type of attack.
Regards,
Saurabh
|
|
|
|
|
If your site is always running over HTTPS, then requests and responses cannot be read or modified by a MitM. The only exceptions would be:
- The attacker has convinced a rogue CA to issue an invalid cert for your site.
This would likely be detected pretty quickly, and would result in browsers dropping that CA from their "trusted CAs" list.
HPKP[^] can help to prevent this; but if the user's first access to your site is via a compromised network, the HPKP information could also be removed or compromised.
- The attacker has compromised the user's computer, and installed their own root cert in the trusted store, allowing them to issue invalid certs for any site.
HPKP might help in this case; but if the user's computer has been compromised, the cached pins could also have been deleted or modified.
- The attacker has compromised the user's computer, and installed malware to modify pages after the browser has downloaded them.
As a site owner, there is nothing you can do to prevent this sort of attack. Even if you add CSP[^] to control which scripts can run, the malware can just remove that header.
A more likely scenario is if your site is initially served over HTTP, in which case, a MitM attacker can prevent the redirection to HTTPS, and is free to do whatever they want with your site's content.
HSTS[^] can help to prevent this, but your user would need to access your site via a clean network first.
You can request to have your site included on the "preload" list[^], which would ensure it's only ever accessed over HTTPS, even for new users. But if you ever wanted to switch back, it could take many months for your site to be removed.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thanks Rechard,
I will try the options provided by you and get back.
|
|
|
|
|
Hi,
I am getting the following error in my Production Server, the application is working fine in Dev environment, so if I have to keep Logging etc and deploy the application, and Web Service, it takes a bit of time like Code Review etc, is there any way to find out where is the Exception happening etc? Without another deployment?
Thanks in advance.
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
|
|
|
|
|
Assuming you're calling a WCF service, you can turn on message logging in the config file:
Message Logging | Microsoft Docs[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Well I've made it this now, which is pretty good. I've almost completed the porting over the front end of my portfolio website and I'm working with the database now, in which I chose MongoDB since that seems to be the buzz word for job apps.
A couple I don't understand about MongoDB. Guess the first question is the auto increment for the index column. Guess Mongo uses a unique identifier based on some other logic, so I used ObjectId.GenerateNewId(); Below is an example of my controller code which writes to Mongo successfully. see the CRMMessage;
Q1: Should I just get rid of the "Id" which was int and is now string and just use InternalId? Or does MongoDB have the same mechanism that will auto increment?
So before I added the the respository to the controller function, it worked fine. Angular would register a success and run my success code. But now it returns something I can't see, which results in Error 500 according to Chrome F12.
Q2: Should I just change IActionResult to void and return nothing? I'm lost here on this.
[HttpPost]
public IActionResult AddMessage([FromBody] CRMMessage message)
{
if (message == null)
{
return BadRequest();
}
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
_crmRespository.AddMessage(new CRMMessage
{
InternalId = ObjectId.GenerateNewId(),
Name = message.Name,
CompanyName = message.CompanyName,
EmailAddress = message.EmailAddress,
PhoneNumber = message.PhoneNumber,
PhoneMobile = message.PhoneMobile,
TimeZone = message.TimeZone,
TimeStamp = message.TimeStamp,
UpdatedOn = message.TimeStamp,
Message = message.Message,
RememberMe = message.RememberMe
});
return CreatedAtRoute("GetSingleMessage", new { id = message.Id }, message);
}
This is my Angular 6, TypeScript onSubmit Function. I know this question is in the wrong section bought thought I'd ask anyways since it tied together. I wonder how it knows the difference between a success and an error. There are tools like postman in which I need to learn how to use.
onSubmit() {
this.dataService.addMessage(this.model).subscribe(
() => {
this.messageSuccess = true;
this.getStartedForm.reset();
this.model.name = '';
this.model.companyName = '';
this.model.emailAddress = ''
this.model.phoneNumber = '';
this.model.phoneMobile = '';
this.model.message = '';
setTimeout(() => {
this.messageSuccess = false;
this.getStartedModal.hide();
this.router.navigate(['/home/getStarted']);<br />
}, 3000);
},
error => {
console.log(error);
}
);
My Angular journey has been confusing because there are so many different examples and versions of Angular. I'm actually dual developing between a pure Angular 6 app in cli and this .Net Core 2.1 version so I can see the different between the two, determine which info is correct. Angular 6 using cli and ng on a text editor is more straight forward to learn first.
Any thoughts besides giving up would be appreciated.
If it ain't broke don't fix it
Discover my world at jkirkerx.com
|
|
|
|
|