Url encryption

Asked

Viewed 1,785 times

2

I have a way of Email which generates a link through HTTP request, which will send to the user’s email for exchange. But for testing I fixed in this URL the user ID, but for security reasons I have to encrypt it. How to perform this procedure ?

Follows code

Metodo Confirmaenvio

  public IActionResult ConfirmarEnvio(Clientes objLogin)
        {
            try
            {
                var link = HttpContext.Request.Host.Value;
                Email objEmail = new Email(_config);
                objEmail.CliCodigo = objLogin.CliCodigo;
                objEmail.CliEmail = objLogin.CliEmail;
                objEmail.link = link;
                objEmail.EnviarEmail();
                return View("Login");
            }
            catch (Exception ex)
            {

                throw ex;
            }

        }

Part of the method that generates the link:

 //From Address  
                string FromAddress = _config.GetValue<string>("From");
                string FromAdressTitle = "TesteEnvio";
                //To Address  
                string ToAddress = CliEmail;
                string ToAdressTitle = "Microsoft ASP.NET Core";
                string Subject = "Redefinição de senha";//Assunto,
                StringBuilder BodyContent = new StringBuilder();
                BodyContent.Append  ("Prezado(a)  para redefinir sua senha, por favor clique no link abaixo.");
                BodyContent.Append  ("<br/>");
                BodyContent.Append  ("Link: http://" + link + "/Accounts/RedefinicaoSenha?id=" + CliCodigo +"");

E-mail received however with the Visivél ID: inserir a descrição da imagem aqui

  • 1

    Just out of curiosity, why encrypting the user ID will bring some security?

  • Because if I paste that URL this way, it will open the password change view and so anyone could change the password without any impediment. See, for the user to reach this point of change it is necessary to make a request on the Login screen, where automatically will load a modal already with the email related to the user’s ID locked, thus preventing the change of email by third parties.

  • 3

    Man, the way I see it, cryptography’s not gonna do you much good on this case. Anyone with this link, even if encrypted, worldwide could access your application. I think you could work with a temporary link, you know? 10 minutes or less. Create a key and send that key which can be in md5 or sha1, etc. Send the key in the email link and relate this key to the user who will exchange the password. Understand? Put a short but sufficient time. This way, your security will be a little better than just encrypting the user id.

  • @And you think encrypting the user ID is the best solution for that? Why not generate a single hash and send it to the user’s email?

  • @LINQ as it is a new feature for me, I’m open to opinions, could exemplify how to follow this path ?

  • @Diegosantos I agree with what you said, but this process of validation of password exchange by link is new for me! So I’m still analyzing the best routes to follow with good 'manners' to develop this logic

  • 1

    I understand @Igorcarreiro, and I think you’re right! Well I point out this way that I said because I have done so a few times and it is not such an honorable process if you already have a certain knowledge in the database, mainly. Examples of how to generate the key, you can generate one in sql server with a select newid(), for example. In C#, you can generate it with a GUID. It’s pretty simple... But follow what you find peaceful for you! Good luck...

  • 1

    I agree with @Diegosantos, but I create a link that can be used only once, the key I Gero using New Guid() and then only pass to Base64, simple, unique, safe. in the database I place this "key" in a table, which has the user id reference, and good. I mark this link as accessed, and then it’s gone, it’s in the bank only for history.

Show 3 more comments

1 answer

4


Answering the initial question:

Using a md5 hash function, it could encrypt the user id:

Function Md5FromStringUTF8:

    public static string Md5FromStringUTF8(string input)
    {
        string saida = null;
        using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
        {
            byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
            byte[] hash = md5.ComputeHash(inputBytes);
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("x2"));
            }
            saida = sb.ToString();
        }

        return saida;
    }

Utilizing:

BodyContent.Append  ("Link: http://" + link + "/Accounts/RedefinicaoSenha?id=" + Md5FromStringUTF8(CliCodigo) +"");

However, in his controller, would no longer execute select by id, but by id md5:

'Select ... from tabela where CONVERT(VARCHAR(32), HashBytes('MD5', id), 2) = [parametro_id]'

or by Entity:

_context.Clientes.Where(x => Md5FromStringUTF8(x.Id) == [parametro_id]).FirstOrDefault();

Understand [parametro_id] as the parameter passed by the Url


Suggested improvement based on the commentary by Diegosantos:

Create a class for password reset, and store in a table. When the user makes a request to reset, you enter a record, generate the link with the id of that record, the user accessing the Url, checks whether the request is valid, and allows it to end the process:

public class RedefinirSenha
{
    public int Id {get;set;}
    public Clientes Cliente { get; set; }
    public DateTime Data { get; set; }
    public bool IsValid { get { return (Data.AddMinutes(10) >= DateTime.Now); } }
    public string Hash { get { return Md5FromStringUTF8(Id.ToString()); } }
}

Whereas you are using Entityframework, and _context be yours DbContext

public IActionResult ConfirmarEnvio(Clientes objLogin)
{
    RedefinirSenha objRed = new RedefinirSenha()
    {
         Cliente = objLogin,
         Data = DateTime.Now
    };

    _context.RedefinicoesSenha.Add(objRed);
    _context.SaveChanges();


    var link = HttpContext.Request.Host.Value;
    Email objEmail = new Email(_config);
    objEmail.CliCodigo = objRed.Id; //Aqui poderia mudar a nomenclatura, já que não será mais codigo do cliente, e também já poderia passar criptografado.

    objEmail.CliEmail = objLogin.CliEmail;
    objEmail.link = link;
    objEmail.EnviarEmail();
    return View("Login");
}

I placed the insertion of the RedefinirSenha in action ConfirmarEnvio to illustrate, I think I could put this insertion in the action where the password request is made, and the sending of the email receives as parameter this object keeping the cohesion of the code.

Finally, in its action RedefinicaoSenha:

public IActionResult RedefinicaoSenha(string id)
{
    RedefinirSenha objRed = _context.RedefinicoesSenha.Where(x=>x.Hash == id && x.IsValid).FirstOrDefault();

    if (objRed != null) 
    {
       //Mudar a senha do cliente com id = objRed.Cliente.id
    }
    else
    {
        //Requisição inválida
    }

    ...
}

I hope it helps, any suggestions for improvement is welcome. =]

  • 1

    Just an addendum, MD5 inherits from Hashalgorithm and needs Dispose. using (var md5 = System.Security.Cryptography.MD5.Create()) {}

  • 1

    @Gabrielcoletta thanks, already updated in the functions that I use here also =]

Browser other questions tagged

You are not signed in. Login or sign up in order to post.