Mysql
 sql >> Database >  >> RDS >> Mysql

Simulazione della crittografia password() di MySql utilizzando .NET o MS SQL

Secondo la documentazione di MySQL, l'algoritmo è un doppio hash SHA1. Quando esamini il codice sorgente di MySQL, trovi una funzione chiamata make_scrambled_password() in libmysql/password.c. La funzione è definita come segue:

/*
    MySQL 4.1.1 password hashing: SHA conversion (see RFC 2289, 3174) twice
    applied to the password string, and then produced octet sequence is
    converted to hex string.
    The result of this function is used as return value from PASSWORD() and
    is stored in the database.
  SYNOPSIS
    make_scrambled_password()
    buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
    password  IN  NULL-terminated password string
*/

void
make_scrambled_password(char *to, const char *password)
{
  SHA1_CONTEXT sha1_context;
  uint8 hash_stage2[SHA1_HASH_SIZE];

  mysql_sha1_reset(&sha1_context);
  /* stage 1: hash password */
  mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
  mysql_sha1_result(&sha1_context, (uint8 *) to);
  /* stage 2: hash stage1 output */
  mysql_sha1_reset(&sha1_context);
  mysql_sha1_input(&sha1_context, (uint8 *) to, SHA1_HASH_SIZE);
  /* separate buffer is used to pass 'to' in octet2hex */
  mysql_sha1_result(&sha1_context, hash_stage2);
  /* convert hash_stage2 to hex string */
  *to++= PVERSION41_CHAR;
  octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
}

Dato questo metodo, puoi creare una controparte .NET che fondamentalmente fa la stessa cosa. Ecco cosa mi è venuto in mente. Quando eseguo SELECT PASSWORD('test'); rispetto alla mia copia locale di MySQL, il valore restituito è:

*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29

Secondo il codice sorgente (sempre in password.c), l'asterisco iniziale indica che questo è il metodo post-MySQL 4.1 per crittografare la password. Quando emulo la funzionalità in VB.Net, ad esempio, questo è ciò che mi viene in mente:

Public Function GenerateMySQLHash(ByVal strKey As String) As String
    Dim keyArray As Byte() = Encoding.UTF8.GetBytes(strKey)
    Dim enc = New SHA1Managed()
    Dim encodedKey = enc.ComputeHash(enc.ComputeHash(keyArray))
    Dim myBuilder As New StringBuilder(encodedKey.Length)

    For Each b As Byte In encodedKey
        myBuilder.Append(b.ToString("X2"))
    Next

    Return "*" & myBuilder.ToString()
End Function

Tieni presente che SHA1Managed() si trova nello spazio dei nomi System.Security.Cryptography. Questo metodo restituisce lo stesso output della chiamata PASSWORD() in MySQL. Spero che questo ti aiuti.

Modifica:ecco lo stesso codice in C#

public string GenerateMySQLHash(string key)
{
    byte[] keyArray = Encoding.UTF8.GetBytes(key);
    SHA1Managed enc = new SHA1Managed();
    byte[] encodedKey = enc.ComputeHash(enc.ComputeHash(keyArray));
    StringBuilder myBuilder = new StringBuilder(encodedKey.Length);

    foreach (byte b in encodedKey)
        myBuilder.Append(b.ToString("X2"));

    return "*" + myBuilder.ToString();
}