--- /dev/null
+
+from twisted.python import usage
+
+class GenerateKeypairOptions(usage.Options):
+ def getSynopsis(self):
+ return "Usage: tahoe admin generate-keypair"
+
+ def getUsage(self, width=None):
+ t = usage.Options.getUsage(self, width)
+ t += """
+Generate an ECDSA192 public/private keypair, dumped to stdout as two lines of
+base32-encoded text.
+
+"""
+ return t
+
+def generate_keypair(options):
+ from pycryptopp.publickey import ecdsa
+ from allmydata.util import base32
+ out = options.stdout
+ privkey = ecdsa.generate(192)
+ print >>out, "private: priv-v0-%s" % base32.b2a(privkey.serialize())
+ pubkey = privkey.get_verifying_key()
+ print >>out, "public: pub-v0-%s" % base32.b2a(pubkey.serialize())
+
+class AdminCommand(usage.Options):
+ subCommands = [
+ ["generate-keypair", None, GenerateKeypairOptions,
+ "Generate a public/private keypair, write to stdout."],
+ ]
+ def postOptions(self):
+ if not hasattr(self, 'subOptions'):
+ raise usage.UsageError("must specify a subcommand")
+ def getSynopsis(self):
+ return "Usage: tahoe admin SUBCOMMAND"
+ def getUsage(self, width=None):
+ #t = usage.Options.getUsage(self, width)
+ t = """
+Subcommands:
+ tahoe admin generate-keypair Generate a public/private keypair,
+ write to stdout.
+
+Please run e.g. 'tahoe admin generate-keypair --help' for more details on
+each subcommand.
+"""
+ return t
+
+subDispatch = {
+ "generate-keypair": generate_keypair,
+ }
+
+def do_admin(options):
+ so = options.subOptions
+ so.stdout = options.stdout
+ so.stderr = options.stderr
+ f = subDispatch[options.subCommand]
+ return f(so)
+
+
+subCommands = [
+ ["admin", None, AdminCommand, "admin subcommands: use 'tahoe admin' for a list"],
+ ]
+
+dispatch = {
+ "admin": do_admin,
+ }
from twisted.python import usage
from allmydata.scripts.common import BaseOptions
-import debug, create_node, startstop_node, cli, keygen
+import debug, create_node, startstop_node, cli, keygen, admin
_general_commands = ( create_node.subCommands
+ keygen.subCommands
+ debug.subCommands
+ cli.subCommands
+ + admin.subCommands
)
class Options(BaseOptions, usage.Options):
rc = startstop_node.dispatch[command](so, stdout, stderr)
elif command in debug.dispatch:
rc = debug.dispatch[command](so)
+ elif command in admin.dispatch:
+ rc = admin.dispatch[command](so)
elif command in cli.dispatch:
rc = cli.dispatch[command](so)
elif command in keygen.dispatch:
from cStringIO import StringIO
import urllib
-from allmydata.util import fileutil, hashutil
+from pycryptopp.publickey import ecdsa
+from allmydata.util import fileutil, hashutil, base32
from allmydata import uri
# at least import the CLI scripts, even if we don't have any real tests for
d.addCallback(lambda (out,err): self.failUnlessEqual(out, DATA2))
return d
+class Admin(unittest.TestCase):
+ def do_cli(self, *args, **kwargs):
+ argv = list(args)
+ stdin = kwargs.get("stdin", "")
+ stdout, stderr = StringIO(), StringIO()
+ d = threads.deferToThread(runner.runner, argv, run_by_human=False,
+ stdin=StringIO(stdin),
+ stdout=stdout, stderr=stderr)
+ def _done(res):
+ return stdout.getvalue(), stderr.getvalue()
+ d.addCallback(_done)
+ return d
+ def test_generate_keypair(self):
+ d = self.do_cli("admin", "generate-keypair")
+ def _done( (stdout, stderr) ):
+ lines = stdout.split("\n")
+ privkey_line = lines[0].strip()
+ pubkey_line = lines[1].strip()
+ sk_header = "private: priv-v0-"
+ vk_header = "public: pub-v0-"
+ self.failUnless(privkey_line.startswith(sk_header), privkey_line)
+ self.failUnless(pubkey_line.startswith(vk_header), pubkey_line)
+ privkey_b = base32.a2b(privkey_line[len(sk_header):])
+ pubkey_b = base32.a2b(pubkey_line[len(vk_header):])
+ sk = ecdsa.create_signing_key_from_string(privkey_b)
+ vk = ecdsa.create_verifying_key_from_string(pubkey_b)
+ self.failUnlessEqual(sk.get_verifying_key().serialize(),
+ vk.serialize())
+ d.addCallback(_done)
+ return d