Changeset 4929


Ignore:
Timestamp:
May 13, 2009, 2:54:02 PM (14 years ago)
Author:
Martin Svensson
Message:

Fixes #1311 Login fails if password contains non-ASCII characters.

Location:
branches/2.11-stable
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/2.11-stable/src/core/net/sf/basedb/core/SessionControl.java

    r4689 r4929  
    313313    The client application should use the challenge as follows:
    314314    <ol>
    315     <li>Calculate the MD5 of the real password
     315    <li>Calculate the MD5 of the real UTF-8 encoded password
    316316    <li>Concatenate this with the challenge with a colon inbetween:
    317317      <code>MD5:challenge</code>
     
    352352
    353353    @param login The login of the user
    354     @param password The password for the user
     354    @param password The UTF-8 encoded password for the user
    355355    @param comment A comment for the login, which will show in the {@link Session}
    356356    @param encryptedPassword A flag indicating if the password has been encrypted
  • branches/2.11-stable/src/core/net/sf/basedb/util/MD5.java

    r4515 r4929  
    3737public class MD5
    3838{
     39  /**
     40    Calculates the MD5 hash of an UTF-8 encoded string.
     41  */
    3942  public static String getHashString(String in)
    4043  {
     
    4245    {
    4346      MessageDigest md5 = MessageDigest.getInstance("MD5");
    44       BigInteger result = new BigInteger(1, md5.digest(in.getBytes()));
     47      BigInteger result = new BigInteger(1, md5.digest(in.getBytes("UTF-8")));
    4548      return leftPad(result.toString(16), '0', 32);
    4649    }
  • branches/2.11-stable/www/include/scripts/md5.js

    r2306 r4929  
    22 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
    33 * Digest Algorithm, as defined in RFC 1321.
    4  * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
     4 * Version 2.2-alpha Copyright (C) Paul Johnston 1999 - 2009
    55 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
    66 * Distributed under the BSD License
     
    1212 * the server-side, but the defaults work in most cases.
    1313 */
    14 var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */
    15 var b64pad  = ""; /* base-64 pad character. "=" for strict RFC compliance   */
    16 var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */
     14var hexcase = 0;   /* hex output format. 0 - lowercase; 1 - uppercase        */
     15var b64pad  = "";  /* base-64 pad character. "=" for strict RFC compliance   */
    1716
    1817/*
     
    2019 * They take string arguments and return either hex or base-64 encoded strings
    2120 */
    22 function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
    23 function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
    24 function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
    25 function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
    26 function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
    27 function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
     21function hex_md5(s)    { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
     22function b64_md5(s)    { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
     23function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
     24function hex_hmac_md5(k, d)
     25  { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
     26function b64_hmac_md5(k, d)
     27  { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
     28function any_hmac_md5(k, d, e)
     29  { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
    2830
    2931/*
     
    3234function md5_vm_test()
    3335{
    34   return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
    35 }
    36 
    37 /*
    38  * Calculate the MD5 of an array of little-endian words, and a bit length
    39  */
    40 function core_md5(x, len)
     36  return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
     37}
     38
     39/*
     40 * Calculate the MD5 of a raw string
     41 */
     42function rstr_md5(s)
     43{
     44  return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
     45}
     46
     47/*
     48 * Calculate the HMAC-MD5, of a key and some data (raw strings)
     49 */
     50function rstr_hmac_md5(key, data)
     51{
     52  var bkey = rstr2binl(key);
     53  if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
     54
     55  var ipad = Array(16), opad = Array(16);
     56  for(var i = 0; i < 16; i++)
     57  {
     58    ipad[i] = bkey[i] ^ 0x36363636;
     59    opad[i] = bkey[i] ^ 0x5C5C5C5C;
     60  }
     61
     62  var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
     63  return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
     64}
     65
     66/*
     67 * Convert a raw string to a hex string
     68 */
     69function rstr2hex(input)
     70{
     71  try { hexcase } catch(e) { hexcase=0; }
     72  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
     73  var output = "";
     74  var x;
     75  for(var i = 0; i < input.length; i++)
     76  {
     77    x = input.charCodeAt(i);
     78    output += hex_tab.charAt((x >>> 4) & 0x0F)
     79           +  hex_tab.charAt( x        & 0x0F);
     80  }
     81  return output;
     82}
     83
     84/*
     85 * Convert a raw string to a base-64 string
     86 */
     87function rstr2b64(input)
     88{
     89  try { b64pad } catch(e) { b64pad=''; }
     90  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
     91  var output = "";
     92  var len = input.length;
     93  for(var i = 0; i < len; i += 3)
     94  {
     95    var triplet = (input.charCodeAt(i) << 16)
     96                | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
     97                | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
     98    for(var j = 0; j < 4; j++)
     99    {
     100      if(i * 8 + j * 6 > input.length * 8) output += b64pad;
     101      else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
     102    }
     103  }
     104  return output;
     105}
     106
     107/*
     108 * Convert a raw string to an arbitrary string encoding
     109 */
     110function rstr2any(input, encoding)
     111{
     112  var divisor = encoding.length;
     113  var i, j, q, x, quotient;
     114
     115  /* Convert to an array of 16-bit big-endian values, forming the dividend */
     116  var dividend = Array(Math.ceil(input.length / 2));
     117  for(i = 0; i < dividend.length; i++)
     118  {
     119    dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
     120  }
     121
     122  /*
     123   * Repeatedly perform a long division. The binary array forms the dividend,
     124   * the length of the encoding is the divisor. Once computed, the quotient
     125   * forms the dividend for the next step. All remainders are stored for later
     126   * use.
     127   */
     128  var full_length = Math.ceil(input.length * 8 /
     129                                    (Math.log(encoding.length) / Math.log(2)));
     130  var remainders = Array(full_length);
     131  for(j = 0; j < full_length; j++)
     132  {
     133    quotient = Array();
     134    x = 0;
     135    for(i = 0; i < dividend.length; i++)
     136    {
     137      x = (x << 16) + dividend[i];
     138      q = Math.floor(x / divisor);
     139      x -= q * divisor;
     140      if(quotient.length > 0 || q > 0)
     141        quotient[quotient.length] = q;
     142    }
     143    remainders[j] = x;
     144    dividend = quotient;
     145  }
     146
     147  /* Convert the remainders to the output string */
     148  var output = "";
     149  for(i = remainders.length - 1; i >= 0; i--)
     150    output += encoding.charAt(remainders[i]);
     151
     152  return output;
     153}
     154
     155/*
     156 * Encode a string as utf-8.
     157 * For efficiency, this assumes the input is valid utf-16.
     158 */
     159function str2rstr_utf8(input)
     160{
     161  var output = "";
     162  var i = -1;
     163  var x, y;
     164
     165  while(++i < input.length)
     166  {
     167    /* Decode utf-16 surrogate pairs */
     168    x = input.charCodeAt(i);
     169    y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
     170    if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
     171    {
     172      x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
     173      i++;
     174    }
     175
     176    /* Encode output as utf-8 */
     177    if(x <= 0x7F)
     178      output += String.fromCharCode(x);
     179    else if(x <= 0x7FF)
     180      output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
     181                                    0x80 | ( x         & 0x3F));
     182    else if(x <= 0xFFFF)
     183      output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
     184                                    0x80 | ((x >>> 6 ) & 0x3F),
     185                                    0x80 | ( x         & 0x3F));
     186    else if(x <= 0x1FFFFF)
     187      output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
     188                                    0x80 | ((x >>> 12) & 0x3F),
     189                                    0x80 | ((x >>> 6 ) & 0x3F),
     190                                    0x80 | ( x         & 0x3F));
     191  }
     192  return output;
     193}
     194
     195/*
     196 * Encode a string as utf-16
     197 */
     198function str2rstr_utf16le(input)
     199{
     200  var output = "";
     201  for(var i = 0; i < input.length; i++)
     202    output += String.fromCharCode( input.charCodeAt(i)        & 0xFF,
     203                                  (input.charCodeAt(i) >>> 8) & 0xFF);
     204  return output;
     205}
     206
     207function str2rstr_utf16be(input)
     208{
     209  var output = "";
     210  for(var i = 0; i < input.length; i++)
     211    output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
     212                                   input.charCodeAt(i)        & 0xFF);
     213  return output;
     214}
     215
     216/*
     217 * Convert a raw string to an array of little-endian words
     218 * Characters >255 have their high-byte silently ignored.
     219 */
     220function rstr2binl(input)
     221{
     222  var output = Array(input.length >> 2);
     223  for(var i = 0; i < output.length; i++)
     224    output[i] = 0;
     225  for(var i = 0; i < input.length * 8; i += 8)
     226    output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
     227  return output;
     228}
     229
     230/*
     231 * Convert an array of little-endian words to a string
     232 */
     233function binl2rstr(input)
     234{
     235  var output = "";
     236  for(var i = 0; i < input.length * 32; i += 8)
     237    output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
     238  return output;
     239}
     240
     241/*
     242 * Calculate the MD5 of an array of little-endian words, and a bit length.
     243 */
     244function binl_md5(x, len)
    41245{
    42246  /* append padding */
     
    130334  }
    131335  return Array(a, b, c, d);
    132 
    133336}
    134337
     
    155358{
    156359  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
    157 }
    158 
    159 /*
    160  * Calculate the HMAC-MD5, of a key and some data
    161  */
    162 function core_hmac_md5(key, data)
    163 {
    164   var bkey = str2binl(key);
    165   if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
    166 
    167   var ipad = Array(16), opad = Array(16);
    168   for(var i = 0; i < 16; i++)
    169   {
    170     ipad[i] = bkey[i] ^ 0x36363636;
    171     opad[i] = bkey[i] ^ 0x5C5C5C5C;
    172   }
    173 
    174   var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
    175   return core_md5(opad.concat(hash), 512 + 128);
    176360}
    177361
     
    194378  return (num << cnt) | (num >>> (32 - cnt));
    195379}
    196 
    197 /*
    198  * Convert a string to an array of little-endian words
    199  * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
    200  */
    201 function str2binl(str)
    202 {
    203   var bin = Array();
    204   var mask = (1 << chrsz) - 1;
    205   for(var i = 0; i < str.length * chrsz; i += chrsz)
    206     bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
    207   return bin;
    208 }
    209 
    210 /*
    211  * Convert an array of little-endian words to a string
    212  */
    213 function binl2str(bin)
    214 {
    215   var str = "";
    216   var mask = (1 << chrsz) - 1;
    217   for(var i = 0; i < bin.length * 32; i += chrsz)
    218     str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
    219   return str;
    220 }
    221 
    222 /*
    223  * Convert an array of little-endian words to a hex string.
    224  */
    225 function binl2hex(binarray)
    226 {
    227   var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
    228   var str = "";
    229   for(var i = 0; i < binarray.length * 4; i++)
    230   {
    231     str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
    232            hex_tab.charAt((binarray[i>>2] >> ((i%4)*8  )) & 0xF);
    233   }
    234   return str;
    235 }
    236 
    237 /*
    238  * Convert an array of little-endian words to a base-64 string
    239  */
    240 function binl2b64(binarray)
    241 {
    242   var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    243   var str = "";
    244   for(var i = 0; i < binarray.length * 4; i += 3)
    245   {
    246     var triplet = (((binarray[i   >> 2] >> 8 * ( i   %4)) & 0xFF) << 16)
    247                 | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
    248                 |  ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
    249     for(var j = 0; j < 4; j++)
    250     {
    251       if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
    252       else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
    253     }
    254   }
    255   return str;
    256 }
Note: See TracChangeset for help on using the changeset viewer.