Create a Magic Wormhole and communicate through it.

    Wormholes are created by speaking the same magic CODE in two
    different places at the same time.  Wormholes are secure against
    anyone who doesn't use the same code.
555692
def wormhole(context, dump_timing, transit_helper, relay_url, appid):
    
    context.obj = cfg = Config()
    cfg.appid = appid
    cfg.relay_url = relay_url
    cfg.transit_helper = transit_helper
    cfg.dump_timing = dump_timing
1137169
def send(self, content):
        
        LOGGER.debug('Sending: %s', content)
        all_bytes = struct.pack('>i', Connection.PROTOCOL_VERSION)
        all_bytes += struct.pack('>i', self._id)
        all_bytes += struct.pack('>i', 2)
        self._id += 1
        for char in content:
            all_bytes += struct.pack('>c', char.encode('utf8'))

        encrypted_bytes = self._crypt.encrypt(all_bytes)

        message_length = Connection.COMM_LENGTH + len(encrypted_bytes)

        self._socket.send(struct.pack('>i', message_length))
        self._socket.send(struct.pack('>i', Connection.NO_COMM_ERROR))
        self._socket.send(encrypted_bytes)
        LOGGER.debug('Sent')

        message = self.recv()
        while message is None:
            message = self.recv()
            yield message

        yield message
906409
function createHubType() {
    log.info("create hub");
    // [ -Events- ]
    // error - emitted when received messages are poorly formatted
    // listen - emitted when listening
    // close - emitted when the hub is closed
    // status - various hub status updates
    // [ -Constructor- ]
    function Hub() {
        log.info("instantiate hub");
        // get non-ambiguous this
        var self = this;
        // Call parent constructor
        Hub.super_.call(self);
        // Internal structures
        self._subscribers = {};
        // subsribers is { source._id: {'source': source, patterns: [pattern*]}}
        self._transport = undefined;
        self._closed = false;
        // state listeners
        self.once('close', function handleClosed() {
            self._closed = true;
        });
        // Constructor.  Return undefined.
        return undefined;
    }
    // [ -Inheritance- ]
    util.inherits(Hub, events.EventEmitter);
    // [ -Private API- ]
    // disconnect a client
    Hub.prototype._disconnectClient = function hubDisconnectClient(client, error, cb) {
        client.close(cb);
        setImmediate(this.emit.bind(this), 'status', "closed client connection", error);
        this.emit('error', error);
        // allow chaining
        return this;
    };
    // handle publication request
    Hub.prototype._handlePublication = function hubHandlePublication(source, messageObj) {
        log.info("hub on publication");
        // get a non-ambiguous "this"
        var self = this;
        var error = validateProperties(
            messageObj,
            "publication message from transport layer",
            ['type', 'message', 'channel', 'transactionID'],
            []
        );
        if (error) { self._disconnectClient(source, error); return null; }
        // FIXME message should be JSON
        // FIXME channel should be regex
        self._distribute(messageObj.message, messageObj.channel, function distributeCB(numPublished) {
            // notify source of publication and number published
            source.send({
                type: 'published',
                'message': messageObj.message,
                channel: messageObj.channel,
                number: numPublished,
                transactionID: messageObj.transactionID,
            }, function onError(error) {
                if (error) { self._disconnectClient(source, error); }
            });
        });
        // allow chaining
        return this;
    };
    // handle subscription request
    Hub.prototype._handleSubscription = function hubHandleSubscription(source, messageObj) {
        log.info("hub on subscription");
        // get a non-ambiguous "this"
        var self = this;
        var error = validateProperties(
            messageObj,
            "subscription message from transport layer",
            ['type', 'pattern', 'transactionID'],
            []
        );
        if (error) { self._disconnectClient(source, error); return null; }
        // FIXME - pattern should be a regex
        var subscriber = self._subscribers[source._id];
        if (subscriber === undefined) {
            subscriber = {
                patterns: [],
                connection: source,
            };
            log.debug("number of unique subscribers: ", _.keys(self._subscribers).length + 1);
        }
        if (!_.contains(subscriber.patterns, messageObj.pattern)) {
            subscriber.patterns.push(messageObj.pattern);
        }
        self._subscribers[source._id] = subscriber;
        // notify source that subscription is in place
        source.send({
            type: 'subscribed',
            pattern: messageObj.pattern,
            number: subscriber.patterns.length,
            transactionID: messageObj.transactionID,
        }, function onError(error) {
            if (error) { self._disconnectClient(source, error); }
        });
        // allow chaining
        return this;
    };
    // handle unsubscription request
    Hub.prototype._handleUnsubscription = function hubHandleUnsubscription(source, messageObj) {
        log.info("hub on unsubscription");
        // get a non-ambiguous "this"
        var self = this;
        var error = validateProperties(
            messageObj,
            "unsubscription message from transport layer",
            ['type', 'pattern', 'transactionID'],
            []
        );
        if (error) { self._disconnectClient(source, error); return null; }
        // FIXME - pattern should be a regex
        var subscriber = self._subscribers[source._id];
        var numPatterns = 0;
        if (subscriber && _.contains(subscriber.patterns, messageObj.pattern)) {
            subscriber.patterns = _.without(subscriber.patterns, messageObj.pattern);
            if (subscriber.patterns.length === 0) {
                delete self._subscribers[source._id];
                log.debug("number of unique subscribers: ", _.keys(self._subscribers).length);
            } else {
                numPatterns = subscriber.patterns.length;
            }
        }
        // notify source that unsubscription occurred
        source.send({
            type: 'unsubscribed',
            pattern: messageObj.pattern,
            number: numPatterns,
            transactionID: messageObj.transactionID,
        }, function onError(error) {
            if (error) { self._disconnectClient(source, error); }
        });
        // allow chaining
        return this;
    };
    // unsubscribe a dead client
    Hub.prototype._unsubscribeFromAll = function hubUnsubscribeFromAll(source) {
        log.info("hub _unsubscribeFromAll", source);
        if (_.contains(_.keys(this._subscribers)), source._id) {
            delete this._subscribers[source._id];
            this.emit('status', "client disconnected", source._id);
        }
        // allow chaining
        return this;
    };
    // handle messages from clients
    Hub.prototype._handleMessage = function hubHandleMessage(source, messageObj) {
        log.info("hub handle message", messageObj);
        // parse the message type and respond accordingly
        if (!messageObj.type) {
            var noTypeError = new VError("Message from transport layer has no type (%j)", messageObj);
            this._disconnectClient(source, noTypeError);
        } else if (messageObj.type == "publication") {
            this._handlePublication(source, messageObj);
        } else if (messageObj.type == "subscription") {
            this._handleSubscription(source, messageObj);
        } else if (messageObj.type == "unsubscription") {
            this._handleUnsubscription(source, messageObj);
        } else {
            var badTypeError = new VError("Unrecognized message type from transport layer: %s. (%j)", messageObj.type, messageObj);
            this._disconnectClient(source, badTypeError);
        }
        // allow chaining
        return this;
    };
    // distribute a message to subscribers
    Hub.prototype._distribute = function hubDistribute(message, channel, cb) {
        // distribute a message on a channel to subscribers
        // get a non-ambiguous "this"
        var self = this;
        // new message object for distribution to clients
        var newMessageObj = {
            type: 'distribution',
            'message': message,
            'channel': channel,
        };
        // send to each subscriber
        var numPublished = 0;
        var match;
        var matchPattern = function matchPattern(pattern) {
            // closure for match.
            // returns true/false for match test, and also sets
            // the matching pattern
            match = pattern;
            return channel.match(pattern);
        };
        async.eachSeries(_.keys(self._subscribers), function distribute(subscriberId, eachCB) {
            // error response
            var subscriber = self._subscribers[subscriberId];
            if (_.any(subscriber.patterns, matchPattern)) {
                newMessageObj.match = match;
                subscriber.connection.send(newMessageObj, function sendError(error) {
                    log.debug('hub sent to client (%j)', newMessageObj);
                    // close the client conn on error.
                    if (error) {
                        self._disconnectClient(subscriber.connection, error, eachCB);
                    } else {
                        numPublished++;
                        eachCB();
                    }
                    return null;
                });
            } else {
                eachCB();
            }
            return null;
        }, function eachFinal() {
            // errors here would come from disconnectClient, which calls
            // the cb when the client is closed.
            // Client.close does not report an error on close.
            callback(cb)(numPublished);
            return null;
        });
        return this;
    };
    // [ -Public API- ]
    // close a transport object
    Hub.prototype.close = function hubClose(cb) {
        log.info("hub close");
        if (this._closed) {
            throw new VError("Hub has already been closed");
        }
        // add cb to listeners
        if (cb) {
            this.on('close', cb);
        }
        this._transport.close();
        // it doesn't make sense to do anything with the object after this,
        // so return null
        return null;
    };
    // listen for connections
    Hub.prototype.listen = function hubListen(options, cb) {
        log.info("hub listen");
        // non-ambiguous self
        var self = this;
        // FIXME - deal with options better - ask for url/http explicitly?
        // only allow this to be called once on the object
        if (self._transport) {
            // throw immediately - this is programmer error
            throw new VError("'listen' has already been called on this hub.");
        }
        // add cb to listeners
        if (cb) {
            self.on('listening', cb);
        }
        // set transport
        self._transport = new ActualTransportServer();
        // proxy events
        self._transport.on('listening', self.emit.bind(self, 'listening'));
        self._transport.on('close', self.emit.bind(self, 'close'));
        // handle client actions
        self._transport.on('client closed', self._unsubscribeFromAll.bind(self));
        self._transport.on('message', self._handleMessage.bind(self));
        // handle transport actions
        self._transport.on('error', function handleTransportError() {
            // FIXME need a test for this
            // FIXME need some notice - either a propagated error event or a reason for the close
            self.close();
        });
        // listen
        self._transport.listen(options);
        // it doesn't make sense to do anything with the object until listen
        // calls back, so return null
        return null;
    };
    // return a new Hub
    return Hub;
}
527204
def create_key(self, master_secret=b""):
        
        master_secret = deserialize.bytes_str(master_secret)
        bip32node = control.create_wallet(self.testnet,
                                          master_secret=master_secret)
        return bip32node.wif()
378213
function init(shard, socket) {  // {{{2
/**
 * Sends request to the master shard to establish a link.
 *
 * @param shard {Object} Slave shard
 * @param ws {Object} WebSocket
 *
 * @method constructor
 */

  if (shard.slaves) {
    if (socket._lid in shard.slaves) {
      return L.error(socket, O.log.todo('Duplicit lid', shard, socket._lid));
    }
  } else {
    shard.slaves = {};
  }

  this.shard = shard;
  shard.slaves[socket._lid] = this;

  return L.open(this, socket, {
    home: shard.isAtHome() || shard.masterState === shard.MASTER_STATE.HOME,
    homeTime: Date.now() + shard.homeTimeOffset,
  });
}
721101
def connect_or_create(self, overwrite=False):
        
        connection = self._get_connection()
        if connection:
            return connection
        else:
            return self.create(overwrite=overwrite)
749979
async def create_tunnel_connection(self, req):
        
        tunnel_address = req.tunnel_address
        connection = await self.create_connection(tunnel_address)
        response = connection.current_consumer()
        for event in response.events().values():
            event.clear()
        response.start(HttpTunnel(self, req))
        await response.event('post_request').waiter()
        if response.status_code != 200:
            raise ConnectionRefusedError(
                'Cannot connect to tunnel: status code %s'
                % response.status_code
            )
        raw_sock = connection.transport.get_extra_info('socket')
        if raw_sock is None:
            raise RuntimeError('Transport without socket')
        # duplicate socket so we can close transport
        raw_sock = raw_sock.dup()
        connection.transport.close()
        await connection.event('connection_lost').waiter()
        self.sessions -= 1
        self.requests_processed -= 1
        #
        connection = await self.create_connection(
            sock=raw_sock, ssl=req.ssl(self), server_hostname=req.netloc
        )
        return connection
1007253
def create(cls, name, value):
        
        sshkey_params = {
            'name': name,
            'value': value,
        }

        result = cls.call('hosting.ssh.create', sshkey_params)
        return result
1289564
function Server(universes, port) {
  if (this instanceof Server === false) {
    return new Server(port);
  }
  EventEmitter.call(this);

  if (universes !== undefined && !Array.isArray(universes)) {
    universes = [universes];
  }
  this.universes = universes || [0x01];
  this.port = port || e131.DEFAULT_PORT;
  this._socket = dgram.createSocket('udp4');
  this._lastSequenceNumber = {};

  var self = this;
  this.universes.forEach(function (universe) {
    self._lastSequenceNumber[universe] = 0;
  });
  this._socket.on('error', function onError(err) {
    self.emit('error', err);
  });
  this._socket.on('listening', function onListening() {
    self.emit('listening');
  });
  this._socket.on('close', function onClose() {
    self.emit('close');
  });
  this._socket.on('message', function onMessage(msg) {
    var packet = new e131.Packet(msg);
    var validation = packet.validate();
    if (validation !== packet.ERR_NONE) {
      self.emit('packet-error', packet, validation);
      return;
    }
    if (packet.discard(self._lastSequenceNumber[packet.getUniverse()])) {
      self.emit('packet-out-of-order', packet);
    } else {
      self.emit('packet', packet);
    }
    self._lastSequenceNumber[packet.getUniverse()] = packet.getSequenceNumber();
  });
  this._socket.bind(this.port, function onListening() {
    self.universes.forEach(function (universe) {
      var multicastGroup = e131.getMulticastGroup(universe);
      self._socket.addMembership(multicastGroup);
    });
  });
}
458600
function initModule(forge) {

forge.cipher = forge.cipher || {};

// supported cipher modes
var modes = forge.cipher.modes = forge.cipher.modes || {};


/** Electronic codebook (ECB) (Don't use this; it's not secure) **/

modes.ecb = function(options) {
  options = options || {};
  this.name = 'ECB';
  this.cipher = options.cipher;
  this.blockSize = options.blockSize || 16;
  this._ints = this.blockSize / 4;
  this._inBlock = new Array(this._ints);
  this._outBlock = new Array(this._ints);
};

modes.ecb.prototype.start = function(options) {};

modes.ecb.prototype.encrypt = function(input, output, finish) {
  // not enough input to encrypt
  if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
    return true;
  }

  // get next block
  for(var i = 0; i < this._ints; ++i) {
    this._inBlock[i] = input.getInt32();
  }

  // encrypt block
  this.cipher.encrypt(this._inBlock, this._outBlock);

  // write output
  for(var i = 0; i < this._ints; ++i) {
    output.putInt32(this._outBlock[i]);
  }
};

modes.ecb.prototype.decrypt = function(input, output, finish) {
  // not enough input to decrypt
  if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
    return true;
  }

  // get next block
  for(var i = 0; i < this._ints; ++i) {
    this._inBlock[i] = input.getInt32();
  }

  // decrypt block
  this.cipher.decrypt(this._inBlock, this._outBlock);

  // write output
  for(var i = 0; i < this._ints; ++i) {
    output.putInt32(this._outBlock[i]);
  }
};

modes.ecb.prototype.pad = function(input, options) {
  // add PKCS#7 padding to block (each pad byte is the
  // value of the number of pad bytes)
  var padding = (input.length() === this.blockSize ?
    this.blockSize : (this.blockSize - input.length()));
  input.fillWithByte(padding, padding);
  return true;
};

modes.ecb.prototype.unpad = function(output, options) {
  // check for error: input data not a multiple of blockSize
  if(options.overflow > 0) {
    return false;
  }

  // ensure padding byte count is valid
  var len = output.length();
  var count = output.at(len - 1);
  if(count > (this.blockSize << 2)) {
    return false;
  }

  // trim off padding bytes
  output.truncate(count);
  return true;
};


/** Cipher-block Chaining (CBC) **/

modes.cbc = function(options) {
  options = options || {};
  this.name = 'CBC';
  this.cipher = options.cipher;
  this.blockSize = options.blockSize || 16;
  this._ints = this.blockSize / 4;
  this._inBlock = new Array(this._ints);
  this._outBlock = new Array(this._ints);
};

modes.cbc.prototype.start = function(options) {
  // Note: legacy support for using IV residue (has security flaws)
  // if IV is null, reuse block from previous processing
  if(options.iv === null) {
    // must have a previous block
    if(!this._prev) {
      throw new Error('Invalid IV parameter.');
    }
    this._iv = this._prev.slice(0);
  } else if(!('iv' in options)) {
    throw new Error('Invalid IV parameter.');
  } else {
    // save IV as "previous" block
    this._iv = transformIV(options.iv);
    this._prev = this._iv.slice(0);
  }
};

modes.cbc.prototype.encrypt = function(input, output, finish) {
  // not enough input to encrypt
  if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
    return true;
  }

  // get next block
  // CBC XOR's IV (or previous block) with plaintext
  for(var i = 0; i < this._ints; ++i) {
    this._inBlock[i] = this._prev[i] ^ input.getInt32();
  }

  // encrypt block
  this.cipher.encrypt(this._inBlock, this._outBlock);

  // write output, save previous block
  for(var i = 0; i < this._ints; ++i) {
    output.putInt32(this._outBlock[i]);
  }
  this._prev = this._outBlock;
};

modes.cbc.prototype.decrypt = function(input, output, finish) {
  // not enough input to decrypt
  if(input.length() < this.blockSize && !(finish && input.length() > 0)) {
    return true;
  }

  // get next block
  for(var i = 0; i < this._ints; ++i) {
    this._inBlock[i] = input.getInt32();
  }

  // decrypt block
  this.cipher.decrypt(this._inBlock, this._outBlock);

  // write output, save previous ciphered block
  // CBC XOR's IV (or previous block) with ciphertext
  for(var i = 0; i < this._ints; ++i) {
    output.putInt32(this._prev[i] ^ this._outBlock[i]);
  }
  this._prev = this._inBlock.slice(0);
};

modes.cbc.prototype.pad = function(input, options) {
  // add PKCS#7 padding to block (each pad byte is the
  // value of the number of pad bytes)
  var padding = (input.length() === this.blockSize ?
    this.blockSize : (this.blockSize - input.length()));
  input.fillWithByte(padding, padding);
  return true;
};

modes.cbc.prototype.unpad = function(output, options) {
  // check for error: input data not a multiple of blockSize
  if(options.overflow > 0) {
    return false;
  }

  // ensure padding byte count is valid
  var len = output.length();
  var count = output.at(len - 1);
  if(count > (this.blockSize << 2)) {
    return false;
  }

  // trim off padding bytes
  output.truncate(count);
  return true;
};


/** Cipher feedback (CFB) **/

modes.cfb = function(options) {
  options = options || {};
  this.name = 'CFB';
  this.cipher = options.cipher;
  this.blockSize = options.blockSize || 16;
  this._ints = this.blockSize / 4;
  this._inBlock = null;
  this._outBlock = new Array(this._ints);
  this._partialBlock = new Array(this._ints);
  this._partialOutput = forge.util.createBuffer();
  this._partialBytes = 0;
};

modes.cfb.prototype.start = function(options) {
  if(!('iv' in options)) {
    throw new Error('Invalid IV parameter.');
  }
  // use IV as first input
  this._iv = transformIV(options.iv);
  this._inBlock = this._iv.slice(0);
  this._partialBytes = 0;
};

modes.cfb.prototype.encrypt = function(input, output, finish) {
  // not enough input to encrypt
  var inputLength = input.length();
  if(inputLength === 0) {
    return true;
  }

  // encrypt block
  this.cipher.encrypt(this._inBlock, this._outBlock);

  // handle full block
  if(this._partialBytes === 0 && inputLength >= this.blockSize) {
    // XOR input with output, write input as output
    for(var i = 0; i < this._ints; ++i) {
      this._inBlock[i] = input.getInt32() ^ this._outBlock[i];
      output.putInt32(this._inBlock[i]);
    }
    return;
  }

  // handle partial block
  var partialBytes = (this.blockSize - inputLength) % this.blockSize;
  if(partialBytes > 0) {
    partialBytes = this.blockSize - partialBytes;
  }

  // XOR input with output, write input as partial output
  this._partialOutput.clear();
  for(var i = 0; i < this._ints; ++i) {
    this._partialBlock[i] = input.getInt32() ^ this._outBlock[i];
    this._partialOutput.putInt32(this._partialBlock[i]);
  }

  if(partialBytes > 0) {
    // block still incomplete, restore input buffer
    input.read -= this.blockSize;
  } else {
    // block complete, update input block
    for(var i = 0; i < this._ints; ++i) {
      this._inBlock[i] = this._partialBlock[i];
    }
  }

  // skip any previous partial bytes
  if(this._partialBytes > 0) {
    this._partialOutput.getBytes(this._partialBytes);
  }

  if(partialBytes > 0 && !finish) {
    output.putBytes(this._partialOutput.getBytes(
      partialBytes - this._partialBytes));
    this._partialBytes = partialBytes;
    return true;
  }

  output.putBytes(this._partialOutput.getBytes(
    inputLength - this._partialBytes));
  this._partialBytes = 0;
};

modes.cfb.prototype.decrypt = function(input, output, finish) {
  // not enough input to decrypt
  var inputLength = input.length();
  if(inputLength === 0) {
    return true;
  }

  // encrypt block (CFB always uses encryption mode)
  this.cipher.encrypt(this._inBlock, this._outBlock);

  // handle full block
  if(this._partialBytes === 0 && inputLength >= this.blockSize) {
    // XOR input with output, write input as output
    for(var i = 0; i < this._ints; ++i) {
      this._inBlock[i] = input.getInt32();
      output.putInt32(this._inBlock[i] ^ this._outBlock[i]);
    }
    return;
  }

  // handle partial block
  var partialBytes = (this.blockSize - inputLength) % this.blockSize;
  if(partialBytes > 0) {
    partialBytes = this.blockSize - partialBytes;
  }

  // XOR input with output, write input as partial output
  this._partialOutput.clear();
  for(var i = 0; i < this._ints; ++i) {
    this._partialBlock[i] = input.getInt32();
    this._partialOutput.putInt32(this._partialBlock[i] ^ this._outBlock[i]);
  }

  if(partialBytes > 0) {
    // block still incomplete, restore input buffer
    input.read -= this.blockSize;
  } else {
    // block complete, update input block
    for(var i = 0; i < this._ints; ++i) {
      this._inBlock[i] = this._partialBlock[i];
    }
  }

  // skip any previous partial bytes
  if(this._partialBytes > 0) {
    this._partialOutput.getBytes(this._partialBytes);
  }

  if(partialBytes > 0 && !finish) {
    output.putBytes(this._partialOutput.getBytes(
      partialBytes - this._partialBytes));
    this._partialBytes = partialBytes;
    return true;
  }

  output.putBytes(this._partialOutput.getBytes(
    inputLength - this._partialBytes));
  this._partialBytes = 0;
};

/** Output feedback (OFB) **/

modes.ofb = function(options) {
  options = options || {};
  this.name = 'OFB';
  this.cipher = options.cipher;
  this.blockSize = options.blockSize || 16;
  this._ints = this.blockSize / 4;
  this._inBlock = null;
  this._outBlock = new Array(this._ints);
  this._partialOutput = forge.util.createBuffer();
  this._partialBytes = 0;
};

modes.ofb.prototype.start = function(options) {
  if(!('iv' in options)) {
    throw new Error('Invalid IV parameter.');
  }
  // use IV as first input
  this._iv = transformIV(options.iv);
  this._inBlock = this._iv.slice(0);
  this._partialBytes = 0;
};

modes.ofb.prototype.encrypt = function(input, output, finish) {
  // not enough input to encrypt
  var inputLength = input.length();
  if(input.length() === 0) {
    return true;
  }

  // encrypt block (OFB always uses encryption mode)
  this.cipher.encrypt(this._inBlock, this._outBlock);

  // handle full block
  if(this._partialBytes === 0 && inputLength >= this.blockSize) {
    // XOR input with output and update next input
    for(var i = 0; i < this._ints; ++i) {
      output.putInt32(input.getInt32() ^ this._outBlock[i]);
      this._inBlock[i] = this._outBlock[i];
    }
    return;
  }

  // handle partial block
  var partialBytes = (this.blockSize - inputLength) % this.blockSize;
  if(partialBytes > 0) {
    partialBytes = this.blockSize - partialBytes;
  }

  // XOR input with output
  this._partialOutput.clear();
  for(var i = 0; i < this._ints; ++i) {
    this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
  }

  if(partialBytes > 0) {
    // block still incomplete, restore input buffer
    input.read -= this.blockSize;
  } else {
    // block complete, update input block
    for(var i = 0; i < this._ints; ++i) {
      this._inBlock[i] = this._outBlock[i];
    }
  }

  // skip any previous partial bytes
  if(this._partialBytes > 0) {
    this._partialOutput.getBytes(this._partialBytes);
  }

  if(partialBytes > 0 && !finish) {
    output.putBytes(this._partialOutput.getBytes(
      partialBytes - this._partialBytes));
    this._partialBytes = partialBytes;
    return true;
  }

  output.putBytes(this._partialOutput.getBytes(
    inputLength - this._partialBytes));
  this._partialBytes = 0;
};

modes.ofb.prototype.decrypt = modes.ofb.prototype.encrypt;


/** Counter (CTR) **/

modes.ctr = function(options) {
  options = options || {};
  this.name = 'CTR';
  this.cipher = options.cipher;
  this.blockSize = options.blockSize || 16;
  this._ints = this.blockSize / 4;
  this._inBlock = null;
  this._outBlock = new Array(this._ints);
  this._partialOutput = forge.util.createBuffer();
  this._partialBytes = 0;
};

modes.ctr.prototype.start = function(options) {
  if(!('iv' in options)) {
    throw new Error('Invalid IV parameter.');
  }
  // use IV as first input
  this._iv = transformIV(options.iv);
  this._inBlock = this._iv.slice(0);
  this._partialBytes = 0;
};

modes.ctr.prototype.encrypt = function(input, output, finish) {
  // not enough input to encrypt
  var inputLength = input.length();
  if(inputLength === 0) {
    return true;
  }

  // encrypt block (CTR always uses encryption mode)
  this.cipher.encrypt(this._inBlock, this._outBlock);

  // handle full block
  if(this._partialBytes === 0 && inputLength >= this.blockSize) {
    // XOR input with output
    for(var i = 0; i < this._ints; ++i) {
      output.putInt32(input.getInt32() ^ this._outBlock[i]);
    }
  } else {
    // handle partial block
    var partialBytes = (this.blockSize - inputLength) % this.blockSize;
    if(partialBytes > 0) {
      partialBytes = this.blockSize - partialBytes;
    }

    // XOR input with output
    this._partialOutput.clear();
    for(var i = 0; i < this._ints; ++i) {
      this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
    }

    if(partialBytes > 0) {
      // block still incomplete, restore input buffer
      input.read -= this.blockSize;
    }

    // skip any previous partial bytes
    if(this._partialBytes > 0) {
      this._partialOutput.getBytes(this._partialBytes);
    }

    if(partialBytes > 0 && !finish) {
      output.putBytes(this._partialOutput.getBytes(
        partialBytes - this._partialBytes));
      this._partialBytes = partialBytes;
      return true;
    }

    output.putBytes(this._partialOutput.getBytes(
      inputLength - this._partialBytes));
    this._partialBytes = 0;
  }

  // block complete, increment counter (input block)
  inc32(this._inBlock);
};

modes.ctr.prototype.decrypt = modes.ctr.prototype.encrypt;


/** Galois/Counter Mode (GCM) **/

modes.gcm = function(options) {
  options = options || {};
  this.name = 'GCM';
  this.cipher = options.cipher;
  this.blockSize = options.blockSize || 16;
  this._ints = this.blockSize / 4;
  this._inBlock = new Array(this._ints);
  this._outBlock = new Array(this._ints);
  this._partialOutput = forge.util.createBuffer();
  this._partialBytes = 0;

  // R is actually this value concatenated with 120 more zero bits, but
  // we only XOR against R so the other zeros have no effect -- we just
  // apply this value to the first integer in a block
  this._R = 0xE1000000;
};

modes.gcm.prototype.start = function(options) {
  if(!('iv' in options)) {
    throw new Error('Invalid IV parameter.');
  }
  // ensure IV is a byte buffer
  var iv = forge.util.createBuffer(options.iv);

  // no ciphered data processed yet
  this._cipherLength = 0;

  // default additional data is none
  var additionalData;
  if('additionalData' in options) {
    additionalData = forge.util.createBuffer(options.additionalData);
  } else {
    additionalData = forge.util.createBuffer();
  }

  // default tag length is 128 bits
  if('tagLength' in options) {
    this._tagLength = options.tagLength;
  } else {
    this._tagLength = 128;
  }

  // if tag is given, ensure tag matches tag length
  this._tag = null;
  if(options.decrypt) {
    // save tag to check later
    this._tag = forge.util.createBuffer(options.tag).getBytes();
    if(this._tag.length !== (this._tagLength / 8)) {
      throw new Error('Authentication tag does not match tag length.');
    }
  }

  // create tmp storage for hash calculation
  this._hashBlock = new Array(this._ints);

  // no tag generated yet
  this.tag = null;

  // generate hash subkey
  // (apply block cipher to "zero" block)
  this._hashSubkey = new Array(this._ints);
  this.cipher.encrypt([0, 0, 0, 0], this._hashSubkey);

  // generate table M
  // use 4-bit tables (32 component decomposition of a 16 byte value)
  // 8-bit tables take more space and are known to have security
  // vulnerabilities (in native implementations)
  this.componentBits = 4;
  this._m = this.generateHashTable(this._hashSubkey, this.componentBits);

  // Note: support IV length different from 96 bits? (only supporting
  // 96 bits is recommended by NIST SP-800-38D)
  // generate J_0
  var ivLength = iv.length();
  if(ivLength === 12) {
    // 96-bit IV
    this._j0 = [iv.getInt32(), iv.getInt32(), iv.getInt32(), 1];
  } else {
    // IV is NOT 96-bits
    this._j0 = [0, 0, 0, 0];
    while(iv.length() > 0) {
      this._j0 = this.ghash(
        this._hashSubkey, this._j0,
        [iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()]);
    }
    this._j0 = this.ghash(
      this._hashSubkey, this._j0, [0, 0].concat(from64To32(ivLength * 8)));
  }

  // generate ICB (initial counter block)
  this._inBlock = this._j0.slice(0);
  inc32(this._inBlock);
  this._partialBytes = 0;

  // consume authentication data
  additionalData = forge.util.createBuffer(additionalData);
  // save additional data length as a BE 64-bit number
  this._aDataLength = from64To32(additionalData.length() * 8);
  // pad additional data to 128 bit (16 byte) block size
  var overflow = additionalData.length() % this.blockSize;
  if(overflow) {
    additionalData.fillWithByte(0, this.blockSize - overflow);
  }
  this._s = [0, 0, 0, 0];
  while(additionalData.length() > 0) {
    this._s = this.ghash(this._hashSubkey, this._s, [
      additionalData.getInt32(),
      additionalData.getInt32(),
      additionalData.getInt32(),
      additionalData.getInt32()
    ]);
  }
};

modes.gcm.prototype.encrypt = function(input, output, finish) {
  // not enough input to encrypt
  var inputLength = input.length();
  if(inputLength === 0) {
    return true;
  }

  // encrypt block
  this.cipher.encrypt(this._inBlock, this._outBlock);

  // handle full block
  if(this._partialBytes === 0 && inputLength >= this.blockSize) {
    // XOR input with output
    for(var i = 0; i < this._ints; ++i) {
      output.putInt32(this._outBlock[i] ^= input.getInt32());
    }
    this._cipherLength += this.blockSize;
  } else {
    // handle partial block
    var partialBytes = (this.blockSize - inputLength) % this.blockSize;
    if(partialBytes > 0) {
      partialBytes = this.blockSize - partialBytes;
    }

    // XOR input with output
    this._partialOutput.clear();
    for(var i = 0; i < this._ints; ++i) {
      this._partialOutput.putInt32(input.getInt32() ^ this._outBlock[i]);
    }

    if(partialBytes === 0 || finish) {
      // handle overflow prior to hashing
      if(finish) {
        // get block overflow
        var overflow = inputLength % this.blockSize;
        this._cipherLength += overflow;
        // truncate for hash function
        this._partialOutput.truncate(this.blockSize - overflow);
      } else {
        this._cipherLength += this.blockSize;
      }

      // get output block for hashing
      for(var i = 0; i < this._ints; ++i) {
        this._outBlock[i] = this._partialOutput.getInt32();
      }
      this._partialOutput.read -= this.blockSize;
    }

    // skip any previous partial bytes
    if(this._partialBytes > 0) {
      this._partialOutput.getBytes(this._partialBytes);
    }

    if(partialBytes > 0 && !finish) {
      // block still incomplete, restore input buffer, get partial output,
      // and return early
      input.read -= this.blockSize;
      output.putBytes(this._partialOutput.getBytes(
        partialBytes - this._partialBytes));
      this._partialBytes = partialBytes;
      return true;
    }

    output.putBytes(this._partialOutput.getBytes(
      inputLength - this._partialBytes));
    this._partialBytes = 0;
  }

  // update hash block S
  this._s = this.ghash(this._hashSubkey, this._s, this._outBlock);

  // increment counter (input block)
  inc32(this._inBlock);
};

modes.gcm.prototype.decrypt = function(input, output, finish) {
  // not enough input to decrypt
  var inputLength = input.length();
  if(inputLength < this.blockSize && !(finish && inputLength > 0)) {
    return true;
  }

  // encrypt block (GCM always uses encryption mode)
  this.cipher.encrypt(this._inBlock, this._outBlock);

  // increment counter (input block)
  inc32(this._inBlock);

  // update hash block S
  this._hashBlock[0] = input.getInt32();
  this._hashBlock[1] = input.getInt32();
  this._hashBlock[2] = input.getInt32();
  this._hashBlock[3] = input.getInt32();
  this._s = this.ghash(this._hashSubkey, this._s, this._hashBlock);

  // XOR hash input with output
  for(var i = 0; i < this._ints; ++i) {
    output.putInt32(this._outBlock[i] ^ this._hashBlock[i]);
  }

  // increment cipher data length
  if(inputLength < this.blockSize) {
    this._cipherLength += inputLength % this.blockSize;
  } else {
    this._cipherLength += this.blockSize;
  }
};

modes.gcm.prototype.afterFinish = function(output, options) {
  var rval = true;

  // handle overflow
  if(options.decrypt && options.overflow) {
    output.truncate(this.blockSize - options.overflow);
  }

  // handle authentication tag
  this.tag = forge.util.createBuffer();

  // concatenate additional data length with cipher length
  var lengths = this._aDataLength.concat(from64To32(this._cipherLength * 8));

  // include lengths in hash
  this._s = this.ghash(this._hashSubkey, this._s, lengths);

  // do GCTR(J_0, S)
  var tag = [];
  this.cipher.encrypt(this._j0, tag);
  for(var i = 0; i < this._ints; ++i) {
    this.tag.putInt32(this._s[i] ^ tag[i]);
  }

  // trim tag to length
  this.tag.truncate(this.tag.length() % (this._tagLength / 8));

  // check authentication tag
  if(options.decrypt && this.tag.bytes() !== this._tag) {
    rval = false;
  }

  return rval;
};

/**
 * See NIST SP-800-38D 6.3 (Algorithm 1). This function performs Galois
 * field multiplication. The field, GF(2^128), is defined by the polynomial:
 *
 * x^128 + x^7 + x^2 + x + 1
 *
 * Which is represented in little-endian binary form as: 11100001 (0xe1). When
 * the value of a coefficient is 1, a bit is set. The value R, is the
 * concatenation of this value and 120 zero bits, yielding a 128-bit value
 * which matches the block size.
 *
 * This function will multiply two elements (vectors of bytes), X and Y, in
 * the field GF(2^128). The result is initialized to zero. For each bit of
 * X (out of 128), x_i, if x_i is set, then the result is multiplied (XOR'd)
 * by the current value of Y. For each bit, the value of Y will be raised by
 * a power of x (multiplied by the polynomial x). This can be achieved by
 * shifting Y once to the right. If the current value of Y, prior to being
 * multiplied by x, has 0 as its LSB, then it is a 127th degree polynomial.
 * Otherwise, we must divide by R after shifting to find the remainder.
 *
 * @param x the first block to multiply by the second.
 * @param y the second block to multiply by the first.
 *
 * @return the block result of the multiplication.
 */
modes.gcm.prototype.multiply = function(x, y) {
  var z_i = [0, 0, 0, 0];
  var v_i = y.slice(0);

  // calculate Z_128 (block has 128 bits)
  for(var i = 0; i < 128; ++i) {
    // if x_i is 0, Z_{i+1} = Z_i (unchanged)
    // else Z_{i+1} = Z_i ^ V_i
    // get x_i by finding 32-bit int position, then left shift 1 by remainder
    var x_i = x[(i / 32) | 0] & (1 << (31 - i % 32));
    if(x_i) {
      z_i[0] ^= v_i[0];
      z_i[1] ^= v_i[1];
      z_i[2] ^= v_i[2];
      z_i[3] ^= v_i[3];
    }

    // if LSB(V_i) is 1, V_i = V_i >> 1
    // else V_i = (V_i >> 1) ^ R
    this.pow(v_i, v_i);
  }

  return z_i;
};

modes.gcm.prototype.pow = function(x, out) {
  // if LSB(x) is 1, x = x >>> 1
  // else x = (x >>> 1) ^ R
  var lsb = x[3] & 1;

  // always do x >>> 1:
  // starting with the rightmost integer, shift each integer to the right
  // one bit, pulling in the bit from the integer to the left as its top
  // most bit (do this for the last 3 integers)
  for(var i = 3; i > 0; --i) {
    out[i] = (x[i] >>> 1) | ((x[i - 1] & 1) << 31);
  }
  // shift the first integer normally
  out[0] = x[0] >>> 1;

  // if lsb was not set, then polynomial had a degree of 127 and doesn't
  // need to divided; otherwise, XOR with R to find the remainder; we only
  // need to XOR the first integer since R technically ends w/120 zero bits
  if(lsb) {
    out[0] ^= this._R;
  }
};

modes.gcm.prototype.tableMultiply = function(x) {
  // assumes 4-bit tables are used
  var z = [0, 0, 0, 0];
  for(var i = 0; i < 32; ++i) {
    var idx = (i / 8) | 0;
    var x_i = (x[idx] >>> ((7 - (i % 8)) * 4)) & 0xF;
    var ah = this._m[i][x_i];
    z[0] ^= ah[0];
    z[1] ^= ah[1];
    z[2] ^= ah[2];
    z[3] ^= ah[3];
  }
  return z;
};

/**
 * A continuing version of the GHASH algorithm that operates on a single
 * block. The hash block, last hash value (Ym) and the new block to hash
 * are given.
 *
 * @param h the hash block.
 * @param y the previous value for Ym, use [0, 0, 0, 0] for a new hash.
 * @param x the block to hash.
 *
 * @return the hashed value (Ym).
 */
modes.gcm.prototype.ghash = function(h, y, x) {
  y[0] ^= x[0];
  y[1] ^= x[1];
  y[2] ^= x[2];
  y[3] ^= x[3];
  return this.tableMultiply(y);
  //return this.multiply(y, h);
};

/**
 * Precomputes a table for multiplying against the hash subkey. This
 * mechanism provides a substantial speed increase over multiplication
 * performed without a table. The table-based multiplication this table is
 * for solves X * H by multiplying each component of X by H and then
 * composing the results together using XOR.
 *
 * This function can be used to generate tables with different bit sizes
 * for the components, however, this implementation assumes there are
 * 32 components of X (which is a 16 byte vector), therefore each component
 * takes 4-bits (so the table is constructed with bits=4).
 *
 * @param h the hash subkey.
 * @param bits the bit size for a component.
 */
modes.gcm.prototype.generateHashTable = function(h, bits) {
  // TODO: There are further optimizations that would use only the
  // first table M_0 (or some variant) along with a remainder table;
  // this can be explored in the future
  var multiplier = 8 / bits;
  var perInt = 4 * multiplier;
  var size = 16 * multiplier;
  var m = new Array(size);
  for(var i = 0; i < size; ++i) {
    var tmp = [0, 0, 0, 0];
    var idx = (i / perInt) | 0;
    var shft = ((perInt - 1 - (i % perInt)) * bits);
    tmp[idx] = (1 << (bits - 1)) << shft;
    m[i] = this.generateSubHashTable(this.multiply(tmp, h), bits);
  }
  return m;
};

/**
 * Generates a table for multiplying against the hash subkey for one
 * particular component (out of all possible component values).
 *
 * @param mid the pre-multiplied value for the middle key of the table.
 * @param bits the bit size for a component.
 */
modes.gcm.prototype.generateSubHashTable = function(mid, bits) {
  // compute the table quickly by minimizing the number of
  // POW operations -- they only need to be performed for powers of 2,
  // all other entries can be composed from those powers using XOR
  var size = 1 << bits;
  var half = size >>> 1;
  var m = new Array(size);
  m[half] = mid.slice(0);
  var i = half >>> 1;
  while(i > 0) {
    // raise m0[2 * i] and store in m0[i]
    this.pow(m[2 * i], m[i] = []);
    i >>= 1;
  }
  i = 2;
  while(i < half) {
    for(var j = 1; j < i; ++j) {
      var m_i = m[i];
      var m_j = m[j];
      m[i + j] = [
        m_i[0] ^ m_j[0],
        m_i[1] ^ m_j[1],
        m_i[2] ^ m_j[2],
        m_i[3] ^ m_j[3]
      ];
    }
    i *= 2;
  }
  m[0] = [0, 0, 0, 0];
  /* Note: We could avoid storing these by doing composition during multiply
  calculate top half using composition by speed is preferred. */
  for(i = half + 1; i < size; ++i) {
    var c = m[i ^ half];
    m[i] = [mid[0] ^ c[0], mid[1] ^ c[1], mid[2] ^ c[2], mid[3] ^ c[3]];
  }
  return m;
};


/** Utility functions */

function transformIV(iv) {
  if(typeof iv === 'string') {
    // convert iv string into byte buffer
    iv = forge.util.createBuffer(iv);
  }

  if(forge.util.isArray(iv) && iv.length > 4) {
    // convert iv byte array into byte buffer
    var tmp = iv;
    iv = forge.util.createBuffer();
    for(var i = 0; i < tmp.length; ++i) {
      iv.putByte(tmp[i]);
    }
  }
  if(!forge.util.isArray(iv)) {
    // convert iv byte buffer into 32-bit integer array
    iv = [iv.getInt32(), iv.getInt32(), iv.getInt32(), iv.getInt32()];
  }

  return iv;
}

function inc32(block) {
  // increment last 32 bits of block only
  block[block.length - 1] = (block[block.length - 1] + 1) & 0xFFFFFFFF;
}

function from64To32(num) {
  // convert 64-bit number to two BE Int32s
  return [(num / 0x100000000) | 0, num & 0xFFFFFFFF];
}


}
17911
function init(space, socket) {  // {{{2
/**
 * Sends request to the master space to establish a link.
 *
 * @param space {Object} Slave space
 * @param ws {Object} WebSocket
 *
 * @method constructor
 */

  if (space.slaves) {
    if (socket._lid in space.slaves) {
      O.link.error(socket, O.log.todo('Duplicit lid', space, socket._lid));
      return;
    }
  } else {
    space.slaves = {};
  }

  this.space = space;
  space.slaves[socket._lid] = this;

  O.link.open(this, socket, {home: space.isAtHome() || space.masterState === space.MASTER_STATE.HOME})
  return;
}
688091
function (options, callback) {
    let me = this
    let tunnel
    let sshcfg = {
      host: this.host + ':' + (options.sshport || 22),
      user: options.username,
      remoteport: this.port
    }

    if (options.password) {
      sshcfg.password = options.password
    }

    if (options.key) {
      sshcfg.key = options.key
    }

    // Dynamically determine port by availability or via option.
    // Then open the tunnel.
    if (options.port) {
      sshcfg.port = options.port
      tunnel = new NGN.Tunnel(sshcfg)
      tunnel.on('ready', function () {
        NGN.BUS.emit('sshtunnel.create', tunnel)
        callback && callback(me.host, options.port)
      })
      tunnel.connect()
    } else {
      // Create a quick TCP server on random port to secure the port,
      // then shut it down and use the newly freed port.
      let tmp = net.createServer().listen(0, '127.0.0.1', function () {
        sshcfg.port = this.address().port
        tmp.close()
      })

      tmp.on('close', function () {
        // Launch the tunnel
        tunnel = new NGN.Tunnel(sshcfg)
        tunnel.on('ready', function () {
          callback && callback('127.0.0.1', sshcfg.port)
        })
        tunnel.connect()
      })
    }
  }
1108036
def _create_socket(self):
        
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s = ssl.wrap_socket(s)
        s.connect((self.host, self.__port))
        s.settimeout(self.timeout)
        return s
1302852
def create_email(self):
        
        self.connect()
        if self.send_as_one:
            self.construct_message()
            self.send()
        elif self.send_as_one is False:
            for email in self.addresses:
                self.construct_message(email)
                self.send(email)
        self.disconnect()
31559
def create(self):
        """"""
        pk = CRTPPacket()
        pk.set_header(5, CHAN_SETTINGS)
        if self.useV2:
            pk.data = (CMD_CREATE_BLOCK_V2, self.id)
        else:
            pk.data = (CMD_CREATE_BLOCK, self.id)
        for var in self.variables:
            if (var.is_toc_variable() is False):  # Memory location
                logger.debug('Logging to raw memory %d, 0x%04X',
                             var.get_storage_and_fetch_byte(), var.address)
                pk.data.append(struct.pack('<B',
                                           var.get_storage_and_fetch_byte()))
                pk.data.append(struct.pack('<I', var.address))
            else:  # Item in TOC
                logger.debug('Adding %s with id=%d and type=0x%02X',
                             var.name,
                             self.cf.log.toc.get_element_id(
                                 var.name), var.get_storage_and_fetch_byte())
                pk.data.append(var.get_storage_and_fetch_byte())
                if self.useV2:
                    ident = self.cf.log.toc.get_element_id(var.name)
                    pk.data.append(ident & 0x0ff)
                    pk.data.append((ident >> 8) & 0x0ff)
                else:
                    pk.data.append(self.cf.log.toc.get_element_id(var.name))
        logger.debug('Adding log block id {}'.format(self.id))
        if self.useV2:
            self.cf.send_packet(pk, expected_reply=(
                CMD_CREATE_BLOCK_V2, self.id))
        else:
            self.cf.send_packet(pk, expected_reply=(CMD_CREATE_BLOCK, self.id))
464643
def createphysicalport(create_processor = partial(default_processor, excluding=('vhost', 'systemid',
                                                                                       'bridge', 'name',
                                                                                       'physicalnetwork')),
                       reorder_dict = default_iterate_dict):
    
    def walker(walk, write, timestamp, parameters_dict):
        for key, parameters in reorder_dict(parameters_dict):
            try:
                value = walk(key)
            except KeyError:
                pass
            else:
                p = create_new(PhysicalPort, value, parameters['vhost'], parameters['systemid'],
                                                    parameters['bridge'], parameters['name'])
                try:
                    physicalnetwork = walk(PhysicalNetwork.default_key(parameters['physicalnetwork']))
                except KeyError:
                    pass
                else:
                    # Should already been check from outside
                    p.physicalnetwork = physicalnetwork.create_reference()
                    try:
                        phymap = walk(PhysicalNetworkMap._network.leftkey(physicalnetwork))
                    except KeyError:
                        pass
                    else:
                        create_processor(p, physicalnetwork, phymap, walk, write, parameters=parameters)
                        phymap.ports.dataset().add(p.create_weakreference())
                        write(phymap.getkey(), phymap)
                try:
                    phyportset = walk(PhysicalPortSet.default_key())
                except KeyError:
                    pass
                else:
                    phyportset.set.dataset().add(p.create_weakreference())
                    write(phyportset.getkey(), phyportset)
                write(p.getkey(), p)
    return walker
509853
function initModule(forge) {

forge.kem = forge.kem || {};

var BigInteger = forge.jsbn.BigInteger;

/**
 * The API for the RSA Key Encapsulation Mechanism (RSA-KEM) from ISO 18033-2.
 */
forge.kem.rsa = {};

/**
 * Creates an RSA KEM API object for generating a secret asymmetric key.
 *
 * The symmetric key may be generated via a call to 'encrypt', which will
 * produce a ciphertext to be transmitted to the recipient and a key to be
 * kept secret. The ciphertext is a parameter to be passed to 'decrypt' which
 * will produce the same secret key for the recipient to use to decrypt a
 * message that was encrypted with the secret key.
 *
 * @param kdf the KDF API to use (eg: new forge.kem.kdf1()).
 * @param options the options to use.
 *          [prng] a custom crypto-secure pseudo-random number generator to use,
 *            that must define "getBytesSync".
 */
forge.kem.rsa.create = function(kdf, options) {
  options = options || {};
  var prng = options.prng || forge.random;

  var kem = {};

  /**
   * Generates a secret key and its encapsulation.
   *
   * @param publicKey the RSA public key to encrypt with.
   * @param keyLength the length, in bytes, of the secret key to generate.
   *
   * @return an object with:
   *   encapsulation: the ciphertext for generating the secret key, as a
   *     binary-encoded string of bytes.
   *   key: the secret key to use for encrypting a message.
   */
  kem.encrypt = function(publicKey, keyLength) {
    // generate a random r where 1 > r > n
    var byteLength = Math.ceil(publicKey.n.bitLength() / 8);
    var r;
    do {
      r = new BigInteger(
        forge.util.bytesToHex(prng.getBytesSync(byteLength)),
        16).mod(publicKey.n);
    } while(r.equals(BigInteger.ZERO));

    // prepend r with zeros
    r = forge.util.hexToBytes(r.toString(16));
    var zeros = byteLength - r.length;
    if(zeros > 0) {
      r = forge.util.fillString(String.fromCharCode(0), zeros) + r;
    }

    // encrypt the random
    var encapsulation = publicKey.encrypt(r, 'NONE');

    // generate the secret key
    var key = kdf.generate(r, keyLength);

    return {encapsulation: encapsulation, key: key};
  };

  /**
   * Decrypts an encapsulated secret key.
   *
   * @param privateKey the RSA private key to decrypt with.
   * @param encapsulation the ciphertext for generating the secret key, as
   *          a binary-encoded string of bytes.
   * @param keyLength the length, in bytes, of the secret key to generate.
   *
   * @return the secret key as a binary-encoded string of bytes.
   */
  kem.decrypt = function(privateKey, encapsulation, keyLength) {
    // decrypt the encapsulation and generate the secret key
    var r = privateKey.decrypt(encapsulation, 'NONE');
    return kdf.generate(r, keyLength);
  };

  return kem;
};

// TODO: add forge.kem.kdf.create('KDF1', {md: ..., ...}) API?

/**
 * Creates a key derivation API object that implements KDF1 per ISO 18033-2.
 *
 * @param md the hash API to use.
 * @param [digestLength] an optional digest length that must be positive and
 *          less than or equal to md.digestLength.
 *
 * @return a KDF1 API object.
 */
forge.kem.kdf1 = function(md, digestLength) {
  _createKDF(this, md, 0, digestLength || md.digestLength);
};

/**
 * Creates a key derivation API object that implements KDF2 per ISO 18033-2.
 *
 * @param md the hash API to use.
 * @param [digestLength] an optional digest length that must be positive and
 *          less than or equal to md.digestLength.
 *
 * @return a KDF2 API object.
 */
forge.kem.kdf2 = function(md, digestLength) {
  _createKDF(this, md, 1, digestLength || md.digestLength);
};

/**
 * Creates a KDF1 or KDF2 API object.
 *
 * @param md the hash API to use.
 * @param counterStart the starting index for the counter.
 * @param digestLength the digest length to use.
 *
 * @return the KDF API object.
 */
function _createKDF(kdf, md, counterStart, digestLength) {
  /**
   * Generate a key of the specified length.
   *
   * @param x the binary-encoded byte string to generate a key from.
   * @param length the number of bytes to generate (the size of the key).
   *
   * @return the key as a binary-encoded string.
   */
  kdf.generate = function(x, length) {
    var key = new forge.util.ByteBuffer();

    // run counter from counterStart to ceil(length / Hash.len)
    var k = Math.ceil(length / digestLength) + counterStart;

    var c = new forge.util.ByteBuffer();
    for(var i = counterStart; i < k; ++i) {
      // I2OSP(i, 4): convert counter to an octet string of 4 octets
      c.putInt32(i);

      // digest 'x' and the counter and add the result to the key
      md.start();
      md.update(x + c.getBytes());
      var hash = md.digest();
      key.putBytes(hash.getBytes(digestLength));
    }

    // truncate to the correct key length
    key.truncate(key.length() - length);
    return key.getBytes();
  };
}

}