docs: function (str) {
      str = str.replace(/\s/g,'');
      if (!str.match(/^\{.*\}$/)) {
        throw new sjcl.exception.invalid("json decode: this isn't json!");
      }
      var a = str.replace(/^\{|\}$/g, '').split(/,/), out={}, i, m;
      for (i=0; i<a.length; i++) {
        if (!(m=a[i].match(/^\s*(?:(["']?)([a-z][a-z0-9]*)\1)\s*:\s*(?:(-?\d+)|"([a-z0-9+\/%*_.@=\-]*)"|(true|false))$/i))) {
          throw new sjcl.exception.invalid("json decode: this isn't json!");
        }
        if (m[3]) {
          out[m[2]] = parseInt(m[3],10);
        } else if (m[4]) {
          out[m[2]] = m[2].match(/^(ct|adata|salt|iv)$/) ? sjcl.codec.base64.toBits(m[4]) : unescape(m[4]);
        } else if (m[5]) {
          out[m[2]] = m[5] === 'true';
        }
      }
      return out;
    }