الگوریتم md5

نویسنده mohammad a, بعد از ظهر 13:05:14 - 12/25/11

« هارپ چیست؟ | تاپیک سوال و جواب های زبان c »

0 اعضا و 1 مهمان درحال دیدن موضوع.

mohammad a

سلام لطفا الگوریتم md5  را توضیح دهید.

aria_com63

یکی از معروف‌ترین روشهای تولید چکیده یک طرفه (One-Way hash) است که در سال 1992 توسط Ron Rivest ابداع شده است (RFC-1320-1321).
چنین الگوریتمی، با دریافت رشته دلخواه M (با طول رشته دلخواه)، نگاشت (H(M را به گونه‌ای محاسبه می‌نماید که به ازای تمام مقادیر M، خروجی دارای طول ثابتی ‌‌‌باشد.
عموما در دنیای تکنولوژی نرم‌افزار، از خروجی تابع (H(M با نام چکیده پیام (Message Digest) نام برده می‌شود.

یک الگوریتم چکیده یک طرفه، دارای دو ویژگی اساسی است:

    با داشتن خروجی (H(M، نمی‌توان به سادگی رشته M را محاسبه نمود.
    با داشتن رشته مفروض M1، پیدا نمودن رشته دلخواه M2، به گونه‌ای که (H(M1)=H(M2 باشد، کار بسیار مشکلی است.

دو رکن اساسی فوق به این معنی هستند که یک الگوریتم چکیده پیام، بازگشت ناپذیر (یکطرفه) بوده و احتمال وجود تصادم در الگوریتم آن (یعنی وجود دو رشته متفاوت که چکیده مشابهی داشته باشند) بسیار پایین است.

هر چند که تا کنون ویژگی اول در مورد الگوریتمهای چکیده پیام نقض نشده است، اما در مورد ویژگی دوم، نقض مکرر آن در نسلهای مختلف الگوریتمهای تولید چکیده پیام، موجب ظهور مبحثی تحت عنوان Collision Detection شده است.

در مورد الگوریتم MD5، اولین بار در سال 1993 (یک سال پس از معرفی MD5 بوده) Bert Boer و Antoon Bosselaers روشی را برای محاسبه دو رشته متفاوت با چکیده پیام مشابه پیدا نمودند. لازم به ذکر است که در حال حاضر، الگوریتم‌های کشف تصادم در MD5 آنقدر پیشرفته هستند که در مدت زمان 1 ساعت، می‌توان چندین رشته متفاوت پیدا نمود که چکیده یکسانی داشته باشند.

البته ذکر مطالب فوق به این معنی نیست که این الگوریتم فاقد امنیت است، بلکه با توجه به میزان امنیت مورد نیاز در الگوریتمهای رمزنگاری مورد استفاده، امنیت آن کافی نیست. در حال حاضر هم هنوز وبسایتها و نرم‌افزارهای بسیاری همچنان از این روش در CA های خود استفاده می‌کنند، اما اگر قرار بر حفظ امنیت در حد اعلای خود باشد، به جای این الگوریتم از الگوریتمهای دیگری مانند SHA-512 و MD6 استفاده خواهد شد.

MD5 یک الگوریتم 128 بیتی است. یعنی که حداکثر تعداد رشته‌های متفاوتی که می‌توان بدون بروز تصادم در این الگوریتم بدست آورد، 2 به توان 128، حالت است. الگوریتمهایی مانند SHA-512 و MD6 نیز که نسخه ارتقاء یافته MD5 است، 512 بیتی هستند.

اما فکر می‌کنید چرا با وجود الگوریتمهای چکیده 512 بیتی و یا حتی بزرگتر از آن، همچنان از روش MD5 هم استفاده می‌شود.؟!
پاسخ ساده است، "هزینه اجرای الگوریتم".

هر چقدر که میزان پیچیدگی عملیات نگاشت در الگوریتم مورد نظر افزایش یابد، هزینه اجرای آن نیز افزایش خواهد یافت.
با توجه به اینکه الگوریتمهای چکیده پیام، با توجه به کاربرد آنها معمولا به دفعات بسیار بسیار زیادی در طول پروسه یک نرم‌افزار اجرا خواهند شد، میزان بار اضافه آن بر کارایی برنامه باید قابل قبول باشد. در نتیجه با توجه به میزان اهمیت کدگذاری در برنامه و همچنین کارایی مورد انتظار از آن، در مورد انتخاب الگوریتم چکیده مناسب تصمیم‌گیری خواهد شد.


اما ساختار الگوریتم MD5 چگونه است:

رشته ورودی M دریافت شده و به بیتهای تشکیل دهنده آن تجزیه می‌شود.

با توجه به طول رشته (بیتی) در صورت نیاز عملیات لایه گذاری (Padding) بر روی آن انجام می‌شود. این عملیات به این صورت است که تا زمانی که باقیمانده تقسیم طول رشته بر 512 برابر با 448 گردد، به تعداد مورد نیاز، صفر به آن الحاق می‌گردد. (در نهایت پس از همه صفرها یک "1" هم اضافه می‌شود)

طول واقعی رشته M، به صورت یک عدد 64 بیتی، به انتهای خروجی مرحله دوم الحاق می‌گردد.

یک تابع Hash که به چهار تابع A تا D تقسیم شده است، بر روی بافر موجود اعمال شده و نتیجه آن در 128 بیت (چهار ثبات 32 بیتی) ذخیره می‌گردد.

بافر خروجی، به صورت بلاکهای 512 بیتی، به بخش اصلی الگوریتم که یک تابع فشرده‌سازی (نگاشت) است ارسال می‌گردد.

نتیجه تمام مراحل تابع فشرده سازی، به صورت یک رشته 128 بیتی محاسبه می‌گردد. این رشته همان خروجی الگوریتم MD5 است.

aria_com63

الگوریتم MD5 به زبان جاوا اسکریپت  پیاده سازی شده....
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/

/*
* 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   */

/*
* 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_md5(s)    { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
function b64_md5(s)    { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
function hex_hmac_md5(k, d)
  { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
function b64_hmac_md5(k, d)
  { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
function any_hmac_md5(k, d, e)
  { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }

/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
  return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
}

/*
* Calculate the MD5 of a raw string
*/
function rstr_md5(s)
{
  return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
}

/*
* Calculate the HMAC-MD5, of a key and some data (raw strings)
*/
function rstr_hmac_md5(key, data)
{
  var bkey = rstr2binl(key);
  if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);

  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 = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
  return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
}

/*
* Convert a raw string to a hex string
*/
function rstr2hex(input)
{
  try { hexcase } catch(e) { hexcase=0; }
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var output = "";
  var x;
  for(var i = 0; i < input.length; i++)
  {
    x = input.charCodeAt(i);
    output += hex_tab.charAt((x >>> 4) & 0x0F)
           +  hex_tab.charAt( x        & 0x0F);
  }
  return output;
}

/*
* Convert a raw string to a base-64 string
*/
function rstr2b64(input)
{
  try { b64pad } catch(e) { b64pad=''; }
  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var output = "";
  var len = input.length;
  for(var i = 0; i < len; i += 3)
  {
    var triplet = (input.charCodeAt(i) << 16)
                | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
                | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
    for(var j = 0; j < 4; j++)
    {
      if(i * 8 + j * 6 > input.length * 8) output += b64pad;
      else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
    }
  }
  return output;
}

/*
* Convert a raw string to an arbitrary string encoding
*/
function rstr2any(input, encoding)
{
  var divisor = encoding.length;
  var i, j, q, x, quotient;

  /* Convert to an array of 16-bit big-endian values, forming the dividend */
  var dividend = Array(Math.ceil(input.length / 2));
  for(i = 0; i < dividend.length; i++)
  {
    dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
  }

  /*
   * Repeatedly perform a long division. The binary array forms the dividend,
   * the length of the encoding is the divisor. Once computed, the quotient
   * forms the dividend for the next step. All remainders are stored for later
   * use.
   */
  var full_length = Math.ceil(input.length * 8 /
                                    (Math.log(encoding.length) / Math.log(2)));
  var remainders = Array(full_length);
  for(j = 0; j < full_length; j++)
  {
    quotient = Array();
    x = 0;
    for(i = 0; i < dividend.length; i++)
    {
      x = (x << 16) + dividend[i];
      q = Math.floor(x / divisor);
      x -= q * divisor;
      if(quotient.length > 0 || q > 0)
        quotient[quotient.length] = q;
    }
    remainders[j] = x;
    dividend = quotient;
  }

  /* Convert the remainders to the output string */
  var output = "";
  for(i = remainders.length - 1; i >= 0; i--)
    output += encoding.charAt(remainders[i]);

  return output;
}

/*
* Encode a string as utf-8.
* For efficiency, this assumes the input is valid utf-16.
*/
function str2rstr_utf8(input)
{
  var output = "";
  var i = -1;
  var x, y;

  while(++i < input.length)
  {
    /* Decode utf-16 surrogate pairs */
    x = input.charCodeAt(i);
    y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
    if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
    {
      x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
      i++;
    }

    /* Encode output as utf-8 */
    if(x <= 0x7F)
      output += String.fromCharCode(x);
    else if(x <= 0x7FF)
      output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
                                    0x80 | ( x         & 0x3F));
    else if(x <= 0xFFFF)
      output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
                                    0x80 | ((x >>> 6 ) & 0x3F),
                                    0x80 | ( x         & 0x3F));
    else if(x <= 0x1FFFFF)
      output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
                                    0x80 | ((x >>> 12) & 0x3F),
                                    0x80 | ((x >>> 6 ) & 0x3F),
                                    0x80 | ( x         & 0x3F));
  }
  return output;
}

/*
* Encode a string as utf-16
*/
function str2rstr_utf16le(input)
{
  var output = "";
  for(var i = 0; i < input.length; i++)
    output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
                                  (input.charCodeAt(i) >>> 8) & 0xFF);
  return output;
}

function str2rstr_utf16be(input)
{
  var output = "";
  for(var i = 0; i < input.length; i++)
    output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
                                   input.charCodeAt(i)        & 0xFF);
  return output;
}

/*
* Convert a raw string to an array of little-endian words
* Characters >255 have their high-byte silently ignored.
*/
function rstr2binl(input)
{
  var output = Array(input.length >> 2);
  for(var i = 0; i < output.length; i++)
    output[i] = 0;
  for(var i = 0; i < input.length * 8; i += 8)
    output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
  return output;
}

/*
* Convert an array of little-endian words to a string
*/
function binl2rstr(input)
{
  var output = "";
  for(var i = 0; i < input.length * 32; i += 8)
    output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
  return output;
}

/*
* Calculate the MD5 of an array of little-endian words, and a bit length.
*/
function binl_md5(x, len)
{
  /* append padding */
  x[len >> 5] |= 0x80 << ((len) % 32);
  x[(((len + 64) >>> 9) << 4) + 14] = len;

  var a =  1732584193;
  var b = -271733879;
  var c = -1732584194;
  var d =  271733878;

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

    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);

    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);

    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);

    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);

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

/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
  return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
  return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}

/*
* 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 bit_rol(num, cnt)
{
  return (num << cnt) | (num >>> (32 - cnt));
}

ali22

این الگوریتم یک رشته با طول متفاوت را به عنوان ورودی می گیرد و یک "خلاصه پیام MD5" یا "اثر انگشت" با طول 128 بیت می سازد.
در این روش اینکه دو پیام مختلف دارای یک "خلاصه پیام" باشند یا اینکه یک رشته از روی یک "خلاصه پیام" ساخته شود غیر ممکن می باشد. این الگوریتم برای امضاهای دیجیتال مناسب است، جایی که احتیاج به خلاصه کردن یک فایل بزرگ در یک رشتهء امن و فشرده، قبل از کد کردن آن متن، در سیستم های کدینگ، با کلید های خصوصی و عمومی آن سیستم مانند RSA (Rivest Shamir Adelman)
الگوریتم MD5 برای داشتن سرعت بالا در ماشین های 32 بیتی طراحی شده است در عین حال احتیاجی به جانشینی ها در جداول بزرگ ندارد. این الگوریتم را با کدهای بسیار کمی می توان نوشت.
الگوریتم MD5 توسعه ای از الگوریتم MD4 می باشد با این تفاوت که MD5 کمی کندتر از MD4 عمل می کند اما در طراحی آن بسیار محافظه کارانه عمل شده است.
MD5 به این دلیل طراحی شد که حس کردند MD4 به عنوان سرعت بالایی که داشت پذیرفته شده و از امنیت بالایی در شرایط بحرانی برخوردار نمی باشد. MD4 برای سرعت بالا طراحی شده ولی احتمال شکست آن در رمز کردنی موفق وجود دارد. MD5 کمی در سرعت کند شده با این تفاوت که بیشترین امنیت را داراست. این الگوریتم حاصل تاثیر دادن نظرات تعدادی از استفاده کنندگان MD4 به همراه مقادیری تغییر در ساختار الگوریتم برای افزایش سرعت و قدرت آن می باشد. الگوریتم MD5 در این مکان عومی قرارگرفته تا از آن استفاده و در صورت امکان استاندارد شود.

2- شرایط و نکات لازم:
در این متن منظور از « کلمه» تعداد 32 بیت و «بایت» تعداد 8 بیت داده می باشد. یک صف از بیت ها دارای خصوصیات طبیعی یک صف از بایتها می باشند که هر گروه هشت تایی متوالی از بیتها یک بایت را تشکیل می دهند که پرارزش ترین بیت در ابتدا قرار دارد. یک صف از بایت ها دقیقا مشابه یک صف 32 بیتی از کلمات پردازش می شود. جایی که گروهی 4 تایی از توالی بایتها پردازش می شوند، کم ارزش ترین بایت اولین بایت می باشد.
اجازه بدهید از x_i بجای xi (x اندیس i ) استفاده کنیم و اگر مقدار اندیس یک عبارت محاسباتی بود آن را در **} محدود می کنیم، مانند: x_{i-1} . همچنین از ^ به عنوان علامت توان استفاده می کنیم، پس x^i یعنیx به توان i .
اجازه بدهید از علامت «+» برای اضافه کردن دو کلمه به هم استفاده کنیم. از x<<<5 به عنوان عملگر چرخش بیتی در کلمات استفاده می شود کهx به اندازه 5 بیت به چپ چرخش می کند.
از not (x) به عنوان عملگر نقیض بیتی، از X v Y به عنوان عملگر فصل (or) و از X xor Y به عنوان عملگر exclusive or و از XY به عنوان عملگر عطف (and) استفاده می کنیم.

3- توضیحات الگوریتم MD5:
فرض کنید ما b بیت پیام به عنوان ورودی داریم و تصمیم داریم خلاصه پیام آن را بدست آوریم. b در اینجا یک عدد نا منفی و صحیح است، b می تواند مقدار صفر داشته باشد و هیچ محدودیتی برای مضرب هشت بودن آن نیست و به هر اندازه می تواند بزرگ باشد. فرض کنید بیت های این پیام را بشود به صورت زیر نوشت:

m_0 m_1 ... m_{b-1}

برای آوردن خلاصه پیام 5 مرحله زیر را انجام می دهیم:
____________
گام 1- اضافه کردن بیتهای نرم کننده:

طول پیام مورد نظر به 448 به پیمانه 512 توسعه پیدا می کند به این معنی که اگر به طول پیام 64 بیت اضافه شود، طولش مضربی از 512 خواهد بود. عمل توسعه دادن همیشه اجرا می شود مگر اینکه طول پیام به صورت 448 به پیمانه 512 باشد.
عمل توسعه پیام یا نرم کردن آن به صورت زیر انجام می شود:
یک بیت [1] سپس تعدادی بیت

به پیام اضافه می شود.اضافه شدن بیت های 0 تا زمانی که طول رشته به 448 بر پایه 512 برسد، ادامه پیدا می کند. در این عمل حداقل یک بیت و حداکثر 512 بیت اضافه خواهد شد.

گام 2- افزایش طول:

یک نمایش 64 بیتی از b بیت پیام اولیه به آخر نتیجه گام قبل اضافه می شود. در بدترین حالت، b بزرگتر از 64 بیت خواهد بود. در این حالت فقط 64 بیت کم ارزش b استفاده خواهد شد.
هم اکنون طول پیام بدست آمده دقیقا معادل مضربی از 512 خواهد بود. مشابه اینکه بگوییم، این پیام طولی معادل مضربی از16 کلمه دارد اجازه بدهید M[0...N-1] را نمایانگر کلمات پیام بدست آمده بدانیم. (N مضربی از 16 می باشد.)

گام 3- یین بافر برای MD:

برای محاسبه خلاصه پیام یک بافر 4 کلمه ای (A,B,C,D) استفاده می شود. هر کدام از A، B، Cو D یک ثبات 32 بیتی می باشند. این ثبات ها مطابق جدول زیر مقدار دهی می شوند ( بایتهای کم ارزش در ابتدا قرار دارند )

word A: 01 23 45 67
word B: 89 ab cd ef
word C: fe dc ba 98
word D: 76 54 32 10

گام 4- پردازش پیام در بلاک های 16 کلمه ای:
در ابتدا 4 تابع کمکی تعریف می کنیم که هر کدام به عنوان ورودی سه کلمهء 32 بیتی می گیرد و برای خروجی یک کلمهء 32 بیتی تولید می کند.

F(X,Y,Z) = XY v not(X) Z
G(X,Y,Z) = XZ v Y not(Z)
H(X,Y,Z) = X xor Y xor Z
I(X,Y,Z) = Y xor (X v not(Z))

در هر موقعیت بیتی، F به عنوان شرط عمل می کند: اگر X آنگاه Y در غیر این صورت Z. تابع F می توانست طوری تعریف شود که به جای استفاده از v از + استفاده کند چون XY و not(X) هرگز یک هایی در موقعیت بیتی یکسان نخواهد داشت. جالب است به یاد داشته باشید که اگر بیت های X، Y و Z مستقل و غیر مرتبط باشند، هر بیت از F(X, Y, Z) مستقل و غیر مرتبط خواهد بود.
توابع G، H و I شبیه تابع F هستند، به طوری که آنها در "توازی بیتی" کار می کنند تا خروجی شان را از بیت های X، Y و Z تولید کنند. در چنین روشی اگر بیت های متناظر X، Y و Z مستقل و غیر مرتبط باشند، آنگاه هر بیت از G(X, Y, Z)، H(X, Y, Z) و I(X, Y, Z) مستقل و غیر مرتبط خواهند بود.
توجه داشته باشید که تابع H، تابع XOR یا توازن بیتی از ورودی هایش است. این گام از یک جدول 64 عنصری T[1...64] ساخته شده از یک تابع مثلثاتی، استفاده می کند. اجازه دهید T، I-امین عنصر جدول را مشخص می کند که برابر است با قسمت صحیح حاصلضرب 4294967296 در abs(sin(i))، به طوری که I به رادیان باشد.
کارهای زیر را انجام می دهید:


/* Process each 16-word block. */
   For i = 0 to N/16-1 do

     /* Copy block i into X. */
     For j = 0 to 15 do
       Set X[j] to M[i*16+j].
     end /* of loop on j */

     /* Save A as AA, B as BB, C as CC, and D as DD. */
     AA = A
     BB = B
     CC = C
     DD = D

     /* Round 1. */
     /* Let [abcd k s i] denote the operation
          a = b + ((a + F(b,c,d) + X[k] + T) <<< s). */
     /* Do the following 16 operations. */
     [ABCD  0  7  1]  [DABC  1 12  2]  [CDAB  2 17  3]  [BCDA  3 22  4]
     [ABCD  4  7  5]  [DABC  5 12  6]  [CDAB  6 17  7]  [BCDA  7 22  8]
     [ABCD  8  7  9]  [DABC  9 12 10]  [CDAB 10 17 11]  [BCDA 11 22 12]
     [ABCD 12  7 13]  [DABC 13 12 14]  [CDAB 14 17 15]  [BCDA 15 22 16]

     /* Round 2. */
     /* Let [abcd k s i] denote the operation
          a = b + ((a + G(b,c,d) + X[k] + T) <<< s). */
     /* Do the following 16 operations. */
     [ABCD  1  5 17]  [DABC  6  9 18]  [CDAB 11 14 19]  [BCDA  0 20 20]
     [ABCD  5  5 21]  [DABC 10  9 22]  [CDAB 15 14 23]  [BCDA  4 20 24]
     [ABCD  9  5 25]  [DABC 14  9 26]  [CDAB  3 14 27]  [BCDA  8 20 28]
     [ABCD 13  5 29]  [DABC  2  9 30]  [CDAB  7 14 31]  [BCDA 12 20 32]

     /* Round 3. */
     /* Let [abcd k s t] denote the operation
          a = b + ((a + H(b,c,d) + X[k] + T) <<< s). */
     /* Do the following 16 operations. */
     [ABCD  5  4 33]  [DABC  8 11 34]  [CDAB 11 16 35]  [BCDA 14 23 36]
     [ABCD  1  4 37]  [DABC  4 11 38]  [CDAB  7 16 39]  [BCDA 10 23 40]
     [ABCD 13  4 41]  [DABC  0 11 42]  [CDAB  3 16 43]  [BCDA  6 23 44]
     [ABCD  9  4 45]  [DABC 12 11 46]  [CDAB 15 16 47]  [BCDA  2 23 48]

     /* Round 4. */
     /* Let [abcd k s t] denote the operation
          a = b + ((a + I(b,c,d) + X[k] + T) <<< s). */
     /* Do the following 16 operations. */
     [ABCD  0  6 49]  [DABC  7 10 50]  [CDAB 14 15 51]  [BCDA  5 21 52]
     [ABCD 12  6 53]  [DABC  3 10 54]  [CDAB 10 15 55]  [BCDA  1 21 56]
     [ABCD  8  6 57]  [DABC 15 10 58]  [CDAB  6 15 59]  [BCDA 13 21 60]
     [ABCD  4  6 61]  [DABC 11 10 62]  [CDAB  2 15 63]  [BCDA  9 21 64]

     /* Then perform the following additions. (That is increment each
        of the four registers by the value it had before this block
        was started.) */
     A = A + AA
     B = B + BB
     C = C + CC
     D = D + DD

   end /* of loop on i */


گام 5- خروجی:

خلاصه پیامی که به عنوان خروجی تولید می شود و عبارت است از A، B، C و D، که ما با کم ارزش ترین بیت A شروع می کنیم و به با ارزش ترین بیت D خاتمه می دهیم. این تعریف MD5 را کامل می کند.

4- نتیجه:
الگوریتم خلاصه پیام MD5 به سادگی قابل اجرا می باشد و یک "اثر انگشت" یا "خلاصه پیام" از پیام با طول اختیاری تولید می کند. گمان برده می شود که امکان مواجه شدن با دو پیام که خلاصه پیام مشابهی دارند از رتبهء 64^2 و برای هر پیامی که به آن یک خلاصه پیام داده شده است از رتبهء 128^2 می باشد.
الگوریتم MD5 برای نقاط ضعف به دقت بررسی شده است. به هر حال این الگوریتم نسبتا جدید است و تحلیل امنیتی بیشتری را طلب می کند، مشابه طرح های مشابه در این رده.

Tags:

Share via facebook Share via linkedin Share via telegram Share via twitter Share via whatsapp