text: /** @fileOverview Bit array codec implementations.
   *
   * @author Emily Stark
   * @author Mike Hamburg
   * @author Dan Boneh
   */
  
  /** @namespace Base64 encoding/decoding */
  sjcl.codec.base64 = {
    /** The base64 alphabet.
     * @private
     */
    _chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    
    /** Convert from a bitArray to a base64 string. */
    fromBits: function (arr, _noEquals, _url) {
      var out = "", i, bits=0, c = sjcl.codec.base64._chars, ta=0, bl = sjcl.bitArray.bitLength(arr);
      if (_url) {
        c = c.substr(0,62) + '-_';
      }
      for (i=0; out.length * 6 < bl; ) {
        out += c.charAt((ta ^ arr[i]>>>bits) >>> 26);
        if (bits < 6) {
          ta = arr[i] << (6-bits);
          bits += 26;
          i++;
        } else {
          ta <<= 6;
          bits -= 6;
        }
      }
      while ((out.length & 3) && !_noEquals) { out += "="; }
      return out;
    },
    
    /** Convert from a base64 string to a bitArray */
    toBits: function(str, _url) {
      str = str.replace(/\s|=/g,'');
      var out = [], i, bits=0, c = sjcl.codec.base64._chars, ta=0, x;
      if (_url) {
        c = c.substr(0,62) + '-_';
      }
      for (i=0; i<str.length; i++) {
        x = c.indexOf(str.charAt(i));
        if (x < 0) {
          throw new sjcl.exception.invalid("this isn't base64!");
        }
        if (bits > 26) {
          bits -= 26;
          out.push(ta ^ x>>>bits);
          ta  = x << (32-bits);
        } else {
          bits += 6;
          ta ^= x << (32-bits);
        }
      }
      if (bits&56) {
        out.push(sjcl.bitArray.partial(bits&56, ta, 1));
      }
      return out;
    }
  };
  
  sjcl.codec.base64url = {
    fromBits: function (arr) { return sjcl.codec.base64.fromBits(arr,1,1); },
    toBits: function (str) { return sjcl.codec.base64.toBits(str,1); }
  };
  