diff --git a/docs/index.rst b/docs/index.rst index f2bf96f1d1754492ca424376d3210e5739693b1b..524cf6e4481fbc15a90a77ca6c9090944e058276 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -22,7 +22,7 @@ Simply type:: Source code ----------- -Sources can be found at https://github.com/duniter-io/duniter-python-api +Sources can be found at https://github.com/duniter/duniter-python-api Contributions are welcome. diff --git a/duniterpy/documents/document.py b/duniterpy/documents/document.py index e809b9489227fa04910ee917f052e66880db735f..bced25b4486189dab1496fb711dd54c9d72d45b8 100644 --- a/duniterpy/documents/document.py +++ b/duniterpy/documents/document.py @@ -59,6 +59,12 @@ class Document: logging.debug("Signature : \n{0}".format(signing.decode("ascii"))) self.signatures.append(signing.decode("ascii")) + def raw(self): + """ + Returns the raw document in string format + """ + raise NotImplementedError() + def signed_raw(self): """ If keys are None, returns the raw + current signatures diff --git a/duniterpy/key/__init__.py b/duniterpy/key/__init__.py index dc1b0fae8c00c238ac22aec69822bf13425a5c56..66d1aa86884477cdb4901eb7413ab71269146b81 100644 --- a/duniterpy/key/__init__.py +++ b/duniterpy/key/__init__.py @@ -1 +1,2 @@ -from .signing_key import SigningKey \ No newline at end of file +from .signing_key import SigningKey +from .verifying_key import VerifyingKey \ No newline at end of file diff --git a/duniterpy/key/base58.py b/duniterpy/key/base58.py new file mode 100644 index 0000000000000000000000000000000000000000..5bcb8060a03095cba6914ab97ce4464049bf4231 --- /dev/null +++ b/duniterpy/key/base58.py @@ -0,0 +1,10 @@ +import base58 + +class Base58Encoder(object): + @staticmethod + def encode(data): + return base58.b58encode(data) + + @staticmethod + def decode(data): + return base58.b58decode(data) \ No newline at end of file diff --git a/duniterpy/key/signing_key.py b/duniterpy/key/signing_key.py index 7cd1b6e1a253f56d2930f0548c8dd471fd628ade..4b646769858f11feec407b696e5bbb6c58ae14d2 100644 --- a/duniterpy/key/signing_key.py +++ b/duniterpy/key/signing_key.py @@ -4,10 +4,9 @@ duniter public and private keys @author: inso """ -import base58 -import base64 import libnacl.sign from pylibscrypt import scrypt +from .base58 import Base58Encoder SEED_LENGTH = 32 # Length of the key @@ -35,12 +34,3 @@ class SigningKey(libnacl.sign.Signer): super().__init__(seed) self.pubkey = Base58Encoder.encode(self.vk) - -class Base58Encoder(object): - @staticmethod - def encode(data): - return base58.b58encode(data) - - @staticmethod - def decode(data): - return base58.b58decode(data) diff --git a/duniterpy/key/verifying_key.py b/duniterpy/key/verifying_key.py new file mode 100644 index 0000000000000000000000000000000000000000..4af608d27f6d9790d5ff02b457c53ecfbf7037e7 --- /dev/null +++ b/duniterpy/key/verifying_key.py @@ -0,0 +1,35 @@ +""" +duniter public and private keys + +@author: inso +""" + +import base58 +import base64 +import libnacl.sign +from pylibscrypt import scrypt +from .base58 import Base58Encoder + + +class VerifyingKey(libnacl.sign.Verifier): + """ + Class to verify documents + """ + def __init__(self, pubkey): + """ + Creates a Verify class from base58 pubkey + :param pubkey: + """ + key = libnacl.encode.hex_encode(Base58Encoder.decode(pubkey)) + super().__init__(key) + + def verify_document(self, document, **kwargs): + """ + Check specified document + :param duniterpy.documents.Document document: + :return: + """ + signature = base64.b64decode(document.signatures[0]) + prepended = signature + bytes(document.raw(**kwargs), 'ascii') + + return self.verify(prepended) diff --git a/setup.py b/setup.py index 4b7f4b676c43c045d22ec7baf0562c98214e5ea5..0c72f9f47ef8e248b7d07931115ee565aa30337c 100644 --- a/setup.py +++ b/setup.py @@ -49,13 +49,13 @@ setup( author_email="insomniak.fr@gmail.com", - description="A python implementation of [duniter](https://github.com/duniter-io/duniter) API", + description="A python implementation of [duniter](https://github.com/duniter/duniter) API", long_description=open('README.md').read(), # Active la prise en compte du fichier MANIFEST.in include_package_data=True, - url='https://github.com/duniter-io/duniter-python-api', + url='https://github.com/duniter/duniter-python-api', test_suite="tests", classifiers=[ diff --git a/tests/key/__init__.py b/tests/key/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/key/test_verifying_key.py b/tests/key/test_verifying_key.py new file mode 100644 index 0000000000000000000000000000000000000000..4f28272507edf5e09f0bfe1ae252396a6a9e2a2b --- /dev/null +++ b/tests/key/test_verifying_key.py @@ -0,0 +1,25 @@ +from duniterpy.key import VerifyingKey, SigningKey +from duniterpy.documents import Peer +import unittest + + +class Test_VerifyingKey(unittest.TestCase): + def test_from_sign_to_verify(self): + sign_key = SigningKey("saltsalt", "passwordpassword") + verify_key = VerifyingKey(sign_key.pubkey) + self.assertEqual(verify_key.vk, sign_key.vk) + + def test_peer_signature(self): + signed_raw = """Version: 2 +Type: Peer +Currency: test_net +PublicKey: 8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU +Block: 2086-00005D6FC6E22FB308D8815A565A01C66FFB7DC761D616DE0698F6322565F1D6 +Endpoints: +BASIC_MERKLED_API testnet.duniter.inso.ovh 80 +4aQ/sfqFAFUeYkkLdC2OfgXqTBjCIcMptpR/GIlGqbe4aFVJcy9NEVAFx7sHiLuAb+VNnec3XHHC+xOk3MLzDA== +""""" + peer = Peer.from_signed_raw(signed_raw) + pubkey = "8Fi1VSTbjkXguwThF4v2ZxC5whK7pwG2vcGTkPUPjPGU" + verifying_key = VerifyingKey(pubkey) + self.assertTrue(verifying_key.verify_document(peer))