본문 바로가기

Story/asp

asp c# .net 에서 mysql password 값을 만들기

반응형

mysql 4.1 이하 버전용 [OLD_PASSWORD]

public static string mysql_old_password(string sPassword)
{
    UInt32
[] result = new UInt32[2];
    bool bDebug
= false;
    UInt32 nr
= (UInt32)1345345333, add = (UInt32)7, nr2 = (UInt32)0x12345671;
    UInt32 tmp
;

    char
[] password = sPassword.ToCharArray();
    int i
;

   
for (i = 0; i < sPassword.Length; i++)
   
{
       
if (password[i] == ' ' || password[i] == '\t')
           
continue;

        tmp
= (UInt32)password[i];
        nr
^= (((nr & 63) + add) * tmp) + (nr << 8);
        nr2
+= (nr2 << 8 ) ^ nr;
       
add += tmp;
   
}

    result
[0] = nr & (((UInt32)1 << 31) - (UInt32)1);
    UInt32 val
= (((UInt32)1 << 31) - (UInt32)1);
    result
[1] = nr2 & val;
    string hash
= String.Format("{0:X}{1:X}", result[0], result[1]);
   
return hash.ToLower();
}

출처 : Simulating MySql OLD_PASSWORD in .NET or MS SQL?

--> http://stackoverflow.com/questions/1243248/simulating-mysql-old-password-in-net-or-ms-sql

 

 

namespace ConsoleApplication
{
    class Program
    {
        static string mysql_old_password(string sPassword)
        {
            UInt32[] result = new UInt32[2];
            bool bDebug = false;
            UInt32 nr = (UInt32)1345345333, add = (UInt32)7, nr2 = (UInt32)0x12345671;
            UInt32 tmp;

            char [] password = sPassword.ToCharArray();
            int i;

            for (i = 0; i < sPassword.Length; i++)
            {
                if (password[i] == ' ' || password[i] == '\t')
                    continue;

                tmp = (UInt32)password[i];
                nr ^= (((nr & 63) + add) * tmp) + (nr << 8);
                nr2 += (nr2 << 8 ) ^ nr;
                add += tmp;
            }

            result[0] = nr & (((UInt32)1 << 31) - (UInt32)1);
            UInt32 val = (((UInt32)1 << 31) - (UInt32)1);
            result[1] = nr2 & val;
            string hash = String.Format("{0:X}{1:X}", result[0], result[1]);
            return hash.ToLower();
        }

        static void Main(string[] args)
        {
            string hash = mysql_old_password("Hier Ihr Passwort");
            Console.WriteLine(hash);
       }
    }
}

원출처 : mySQL: Alten MD5 Hash in C# berechnen (16 stellig)

--> http://www.yourhelpcenter.de/2009/06/mysql-alten-md5-hash-in-c-berechnen-16-stellig/

 

mysql 4.1 이상 버전용

According to MySQL documentation, the algorithm is a double SHA1 hash. When examining the MySQL source code, you find a function called make_scrambled_password() in libmysql/password.c. The function is defined as follows:
/*
    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);
}

Given this method, you can create a .NET counterpart that basically does the same thing. Here's what I've come up with. When I run SELECT PASSWORD('test'); against my local copy of MySQL, the value returned is:

*94BDCEBE19083CE2A1F959FD02F964C7AF4CFC29

According to the source code (again in password.c), the beginning asterisk indicates that this is the post-MySQL 4.1 method of encrypting the password. When I emulate the functionality in VB.Net for example, this is what I come up with:

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

Keep in mind that SHA1Managed() is in the System.Security.Cryptography namespace. This method returns the same output as the PASSWORD() call in MySQL. I hope this helps for you.

Edit: Here's the same code 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();
}

출처 : Simulating MySql's password() encryption using .NET or MS SQL

--> http://stackoverflow.com/questions/868482/simulating-mysqls-password-encryption-using-net-or-ms-sql

 

 

참고 : php 용

mysql 4.1.x 이하 옛날 password() 함수 - old_password()

/**
* @brief mysql old_password 의 php 구현 함수
* 제로보드4나 기타 mysql4.1 이전의 old_password()함수를 쓴 데이터의 사용을 위해서
* mysql의 password.c 소스 참조해서 구현함
**/
function mysql_pre4_hash_password($password) {
    $nr=0x50305735;
    $nr2=0x12345671;
    $add=7;
    $charArr = preg_split("//", $password);
    foreach ($charArr as $char) {
        if (($char == '') || ($char == ' ') || ($char == '\t')) continue;
        $charVal = ord($char);
        $nr ^= ((($nr & 63) + $add) * $charVal) + ($nr << 8);
        $nr2 += ($nr2 << 8) ^ $nr;
        $add += $charVal;
    }
    return sprintf("%08x%08x", ($nr & 0x7fffffff), ($nr2 & 0x7fffffff));
}

/** 5.0 이상일 경우
function mysql_pre4_hash_password($password) {
    $nr = 1345345333;
    $add = 7;
    $nr2 = 0x12345671;

    settype($password, "string");

    for ($i=0; $i<strlen($password); $i++) {
        if ($password[$i] == ' ' || $password[$i] == '\t') continue;
        $tmp = ord($password[$i]);
        $nr ^= ((($nr & 63) + $add) * $tmp) + ($nr << 8);
        $nr2 += ($nr2 << 8) ^ $nr;
        $add += $tmp;
    }
    $result1 = sprintf("%08lx", $nr & ((1 << 31) -1));
    $result2 = sprintf("%08lx", $nr2 & ((1 << 31) -1));

    if($result1 == '80000000') $nr += 0x80000000;
    if($result2 == '80000000') $nr2 += 0x80000000;

    return sprintf("%08lx%08lx", $nr, $nr2);
}
**/


mysql 4.1.x 이상 새로운 password() 함수 - password()

function mysql_new_password( $pw ) {
    return (strlen($pw) > 0) ? strtoupper('*'.sha1(sha1($pw, true))) : ($pw === null ? null : '');
}

 

출처 : PHP5 에서 mysql password, old_password 구현

-- > http://andstory.com/zb41/zboard.php?id=tip_board&page=7&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=subject&desc=asc&no=425

 

 

딱 맞는 소스를 검색도중 찾았다

출처 : http://www.taeyo.pe.kr/Forum/Content.aspx?SEQ=148467&TBL=ASP&PGN=1

먼저 이 내용은 닭짓임을 알려드립니다

password 함수는 단방향 암호화입니다
대개의 경우 복호화는 안되는 지라
php + mysql 에서도 로그인시에도 이를테면
select * from member_table where member_id=$id and member_pw=password($pw)
처럼 입력받은 암호를 저장시와 같은 루틴으로 암호화한 후 비교하는 방식으로 이루어집니다

많은 경우 비밀번호 변경을 유도하는 경우가 많으며
정말 곤란한 경우라면 password 함수를 구현하는 수밖에 없다고 여겨집니다.(만 이런 경우도 본적이 없습니다)

년차가 쌓이다 보니 늘어나게 된건 검색능력밖에 없는지라
몇가지 레퍼런스 페이지와 조합된 결과물을 알려드립니다

<script language="jscript" runat="server">
/*
 * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
 * in FIPS PUB 180-1
 * Version 2.1a Copyright Paul Johnston 2000 - 2002.
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 * Distributed under the BSD License
 * See http://pajhome.org.uk/crypt/md5 for details.
 */

/*
 * Configurable variables. You may need to tweak these to be compatible with
 * the server-side, but the defaults work in most cases.
 */
var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
var b64pad  = "="; /* base-64 pad character. "=" for strict RFC compliance   */
var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */

/*
 * These are the functions you'll usually want to call
 * They take string arguments and return either hex or base-64 encoded strings
 */
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}

/*
 * Perform a simple self-test to see if the VM is working
 */
function sha1_vm_test()
{
  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}

/*
 * Calculate the SHA-1 of an array of big-endian words, and a bit length
 */
function core_sha1(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << (24 - len % 32);
  x[((len + 64 >> 9) << 4) + 15] = len;

  var w = Array(80);
  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;
  var e = -1009589776;

  for(var i = 0; i < x.length; i += 16)
  {
    var olda = a;
    var oldb = b;
    var oldc = c;
    var oldd = d;
    var olde = e;

    for(var j = 0; j < 80; j++)
    {
      if(j < 16) w[j] = x[i + j];
      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
                       safe_add(safe_add(e, w[j]), sha1_kt(j)));
      e = d;
      d = c;
      c = rol(b, 30);
      b = a;
      a = t;
    }

    a = safe_add(a, olda);
    b = safe_add(b, oldb);
    c = safe_add(c, oldc);
    d = safe_add(d, oldd);
    e = safe_add(e, olde);
  }
  return Array(a, b, c, d, e);

}

/*
 * Perform the appropriate triplet combination function for the current
 * iteration
 */
function sha1_ft(t, b, c, d)
{
  if(t < 20) return (b & c) | ((~b) & d);
  if(t < 40) return b ^ c ^ d;
  if(t < 60) return (b & c) | (b & d) | (c & d);
  return b ^ c ^ d;
}

/*
 * Determine the appropriate additive constant for the current iteration
 */
function sha1_kt(t)
{
  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
         (t < 60) ? -1894007588 : -899497514;
}

/*
 * Calculate the HMAC-SHA1 of a key and some data
 */
function core_hmac_sha1(key, data)
{
  var bkey = str2binb(key);
  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);

  var ipad = Array(16), opad = Array(16);
  for(var i = 0; i < 16; i++)
  {
    ipad[i] = bkey[i] ^ 0x36363636;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;
  }

  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
  return core_sha1(opad.concat(hash), 512 + 160);
}

/*
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 * to work around bugs in some JS interpreters.
 */
function safe_add(x, y)
{
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}

/*
 * Bitwise rotate a 32-bit number to the left.
 */
function rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

/*

 * Convert an 8-bit or 16-bit string to an array of big-endian words
 * In 8-bit function, characters >255 have their hi-byte silently ignored.
 */
function str2binb(str)
{
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
  return bin;
}

/*
 * Convert an array of big-endian words to a string
 */
function binb2str(bin)
{
  var str = "";
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < bin.length * 32; i += chrsz)
    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
  return str;
}

/*
 * Convert an array of big-endian words to a hex string.
 */
function binb2hex(binarray)
{
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i++)
  {
    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
  }
  return str;
}

/*
 * Convert an array of big-endian words to a base-64 string
 */
function binb2b64(binarray)
{
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var str = "";
  for(var i = 0; i < binarray.length * 4; i += 3)
  {
    var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)
                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
                |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    }
  }
  return str;
}

//mysql 5.x 이상???
function password(str) {
  if(str == null)
      return null;
  if(str.length == 0)
      return "";
  return "*" + hex_sha1(str_sha1(str)).toUpperCase();
}
//mysql 구버젼( 올리신 질문 내용으로는 이게 맞는거 같음 )
function old_password(str) {
  if(str == null)
      return null;
  if(str.length == 0)
      return "";
  var nr = 1345345333;
  var add = 7;
  var nr2 = 0x12345671;
  var ch, chr, i = 0;
  while(chr = str.charAt(i++)) {
    if(chr == '' || chr == ' ' || chr == '\t')
        continue;
    ch = chr.charCodeAt(0);
    nr ^= (((nr & 63) + add) * ch) + (nr << 8);
    nr2 += (nr2 << 8) ^ nr;
    add += ch;
  }
  nr &= 0x7fffffff;
  nr2 &= 0x7fffffff;
  
  return ("00000000" + nr.toString(16)).slice(-8) + ("00000000" + nr2.toString(16)).slice(-8);
}
</script>
<%
아이디 = Request.Form("mid")
비밀번호 = Request.Form("mpw")
...db 연결...
Set rs = db.Execute("SELECT * FROM 회원정보 WHERE mid='" & 아이디 & "' AND mpw='" & old_password(비
밀번호) & "'")
...나머지 처리...

대충 이런 방식이면 될거라 생각되는데..... 아무리 봐도 닭짓이네요 ^^

소스는 필요한 부분만 정리하면 줄어들겠지만, 원본을 살리는 의미에서 그대로 살려뒀습니다

참고한 페이지는 다음과 같습니다

* mysql 암호화 함수의 원리(?)
http://reznoa.nayana.com/tt/entry/MySQL-암호화-함수를-PHP에서-사용하기
* asp 에서의 sha1 암호화
http://forums.aspfree.com/code-bank-54/asp-classic-sha1-hash-82166.html

 

자바스크립트로도 가능함

 

<%@ Language=VBScript%>
<script language="javascript" type="text/javascript" runat="server">

//mysql 구버젼

function old_password(str) {
  if(str == null)
      return null;
  if(str.length == 0)
      return "";
  var nr = 1345345333;
  var add = 7;
  var nr2 = 0x12345671;
  var ch, chr, i = 0;
  while(chr = str.charAt(i++)) {
    if(chr == '' || chr == ' ' || chr == '\t')
        continue;
    ch = chr.charCodeAt(0);
    nr ^= (((nr & 63) + add) * ch) + (nr << 8);
    nr2 += (nr2 << 8) ^ nr;
    add += ch;
  }
  nr &= 0x7fffffff;
  nr2 &= 0x7fffffff;

  return ("00000000" + nr.toString(16)).slice(-8) + ("00000000" + nr2.toString(16)).slice(-8);
}

</script>
<%
response.write  old_password("1111")
%>

 

화면상 결과는 : 45271aba0b765d95

mysql 에서 select old_password('1111') 한결과와 동일하다.

 

반응형

'Story > asp' 카테고리의 다른 글

asp file download  (0) 2015.02.06
Mssql To Xml  (0) 2013.03.13
asp 로 rss feed (reader) 구현하기  (0) 2011.07.01
asp 쿠키(Cookies) 사용  (0) 2011.02.25
asp 특정 아이피(ip)일때 처리  (0) 2011.02.19