CLI: add 'tahoe admin generate-keypair' command

This commit is contained in:
Brian Warner 2008-09-18 17:11:33 -07:00
parent 99d5a8d8b9
commit 6607fdc586
3 changed files with 102 additions and 2 deletions

View File

@ -0,0 +1,66 @@
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,
}

View File

@ -4,12 +4,13 @@ from cStringIO import StringIO
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):
@ -69,6 +70,8 @@ def runner(argv,
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:

View File

@ -4,7 +4,8 @@ from twisted.trial import unittest
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
@ -500,5 +501,35 @@ class Put(SystemTestMixin, CLITestMixin, unittest.TestCase):
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