
function PBKDF2(password,salt,num_iterations,num_bytes)
{var m_bpassword=str2binb(password);var m_salt=salt;var m_total_iterations=num_iterations;var m_iterations_in_chunk=10;var m_iterations_done=0;var m_key_length=num_bytes;var m_hash_length=20;var m_total_blocks=Math.ceil(m_key_length/m_hash_length);var m_current_block=1;var m_ipad=new Array(16);var m_opad=new Array(16);var m_buffer=new Array(0x0,0x0,0x0,0x0,0x0);var m_key="";var m_result_func;var m_status_func;if(m_bpassword.length>16)m_bpassword=core_sha1(m_bpassword,password.length*chrsz);for(var i=0;i<16;++i)
{m_ipad[i]=m_bpassword[i]^0x36363636;m_opad[i]=m_bpassword[i]^0x5C5C5C5C;}
this.deriveKey=function(status_callback,result_callback)
{m_status_func=status_callback;m_result_func=result_callback;var this_object=this;setTimeout(function(){this_object.do_PBKDF2_iterations()},0);}
this.do_PBKDF2_iterations=function()
{var iterations=m_iterations_in_chunk;if(m_total_iterations-m_iterations_done<m_iterations_in_chunk)
iterations=m_total_iterations-m_iterations_done;for(var i=0;i<iterations;++i)
{if(m_iterations_done==0)
{var salt_block=m_salt+
String.fromCharCode(m_current_block>>24&0xF)+
String.fromCharCode(m_current_block>>16&0xF)+
String.fromCharCode(m_current_block>>8&0xF)+
String.fromCharCode(m_current_block&0xF);m_hash=core_sha1(m_ipad.concat(str2binb(salt_block)),512+salt_block.length*8);m_hash=core_sha1(m_opad.concat(m_hash),512+160);}
else
{m_hash=core_sha1(m_ipad.concat(m_hash),512+m_hash.length*32);m_hash=core_sha1(m_opad.concat(m_hash),512+160);}
for(var j=0;j<m_hash.length;++j)
m_buffer[j]^=m_hash[j];m_iterations_done++;}
m_status_func((m_current_block-1+m_iterations_done/m_total_iterations)/m_total_blocks*100);if(m_iterations_done<m_total_iterations)
{var this_object=this;setTimeout(function(){this_object.do_PBKDF2_iterations()},0);}
else
{if(m_current_block<m_total_blocks)
{m_key+=binb2hex(m_buffer);m_current_block++;m_buffer=new Array(0x0,0x0,0x0,0x0,0x0);m_iterations_done=0;var this_object=this;setTimeout(function(){this_object.do_PBKDF2_iterations()},0);}
else
{var tmp=binb2hex(m_buffer);m_key+=tmp.substr(0,(m_key_length-(m_total_blocks-1)*m_hash_length)*2);m_result_func(m_key);}}}}