docs: function (password, plaintext, params, rp) {
      params = params || {};
      rp = rp || {};
  
      var j = sjcl.json, p = j._add({ iv: sjcl.random.randomWords(4,0) },
                                    j.defaults), tmp, prp, adata;
      j._add(p, params);
      adata = p.adata;
      if (typeof p.salt === "string") {
        p.salt = sjcl.codec.base64.toBits(p.salt);
      }
      if (typeof p.iv === "string") {
        p.iv = sjcl.codec.base64.toBits(p.iv);
      }
  
      if (!sjcl.mode[p.mode] ||
          !sjcl.cipher[p.cipher] ||
          (typeof password === "string" && p.iter <= 100) ||
          (p.ts !== 64 && p.ts !== 96 && p.ts !== 128) ||
          (p.ks !== 128 && p.ks !== 192 && p.ks !== 256) ||
          (p.iv.length < 2 || p.iv.length > 4)) {
        throw new sjcl.exception.invalid("json encrypt: invalid parameters");
      }
  
      if (typeof password === "string") {
        tmp = sjcl.misc.cachedPbkdf2(password, p);
        password = tmp.key.slice(0,p.ks/32);
        p.salt = tmp.salt;
      } else if (sjcl.ecc && password instanceof sjcl.ecc.elGamal.publicKey) {
        tmp = password.kem();
        p.kemtag = tmp.tag;
        password = tmp.key.slice(0,p.ks/32);
      }
      if (typeof plaintext === "string") {
        plaintext = sjcl.codec.utf8String.toBits(plaintext);
      }
      if (typeof adata === "string") {
        p.adata = adata = sjcl.codec.utf8String.toBits(adata);
      }
      prp = new sjcl.cipher[p.cipher](password);
  
      /* return the json data */
      j._add(rp, p);
      rp.key = password;
  
      /* do the encryption */
      p.ct = sjcl.mode[p.mode].encrypt(prp, plaintext, p.iv, adata, p.ts);
  
      //return j.encode(j._subtract(p, j.defaults));
      return p;
    }