replaced uses of pycryptopp's ed25519 with our own

This commit is contained in:
heartsucker 2019-05-16 16:21:12 +02:00 committed by meejah
parent 74b1a0c279
commit 3a5a0fb572
5 changed files with 81 additions and 46 deletions

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)