Merge pull request #240 from ralexstokes/allow-multiple-identity-types
Allow multiple peer identity types (via different cryptosystems)
This commit is contained in:
commit
9977933fd1
1
Makefile
1
Makefile
|
@ -11,4 +11,5 @@ lintroll:
|
|||
flake8 $(FILES_TO_LINT)
|
||||
|
||||
protobufs:
|
||||
cd libp2p/crypto/pb && protoc --python_out=. crypto.proto
|
||||
cd libp2p/pubsub/pb && protoc --python_out=. rpc.proto
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import asyncio
|
||||
from typing import Mapping, Sequence
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
from libp2p.crypto.rsa import create_new_key_pair
|
||||
from libp2p.host.basic_host import BasicHost
|
||||
from libp2p.kademlia.network import KademliaServer
|
||||
from libp2p.kademlia.storage import IStorage
|
||||
|
@ -34,9 +33,10 @@ async def cleanup_done_tasks() -> None:
|
|||
await asyncio.sleep(3)
|
||||
|
||||
|
||||
def generate_id() -> ID:
|
||||
new_key = RSA.generate(2048, e=65537).publickey().export_key("DER")
|
||||
new_id = ID.from_pubkey(new_key)
|
||||
def generate_peer_id_from_rsa_identity() -> ID:
|
||||
new_key_pair = create_new_key_pair()
|
||||
new_public_key = new_key_pair.public_key
|
||||
new_id = ID.from_pubkey(new_public_key)
|
||||
return new_id
|
||||
|
||||
|
||||
|
@ -53,7 +53,7 @@ def initialize_default_kademlia_router(
|
|||
:return: return a default kademlia instance
|
||||
"""
|
||||
if not id_opt:
|
||||
id_opt = generate_id()
|
||||
id_opt = generate_peer_id_from_rsa_identity()
|
||||
|
||||
node_id = id_opt.to_bytes()
|
||||
# ignore type for Kademlia module
|
||||
|
@ -83,7 +83,7 @@ def initialize_default_swarm(
|
|||
"""
|
||||
|
||||
if not id_opt:
|
||||
id_opt = generate_id()
|
||||
id_opt = generate_peer_id_from_rsa_identity()
|
||||
|
||||
# TODO parse transport_opt to determine transport
|
||||
transport_opt = transport_opt or ["/ip4/127.0.0.1/tcp/8001"]
|
||||
|
@ -124,7 +124,7 @@ async def new_node(
|
|||
"""
|
||||
|
||||
if not id_opt:
|
||||
id_opt = generate_id()
|
||||
id_opt = generate_peer_id_from_rsa_identity()
|
||||
|
||||
if not swarm_opt:
|
||||
swarm_opt = initialize_default_swarm(
|
||||
|
|
0
libp2p/crypto/__init__.py
Normal file
0
libp2p/crypto/__init__.py
Normal file
82
libp2p/crypto/keys.py
Normal file
82
libp2p/crypto/keys.py
Normal file
|
@ -0,0 +1,82 @@
|
|||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, unique
|
||||
|
||||
from .pb import crypto_pb2 as protobuf
|
||||
|
||||
|
||||
@unique
|
||||
class KeyType(Enum):
|
||||
RSA = 0
|
||||
Ed25519 = 1
|
||||
Secp256k1 = 2
|
||||
ECDSA = 3
|
||||
|
||||
|
||||
class Key:
|
||||
"""
|
||||
A ``Key`` represents a cryptographic key.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def to_bytes(self) -> bytes:
|
||||
"""
|
||||
Returns the byte representation of this key.
|
||||
"""
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def get_type(self) -> KeyType:
|
||||
"""
|
||||
Returns the ``KeyType`` for ``self``.
|
||||
"""
|
||||
...
|
||||
|
||||
|
||||
class PublicKey(ABC, Key):
|
||||
"""
|
||||
A ``PublicKey`` represents a cryptographic public key.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def verify(self, data: bytes, signature: bytes) -> bool:
|
||||
"""
|
||||
Verify that ``signature`` is the cryptographic signature of the hash of ``data``.
|
||||
"""
|
||||
...
|
||||
|
||||
def serialize_to_protobuf(self) -> protobuf.PublicKey:
|
||||
_type = self.get_type()
|
||||
data = self.to_bytes()
|
||||
protobuf_key = protobuf.PublicKey()
|
||||
protobuf_key.key_type = _type.value
|
||||
protobuf_key.data = data
|
||||
return protobuf_key
|
||||
|
||||
|
||||
class PrivateKey(ABC, Key):
|
||||
"""
|
||||
A ``PrivateKey`` represents a cryptographic private key.
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
def sign(self, data: bytes) -> bytes:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def get_public_key(self) -> PublicKey:
|
||||
...
|
||||
|
||||
def serialize_to_protobuf(self) -> protobuf.PrivateKey:
|
||||
_type = self.get_type()
|
||||
data = self.to_bytes()
|
||||
protobuf_key = protobuf.PrivateKey()
|
||||
protobuf_key.key_type = _type.value
|
||||
protobuf_key.data = data
|
||||
return protobuf_key
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class KeyPair:
|
||||
private_key: PrivateKey
|
||||
public_key: PublicKey
|
20
libp2p/crypto/pb/crypto.proto
Normal file
20
libp2p/crypto/pb/crypto.proto
Normal file
|
@ -0,0 +1,20 @@
|
|||
syntax = "proto2";
|
||||
|
||||
package crypto.pb;
|
||||
|
||||
enum KeyType {
|
||||
RSA = 0;
|
||||
Ed25519 = 1;
|
||||
Secp256k1 = 2;
|
||||
ECDSA = 3;
|
||||
}
|
||||
|
||||
message PublicKey {
|
||||
required KeyType key_type = 1;
|
||||
required bytes data = 2;
|
||||
}
|
||||
|
||||
message PrivateKey {
|
||||
required KeyType key_type = 1;
|
||||
required bytes data = 2;
|
||||
}
|
162
libp2p/crypto/pb/crypto_pb2.py
Normal file
162
libp2p/crypto/pb/crypto_pb2.py
Normal file
|
@ -0,0 +1,162 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: crypto.proto
|
||||
|
||||
import sys
|
||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
|
||||
from google.protobuf.internal import enum_type_wrapper
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='crypto.proto',
|
||||
package='crypto.pb',
|
||||
syntax='proto2',
|
||||
serialized_options=None,
|
||||
serialized_pb=_b('\n\x0c\x63rypto.proto\x12\tcrypto.pb\"?\n\tPublicKey\x12$\n\x08key_type\x18\x01 \x02(\x0e\x32\x12.crypto.pb.KeyType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c\"@\n\nPrivateKey\x12$\n\x08key_type\x18\x01 \x02(\x0e\x32\x12.crypto.pb.KeyType\x12\x0c\n\x04\x64\x61ta\x18\x02 \x02(\x0c*9\n\x07KeyType\x12\x07\n\x03RSA\x10\x00\x12\x0b\n\x07\x45\x64\x32\x35\x35\x31\x39\x10\x01\x12\r\n\tSecp256k1\x10\x02\x12\t\n\x05\x45\x43\x44SA\x10\x03')
|
||||
)
|
||||
|
||||
_KEYTYPE = _descriptor.EnumDescriptor(
|
||||
name='KeyType',
|
||||
full_name='crypto.pb.KeyType',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
values=[
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='RSA', index=0, number=0,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='Ed25519', index=1, number=1,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='Secp256k1', index=2, number=2,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='ECDSA', index=3, number=3,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
],
|
||||
containing_type=None,
|
||||
serialized_options=None,
|
||||
serialized_start=158,
|
||||
serialized_end=215,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_KEYTYPE)
|
||||
|
||||
KeyType = enum_type_wrapper.EnumTypeWrapper(_KEYTYPE)
|
||||
RSA = 0
|
||||
Ed25519 = 1
|
||||
Secp256k1 = 2
|
||||
ECDSA = 3
|
||||
|
||||
|
||||
|
||||
_PUBLICKEY = _descriptor.Descriptor(
|
||||
name='PublicKey',
|
||||
full_name='crypto.pb.PublicKey',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='key_type', full_name='crypto.pb.PublicKey.key_type', index=0,
|
||||
number=1, type=14, cpp_type=8, label=2,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='data', full_name='crypto.pb.PublicKey.data', index=1,
|
||||
number=2, type=12, cpp_type=9, label=2,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto2',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=27,
|
||||
serialized_end=90,
|
||||
)
|
||||
|
||||
|
||||
_PRIVATEKEY = _descriptor.Descriptor(
|
||||
name='PrivateKey',
|
||||
full_name='crypto.pb.PrivateKey',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='key_type', full_name='crypto.pb.PrivateKey.key_type', index=0,
|
||||
number=1, type=14, cpp_type=8, label=2,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='data', full_name='crypto.pb.PrivateKey.data', index=1,
|
||||
number=2, type=12, cpp_type=9, label=2,
|
||||
has_default_value=False, default_value=_b(""),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto2',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=92,
|
||||
serialized_end=156,
|
||||
)
|
||||
|
||||
_PUBLICKEY.fields_by_name['key_type'].enum_type = _KEYTYPE
|
||||
_PRIVATEKEY.fields_by_name['key_type'].enum_type = _KEYTYPE
|
||||
DESCRIPTOR.message_types_by_name['PublicKey'] = _PUBLICKEY
|
||||
DESCRIPTOR.message_types_by_name['PrivateKey'] = _PRIVATEKEY
|
||||
DESCRIPTOR.enum_types_by_name['KeyType'] = _KEYTYPE
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
PublicKey = _reflection.GeneratedProtocolMessageType('PublicKey', (_message.Message,), dict(
|
||||
DESCRIPTOR = _PUBLICKEY,
|
||||
__module__ = 'crypto_pb2'
|
||||
# @@protoc_insertion_point(class_scope:crypto.pb.PublicKey)
|
||||
))
|
||||
_sym_db.RegisterMessage(PublicKey)
|
||||
|
||||
PrivateKey = _reflection.GeneratedProtocolMessageType('PrivateKey', (_message.Message,), dict(
|
||||
DESCRIPTOR = _PRIVATEKEY,
|
||||
__module__ = 'crypto_pb2'
|
||||
# @@protoc_insertion_point(class_scope:crypto.pb.PrivateKey)
|
||||
))
|
||||
_sym_db.RegisterMessage(PrivateKey)
|
||||
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
50
libp2p/crypto/rsa.py
Normal file
50
libp2p/crypto/rsa.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
import Crypto.PublicKey.RSA as RSA
|
||||
from Crypto.PublicKey.RSA import RsaKey
|
||||
|
||||
from libp2p.crypto.keys import KeyPair, KeyType, PrivateKey, PublicKey
|
||||
|
||||
|
||||
class RSAPublicKey(PublicKey):
|
||||
def __init__(self, impl: RsaKey) -> None:
|
||||
self.impl = impl
|
||||
|
||||
def to_bytes(self) -> bytes:
|
||||
return self.impl.export_key("DER")
|
||||
|
||||
def get_type(self) -> KeyType:
|
||||
return KeyType.RSA
|
||||
|
||||
def verify(self, data: bytes, signature: bytes) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class RSAPrivateKey(PrivateKey):
|
||||
def __init__(self, impl: RsaKey) -> None:
|
||||
self.impl = impl
|
||||
|
||||
@classmethod
|
||||
def new(cls, bits: int = 2048, e: int = 65537) -> "RSAPrivateKey":
|
||||
private_key_impl = RSA.generate(bits, e=e)
|
||||
return cls(private_key_impl)
|
||||
|
||||
def to_bytes(self) -> bytes:
|
||||
return self.impl.export_key("DER")
|
||||
|
||||
def get_type(self) -> KeyType:
|
||||
return KeyType.RSA
|
||||
|
||||
def sign(self, data: bytes) -> bytes:
|
||||
raise NotImplementedError
|
||||
|
||||
def get_public_key(self) -> PublicKey:
|
||||
return RSAPublicKey(self.impl.publickey())
|
||||
|
||||
|
||||
def create_new_key_pair(bits: int = 2048, e: int = 65537) -> KeyPair:
|
||||
"""
|
||||
Returns a new RSA keypair with the requested key size (``bits``) and the given public
|
||||
exponent ``e``. Sane defaults are provided for both values.
|
||||
"""
|
||||
private_key = RSAPrivateKey.new(bits, e)
|
||||
public_key = private_key.get_public_key()
|
||||
return KeyPair(private_key, public_key)
|
52
libp2p/crypto/secp256k1.py
Normal file
52
libp2p/crypto/secp256k1.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
import coincurve
|
||||
|
||||
from libp2p.crypto.keys import KeyPair, KeyType, PrivateKey, PublicKey
|
||||
|
||||
|
||||
class Secp256k1PublicKey(PublicKey):
|
||||
def __init__(self, impl: coincurve.PublicKey) -> None:
|
||||
self.impl = impl
|
||||
|
||||
def to_bytes(self) -> bytes:
|
||||
return self.impl.format()
|
||||
|
||||
def get_type(self) -> KeyType:
|
||||
return KeyType.Secp256k1
|
||||
|
||||
def verify(self, data: bytes, signature: bytes) -> bool:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class Secp256k1PrivateKey(PrivateKey):
|
||||
def __init__(self, impl: coincurve.PrivateKey) -> None:
|
||||
self.impl = impl
|
||||
|
||||
@classmethod
|
||||
def new(cls, secret: bytes = None) -> "Secp256k1PrivateKey":
|
||||
private_key_impl = coincurve.PrivateKey(secret)
|
||||
return cls(private_key_impl)
|
||||
|
||||
def to_bytes(self) -> bytes:
|
||||
return self.impl.secret
|
||||
|
||||
def get_type(self) -> KeyType:
|
||||
return KeyType.Secp256k1
|
||||
|
||||
def sign(self, data: bytes) -> bytes:
|
||||
raise NotImplementedError
|
||||
|
||||
def get_public_key(self) -> PublicKey:
|
||||
public_key_impl = coincurve.PublicKey.from_secret(self.impl.secret)
|
||||
return Secp256k1PublicKey(public_key_impl)
|
||||
|
||||
|
||||
def create_new_key_pair(secret: bytes = None) -> KeyPair:
|
||||
"""
|
||||
Returns a new Secp256k1 keypair derived from the provided ``secret``,
|
||||
a sequence of bytes corresponding to some integer between 0 and the group order.
|
||||
|
||||
A valid secret is created if ``None`` is passed.
|
||||
"""
|
||||
private_key = Secp256k1PrivateKey.new(secret)
|
||||
public_key = private_key.get_public_key()
|
||||
return KeyPair(private_key, public_key)
|
|
@ -4,6 +4,15 @@ from typing import Union
|
|||
import base58
|
||||
import multihash
|
||||
|
||||
from libp2p.crypto.keys import PublicKey
|
||||
|
||||
|
||||
def _serialize_public_key(key: PublicKey) -> bytes:
|
||||
"""
|
||||
Serializes ``key`` in the way expected to form valid peer ids.
|
||||
"""
|
||||
return key.serialize_to_protobuf().SerializeToString()
|
||||
|
||||
|
||||
class ID:
|
||||
|
||||
|
@ -28,10 +37,10 @@ class ID:
|
|||
self._b58_str = base58.b58encode(self._bytes).decode()
|
||||
return self._b58_str
|
||||
|
||||
def __bytes__(self) -> bytes:
|
||||
return self._bytes
|
||||
def __repr__(self) -> str:
|
||||
return "<libp2p.peer.id.ID 0x" + self._bytes.hex() + ">"
|
||||
|
||||
__repr__ = __str__ = pretty = to_string = to_base58
|
||||
__str__ = pretty = to_string = to_base58
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if isinstance(other, str):
|
||||
|
@ -53,9 +62,10 @@ class ID:
|
|||
return pid
|
||||
|
||||
@classmethod
|
||||
def from_pubkey(cls, key: bytes) -> "ID":
|
||||
def from_pubkey(cls, key: PublicKey) -> "ID":
|
||||
serialized_key = _serialize_public_key(key)
|
||||
algo = multihash.Func.sha2_256
|
||||
mh_digest = multihash.digest(key, algo)
|
||||
mh_digest = multihash.digest(serialized_key, algo)
|
||||
return cls(mh_digest.encode())
|
||||
|
||||
|
||||
|
|
1
setup.py
1
setup.py
|
@ -38,6 +38,7 @@ setuptools.setup(
|
|||
"rpcudp>=3.0.0,<4.0.0",
|
||||
"lru-dict>=1.1.6",
|
||||
"protobuf==3.9.0",
|
||||
"coincurve==12.0.0",
|
||||
],
|
||||
extras_require=extras_require,
|
||||
packages=setuptools.find_packages(exclude=["tests", "tests.*"]),
|
||||
|
|
43
tests/peer/test_interop.py
Normal file
43
tests/peer/test_interop.py
Normal file
|
@ -0,0 +1,43 @@
|
|||
import base64
|
||||
|
||||
import Crypto.PublicKey.RSA as RSA
|
||||
|
||||
from libp2p.crypto.pb import crypto_pb2 as pb
|
||||
from libp2p.crypto.rsa import RSAPrivateKey
|
||||
from libp2p.peer.id import ID
|
||||
|
||||
# ``PRIVATE_KEY_PROTOBUF_SERIALIZATION`` is a protobuf holding an RSA private key.
|
||||
PRIVATE_KEY_PROTOBUF_SERIALIZATION = """
|
||||
CAAS4AQwggJcAgEAAoGBAL7w+Wc4VhZhCdM/+Hccg5Nrf4q9NXWwJylbSrXz/unFS24wyk6pEk0zi3W
|
||||
7li+vSNVO+NtJQw9qGNAMtQKjVTP+3Vt/jfQRnQM3s6awojtjueEWuLYVt62z7mofOhCtj+VwIdZNBo
|
||||
/EkLZ0ETfcvN5LVtLYa8JkXybnOPsLvK+PAgMBAAECgYBdk09HDM7zzL657uHfzfOVrdslrTCj6p5mo
|
||||
DzvCxLkkjIzYGnlPuqfNyGjozkpSWgSUc+X+EGLLl3WqEOVdWJtbM61fewEHlRTM5JzScvwrJ39t7o6
|
||||
CCAjKA0cBWBd6UWgbN/t53RoWvh9HrA2AW5YrT0ZiAgKe9y7EMUaENVJ8QJBAPhpdmb4ZL4Fkm4OKia
|
||||
NEcjzn6mGTlZtef7K/0oRC9+2JkQnCuf6HBpaRhJoCJYg7DW8ZY+AV6xClKrgjBOfERMCQQDExhnzu2
|
||||
dsQ9k8QChBlpHO0TRbZBiQfC70oU31kM1AeLseZRmrxv9Yxzdl8D693NNWS2JbKOXl0kMHHcuGQLMVA
|
||||
kBZ7WvkmPV3aPL6jnwp2pXepntdVnaTiSxJ1dkXShZ/VSSDNZMYKY306EtHrIu3NZHtXhdyHKcggDXr
|
||||
qkBrdgErAkAlpGPojUwemOggr4FD8sLX1ot2hDJyyV7OK2FXfajWEYJyMRL1Gm9Uk1+Un53RAkJneqp
|
||||
JGAzKpyttXBTIDO51AkEA98KTiROMnnU8Y6Mgcvr68/SMIsvCYMt9/mtwSBGgl80VaTQ5Hpaktl6Xbh
|
||||
VUt5Wv0tRxlXZiViCGCD1EtrrwTw==
|
||||
""".replace(
|
||||
"\n", ""
|
||||
)
|
||||
|
||||
EXPECTED_PEER_ID = "QmRK3JgmVEGiewxWbhpXLJyjWuGuLeSTMTndA1coMHEy5o"
|
||||
|
||||
|
||||
# NOTE: this test checks that we can recreate the expected peer id given a private key
|
||||
# serialization, taken from the Go implementation of libp2p.
|
||||
def test_peer_id_interop():
|
||||
private_key_protobuf_bytes = base64.b64decode(PRIVATE_KEY_PROTOBUF_SERIALIZATION)
|
||||
private_key_protobuf = pb.PrivateKey()
|
||||
private_key_protobuf.ParseFromString(private_key_protobuf_bytes)
|
||||
|
||||
private_key_data = private_key_protobuf.data
|
||||
|
||||
private_key_impl = RSA.import_key(private_key_data)
|
||||
private_key = RSAPrivateKey(private_key_impl)
|
||||
public_key = private_key.get_public_key()
|
||||
|
||||
peer_id = ID.from_pubkey(public_key)
|
||||
assert peer_id == EXPECTED_PEER_ID
|
|
@ -1,32 +1,26 @@
|
|||
import random
|
||||
|
||||
from Crypto.PublicKey import RSA
|
||||
import base58
|
||||
import multihash
|
||||
import pytest
|
||||
|
||||
from libp2p.crypto.rsa import create_new_key_pair
|
||||
from libp2p.peer.id import ID
|
||||
|
||||
ALPHABETS = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
||||
|
||||
|
||||
def test_init():
|
||||
def test_eq_impl_for_bytes():
|
||||
random_id_string = ""
|
||||
for _ in range(10):
|
||||
random_id_string += random.SystemRandom().choice(ALPHABETS)
|
||||
random_id_string += random.choice(ALPHABETS)
|
||||
peer_id = ID(random_id_string.encode())
|
||||
assert peer_id == random_id_string.encode()
|
||||
|
||||
|
||||
def test_no_init_value():
|
||||
with pytest.raises(Exception):
|
||||
ID()
|
||||
|
||||
|
||||
def test_pretty():
|
||||
random_id_string = ""
|
||||
for _ in range(10):
|
||||
random_id_string += random.SystemRandom().choice(ALPHABETS)
|
||||
random_id_string += random.choice(ALPHABETS)
|
||||
peer_id = ID(random_id_string.encode())
|
||||
actual = peer_id.pretty()
|
||||
expected = base58.b58encode(random_id_string).decode()
|
||||
|
@ -37,7 +31,7 @@ def test_pretty():
|
|||
def test_str_less_than_10():
|
||||
random_id_string = ""
|
||||
for _ in range(5):
|
||||
random_id_string += random.SystemRandom().choice(ALPHABETS)
|
||||
random_id_string += random.choice(ALPHABETS)
|
||||
peer_id = base58.b58encode(random_id_string).decode()
|
||||
expected = peer_id
|
||||
actual = ID(random_id_string.encode()).__str__()
|
||||
|
@ -48,7 +42,7 @@ def test_str_less_than_10():
|
|||
def test_str_more_than_10():
|
||||
random_id_string = ""
|
||||
for _ in range(10):
|
||||
random_id_string += random.SystemRandom().choice(ALPHABETS)
|
||||
random_id_string += random.choice(ALPHABETS)
|
||||
peer_id = base58.b58encode(random_id_string).decode()
|
||||
expected = peer_id
|
||||
actual = ID(random_id_string.encode()).__str__()
|
||||
|
@ -59,7 +53,7 @@ def test_str_more_than_10():
|
|||
def test_eq_true():
|
||||
random_id_string = ""
|
||||
for _ in range(10):
|
||||
random_id_string += random.SystemRandom().choice(ALPHABETS)
|
||||
random_id_string += random.choice(ALPHABETS)
|
||||
peer_id = ID(random_id_string.encode())
|
||||
|
||||
assert peer_id == base58.b58encode(random_id_string).decode()
|
||||
|
@ -74,21 +68,10 @@ def test_eq_false():
|
|||
assert peer_id != other
|
||||
|
||||
|
||||
def test_hash():
|
||||
random_id_string = ""
|
||||
for _ in range(10):
|
||||
random_id_string += random.SystemRandom().choice(ALPHABETS)
|
||||
|
||||
expected = hash(random_id_string.encode())
|
||||
actual = ID(random_id_string.encode()).__hash__()
|
||||
|
||||
assert actual == expected
|
||||
|
||||
|
||||
def test_id_to_base58():
|
||||
random_id_string = ""
|
||||
for _ in range(10):
|
||||
random_id_string += random.SystemRandom().choice(ALPHABETS)
|
||||
random_id_string += random.choice(ALPHABETS)
|
||||
expected = base58.b58encode(random_id_string).decode()
|
||||
actual = ID(random_id_string.encode()).to_base58()
|
||||
|
||||
|
@ -98,7 +81,7 @@ def test_id_to_base58():
|
|||
def test_id_from_base58():
|
||||
random_id_string = ""
|
||||
for _ in range(10):
|
||||
random_id_string += random.SystemRandom().choice(ALPHABETS)
|
||||
random_id_string += random.choice(ALPHABETS)
|
||||
expected = ID(base58.b58decode(random_id_string))
|
||||
actual = ID.from_base58(random_id_string.encode())
|
||||
|
||||
|
@ -106,12 +89,14 @@ def test_id_from_base58():
|
|||
|
||||
|
||||
def test_id_from_public_key():
|
||||
bits_list = [1024, 1280, 1536, 1536, 2048]
|
||||
key = RSA.generate(random.choice(bits_list))
|
||||
key_bin = key.exportKey("DER")
|
||||
key_pair = create_new_key_pair()
|
||||
public_key = key_pair.public_key
|
||||
|
||||
key_bin = public_key.serialize_to_protobuf().SerializeToString()
|
||||
algo = multihash.Func.sha2_256
|
||||
mh_digest = multihash.digest(key_bin, algo)
|
||||
expected = ID(mh_digest.encode())
|
||||
actual = ID.from_pubkey(key_bin)
|
||||
|
||||
actual = ID.from_pubkey(public_key)
|
||||
|
||||
assert actual == expected
|
||||
|
|
Loading…
Reference in New Issue
Block a user