mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-01-20 11:38:52 +00:00
replaced uses of pycryptopp's ed25519 with our own
This commit is contained in:
parent
74b1a0c279
commit
3a5a0fb572
@ -489,7 +489,7 @@ class _Client(node.Node, pollmixin.PollMixin):
|
||||
|
||||
def get_long_nodeid(self):
|
||||
# this matches what IServer.get_longname() says about us elsewhere
|
||||
vk_bytes = self._node_key.get_verifying_key_bytes()
|
||||
vk_bytes = self._node_key.public_key().public_bytes()
|
||||
return "v0-"+base32.b2a(vk_bytes)
|
||||
|
||||
def get_long_tubid(self):
|
||||
@ -511,7 +511,7 @@ class _Client(node.Node, pollmixin.PollMixin):
|
||||
else:
|
||||
# otherwise, we're free to use the more natural seed of our
|
||||
# pubkey-based serverid
|
||||
vk_bytes = self._node_key.get_verifying_key_bytes()
|
||||
vk_bytes = self._node_key.public_key().public_bytes()
|
||||
seed = base32.b2a(vk_bytes)
|
||||
self.config.write_config_file("permutation-seed", seed+"\n")
|
||||
return seed.strip()
|
||||
|
@ -1,9 +1,48 @@
|
||||
'''
|
||||
Ed25519 keys and helpers.
|
||||
|
||||
Key Formatting
|
||||
--------------
|
||||
|
||||
- in base32, keys are 52 chars long (both signing and verifying keys)
|
||||
- in base62, keys is 43 chars long
|
||||
- in base64, keys is 43 chars long
|
||||
|
||||
We can't use base64 because we want to reserve punctuation and preserve
|
||||
cut-and-pasteability. The base62 encoding is shorter than the base32 form,
|
||||
but the minor usability improvement is not worth the documentation and
|
||||
specification confusion of using a non-standard encoding. So we stick with
|
||||
base32.
|
||||
'''
|
||||
|
||||
import six
|
||||
|
||||
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
|
||||
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption, \
|
||||
PublicFormat
|
||||
|
||||
# When we were still using `pycryptopp`, BadSignatureError was the name of the exception, and now
|
||||
# that we've switched to `cryptography`, we are importing and "re-exporting" this to keep the name
|
||||
# the same (for now).
|
||||
from cryptography.exceptions import InvalidSignature
|
||||
BadSignatureError = InvalidSignature
|
||||
del InvalidSignature
|
||||
|
||||
from allmydata.util.base32 import a2b, b2a
|
||||
|
||||
_PRIV_PREFIX = 'priv-v0-'
|
||||
_PUB_PREFIX = 'pub-v0-'
|
||||
|
||||
|
||||
class BadPrefixError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _remove_prefix(s_bytes, prefix):
|
||||
if not s_bytes.startswith(prefix):
|
||||
raise BadPrefixError("did not see expected '%s' prefix" % (prefix,))
|
||||
return s_bytes[len(prefix):]
|
||||
|
||||
|
||||
class SigningKey:
|
||||
|
||||
@ -37,6 +76,24 @@ class SigningKey:
|
||||
raise ValueError('data must be bytes')
|
||||
return self._priv_key.sign(data)
|
||||
|
||||
@classmethod
|
||||
def parse_encoded_key(cls, priv_str):
|
||||
global _PRIV_PREFIX
|
||||
return cls.from_private_bytes(a2b(_remove_prefix(priv_str, _PRIV_PREFIX)))
|
||||
|
||||
def encoded_key(self):
|
||||
global _PRIV_PREFIX
|
||||
return _PRIV_PREFIX + a2b(self.private_bytes())
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, type(self)):
|
||||
return self.private_bytes() == other.private_bytes()
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
|
||||
class VerifyingKey:
|
||||
|
||||
@ -62,3 +119,21 @@ class VerifyingKey:
|
||||
raise ValueError('data must be bytes')
|
||||
|
||||
self._pub_key.verify(signature, data)
|
||||
|
||||
@classmethod
|
||||
def parse_encoded_key(cls, pub_str):
|
||||
global _PUB_PREFIX
|
||||
return cls.from_public_bytes(a2b(_remove_prefix(pub_str, _PUB_PREFIX)))
|
||||
|
||||
def encoded_key(self):
|
||||
global _PUB_PREFIX
|
||||
return _PUB_PREFIX + a2b(self.public_bytes())
|
||||
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, type(self)):
|
||||
return self.public_bytes() == other.public_bytes()
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
@ -19,7 +19,7 @@ def sign_to_foolscap(ann, sk):
|
||||
# pubkey:v0-b64(pubkey)}) .
|
||||
msg = json.dumps(ann).encode("utf-8")
|
||||
sig = "v0-"+base32.b2a(sk.sign(msg))
|
||||
vk_bytes = sk.get_verifying_key_bytes()
|
||||
vk_bytes = sk.public_key().public_bytes()
|
||||
ann_t = (msg, sig, "v0-"+base32.b2a(vk_bytes))
|
||||
return ann_t
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
import os.path
|
||||
from six.moves import cStringIO as StringIO
|
||||
import urllib, sys
|
||||
@ -11,6 +10,7 @@ from twisted.internet import task
|
||||
from twisted.python.filepath import FilePath
|
||||
|
||||
import allmydata
|
||||
from allmydata.crypto import ed25519
|
||||
from allmydata.util import fileutil, hashutil, base32, keyutil
|
||||
from allmydata.util.namespace import Namespace
|
||||
from allmydata import uri
|
||||
@ -18,7 +18,6 @@ from allmydata.immutable import upload
|
||||
from allmydata.dirnode import normalize
|
||||
from allmydata.scripts.common_http import socket_error
|
||||
import allmydata.scripts.common_http
|
||||
from pycryptopp.publickey import ed25519
|
||||
|
||||
# Test that the scripts can be imported.
|
||||
from allmydata.scripts import create_node, debug, tahoe_start, tahoe_restart, \
|
||||
@ -735,9 +734,9 @@ class Admin(unittest.TestCase):
|
||||
self.failUnless(privkey_bits[1].startswith("priv-v0-"), lines[0])
|
||||
self.failUnless(pubkey_bits[1].startswith("pub-v0-"), lines[1])
|
||||
sk_bytes = base32.a2b(keyutil.remove_prefix(privkey_bits[1], "priv-v0-"))
|
||||
sk = ed25519.SigningKey(sk_bytes)
|
||||
sk = ed25519.SigningKey.from_private_bytes(sk_bytes)
|
||||
vk_bytes = base32.a2b(keyutil.remove_prefix(pubkey_bits[1], "pub-v0-"))
|
||||
self.failUnlessEqual(sk.get_verifying_key_bytes(), vk_bytes)
|
||||
self.failUnlessEqual(sk.public_key().public_bytes(), vk_bytes)
|
||||
d.addCallback(_done)
|
||||
return d
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
import os
|
||||
from pycryptopp.publickey import ed25519
|
||||
from allmydata.util.base32 import a2b, b2a
|
||||
|
||||
BadSignatureError = ed25519.BadSignatureError
|
||||
|
||||
class BadPrefixError(Exception):
|
||||
pass
|
||||
|
||||
def remove_prefix(s_bytes, prefix):
|
||||
if not s_bytes.startswith(prefix):
|
||||
raise BadPrefixError("did not see expected '%s' prefix" % (prefix,))
|
||||
return s_bytes[len(prefix):]
|
||||
|
||||
# in base32, keys are 52 chars long (both signing and verifying keys)
|
||||
# in base62, keys is 43 chars long
|
||||
# in base64, keys is 43 chars long
|
||||
#
|
||||
# We can't use base64 because we want to reserve punctuation and preserve
|
||||
# cut-and-pasteability. The base62 encoding is shorter than the base32 form,
|
||||
# but the minor usability improvement is not worth the documentation and
|
||||
# specification confusion of using a non-standard encoding. So we stick with
|
||||
# base32.
|
||||
|
||||
def make_keypair():
|
||||
sk_bytes = os.urandom(32)
|
||||
sk = ed25519.SigningKey(sk_bytes)
|
||||
vk_bytes = sk.get_verifying_key_bytes()
|
||||
return ("priv-v0-"+b2a(sk_bytes), "pub-v0-"+b2a(vk_bytes))
|
||||
|
||||
def parse_privkey(privkey_vs):
|
||||
sk_bytes = a2b(remove_prefix(privkey_vs, "priv-v0-"))
|
||||
sk = ed25519.SigningKey(sk_bytes)
|
||||
vk_bytes = sk.get_verifying_key_bytes()
|
||||
return (sk, "pub-v0-"+b2a(vk_bytes))
|
||||
|
||||
def parse_pubkey(pubkey_vs):
|
||||
vk_bytes = a2b(remove_prefix(pubkey_vs, "pub-v0-"))
|
||||
return ed25519.VerifyingKey(vk_bytes)
|
Loading…
Reference in New Issue
Block a user