code: function decrypt(buffer, params, keyLookupCallback) {
    var header = parseParams(params);
    if (header.version === 'aes128gcm') {
      var headerLength = readHeader(buffer, header);
      buffer = buffer.slice(headerLength);
    }
    var key = deriveKeyAndNonce(header, MODE_DECRYPT, keyLookupCallback);
    var start = 0;
    var result = new Buffer(0);
  
    var chunkSize = header.rs;
    if (header.version !== 'aes128gcm') {
      chunkSize += TAG_LENGTH;
    }
  
    for (var i = 0; start < buffer.length; ++i) {
      var end = start + chunkSize;
      if (header.version !== 'aes128gcm' && end === buffer.length) {
        throw new Error('Truncated payload');
      }
      end = Math.min(end, buffer.length);
      if (end - start <= TAG_LENGTH) {
        throw new Error('Invalid block: too small at ' + i);
      }
      var block = decryptRecord(key, i, buffer.slice(start, end),
                                header, end >= buffer.length);
      result = Buffer.concat([result, block]);
      start = end;
    }
    return result;
  }
docs: Decrypt some bytes.  This uses the parameters to determine the key and block
  size, which are described in the draft.  Binary values are base64url encoded.
  
  |params.version| contains the version of encoding to use: aes128gcm is the latest,
  but aesgcm is also accepted (though the latter might
  disappear in a future release).  If omitted, assume aes128gcm.
  
  If |params.key| is specified, that value is used as the key.
  
  If the version is aes128gcm, the keyid is extracted from the header and used
  as the ECDH public key of the sender.  For version aesgcm ,
  |params.dh| needs to be provided with the public key of the sender.
  
  The |params.privateKey| includes the private key of the receiver.