CLI: add 'tahoe admin generate-keypair' command
This commit is contained in:
parent
99d5a8d8b9
commit
6607fdc586
|
@ -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,
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue