added offloaded key generation

this adds a new service to pre-generate RSA key pairs.  This allows
the expensive (i.e. slow) key generation to be placed into a process
outside the node, so that the node's reactor will not block when it
needs a key pair, but instead can retrieve them from a pool of already
generated key pairs in the key-generator service.

it adds a tahoe create-key-generator command which initialises an 
empty dir with a tahoe-key-generator.tac file which can then be run
via twistd.  it stashes its .pem and portnum for furl stability and
writes the furl of the key gen service to key_generator.furl, also
printing it to stdout.

by placing a key_generator.furl file into the nodes config directory
(e.g. ~/.tahoe) a node will attempt to connect to such a service, and
will use that when creating mutable files (i.e. directories) whenever
possible.  if the keygen service is unavailable, it will perform the
key generation locally instead, as before.
This commit is contained in:
robk-tahoe
2008-04-01 18:45:13 -07:00
parent d6c66f99c0
commit 5578559b85
9 changed files with 211 additions and 15 deletions

View File

@ -8,6 +8,7 @@ from twisted.internet import reactor
from twisted.application.internet import TimerService
from foolscap import Referenceable
from foolscap.logging import log
from pycryptopp.publickey import rsa
import allmydata
from allmydata.storage import StorageServer
@ -72,6 +73,10 @@ class Client(node.Node, testutil.PollMixin):
if run_helper:
self.init_helper()
self.init_client()
self._key_generator = None
key_gen_furl = self.get_config('key_generator.furl')
if key_gen_furl:
self.init_key_gen(key_gen_furl)
# ControlServer and Helper are attached after Tub startup
hotline_file = os.path.join(self.basedir,
@ -196,6 +201,20 @@ class Client(node.Node, testutil.PollMixin):
d.addCallback(_publish)
d.addErrback(log.err, facility="tahoe.init", level=log.BAD)
def init_key_gen(self, key_gen_furl):
d = self.when_tub_ready()
def _subscribe(self):
self.tub.connectTo(key_gen_furl, self._got_key_generator)
d.addCallback(_subscribe)
d.addErrback(log.err, facility="tahoe.init", level=log.BAD)
def _got_key_generator(self, key_generator):
self._key_generator = key_generator
key_generator.notifyOnDisconnect(self._lost_key_generator)
def _lost_key_generator(self):
self._key_generator = None
def init_web(self, webport):
self.log("init_web(webport=%s)", args=(webport,))
@ -281,16 +300,31 @@ class Client(node.Node, testutil.PollMixin):
def create_empty_dirnode(self):
n = NewDirectoryNode(self)
d = n.create()
d = n.create(self._generate_pubprivkeys)
d.addCallback(lambda res: n)
return d
def create_mutable_file(self, contents=""):
n = MutableFileNode(self)
d = n.create(contents)
d = n.create(contents, self._generate_pubprivkeys)
d.addCallback(lambda res: n)
return d
def _generate_pubprivkeys(self, key_size):
if self._key_generator:
d = self._key_generator.callRemote('get_rsa_key_pair', key_size)
def make_key_objs((verifying_key, signing_key)):
v = rsa.create_verifying_key_from_string(verifying_key)
s = rsa.create_signing_key_from_string(signing_key)
return v, s
d.addCallback(make_key_objs)
return d
else:
# RSA key generation for a 2048 bit key takes between 0.8 and 3.2 secs
signer = rsa.generate(key_size)
verifier = signer.get_verifying_key()
return verifier, signer
def upload(self, uploadable):
uploader = self.getServiceNamed("uploader")
return uploader.upload(uploadable)