Tests for remote feeds
This commit is contained in:
parent
e2ec8313dc
commit
778f74200a
23
ssb/feed.py
23
ssb/feed.py
@ -48,6 +48,9 @@ class Message(object):
|
|||||||
def __init__(self, feed, content, signature, sequence=1, timestamp=None, previous=None):
|
def __init__(self, feed, content, signature, sequence=1, timestamp=None, previous=None):
|
||||||
self.feed = feed
|
self.feed = feed
|
||||||
self.content = content
|
self.content = content
|
||||||
|
|
||||||
|
if signature is None:
|
||||||
|
raise ValueError("signature can't be None")
|
||||||
self.signature = signature
|
self.signature = signature
|
||||||
|
|
||||||
self.previous = previous
|
self.previous = previous
|
||||||
@ -93,11 +96,23 @@ class Message(object):
|
|||||||
|
|
||||||
class LocalMessage(Message):
|
class LocalMessage(Message):
|
||||||
def __init__(self, feed, content, signature=None, sequence=1, timestamp=None, previous=None):
|
def __init__(self, feed, content, signature=None, sequence=1, timestamp=None, previous=None):
|
||||||
super(LocalMessage, self).__init__(feed, content, signature, sequence, timestamp, previous)
|
self.feed = feed
|
||||||
if signature is None:
|
self.content = content
|
||||||
self.signature = self.sign()
|
|
||||||
|
|
||||||
def sign(self):
|
self.previous = previous
|
||||||
|
if self.previous:
|
||||||
|
self.sequence = self.previous.sequence + 1
|
||||||
|
else:
|
||||||
|
self.sequence = sequence
|
||||||
|
|
||||||
|
self.timestamp = int(time.time() * 1000) if timestamp is None else timestamp
|
||||||
|
|
||||||
|
if signature is None:
|
||||||
|
self.signature = self._sign()
|
||||||
|
else:
|
||||||
|
self.signature = signature
|
||||||
|
|
||||||
|
def _sign(self):
|
||||||
# ensure ordering of keys and indentation of 2 characters, like ssb-keys
|
# ensure ordering of keys and indentation of 2 characters, like ssb-keys
|
||||||
data = dumps(self.to_dict(add_signature=False), indent=2)
|
data = dumps(self.to_dict(add_signature=False), indent=2)
|
||||||
return (b64encode(bytes(self.feed.sign(data.encode('ascii')))) + b'.sig.ed25519').decode('ascii')
|
return (b64encode(bytes(self.feed.sign(data.encode('ascii')))) + b'.sig.ed25519').decode('ascii')
|
||||||
|
@ -2,18 +2,24 @@ from base64 import b64decode
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from nacl.signing import SigningKey
|
from nacl.signing import SigningKey, VerifyKey
|
||||||
|
|
||||||
from ssb.feed import LocalMessage, LocalFeed
|
from ssb.feed import LocalMessage, LocalFeed, Feed, Message, NoPrivateKeyException
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def feed():
|
def local_feed():
|
||||||
secret = b64decode('Mz2qkNOP2K6upnqibWrR+z8pVUI1ReA1MLc7QMtF2qQ=')
|
secret = b64decode('Mz2qkNOP2K6upnqibWrR+z8pVUI1ReA1MLc7QMtF2qQ=')
|
||||||
return LocalFeed(SigningKey(secret))
|
return LocalFeed(SigningKey(secret))
|
||||||
|
|
||||||
|
|
||||||
def test_feed():
|
@pytest.fixture()
|
||||||
|
def remote_feed():
|
||||||
|
public = b64decode('I/4cyN/jPBbDsikbHzAEvmaYlaJK33lW3UhWjNXjyrU=')
|
||||||
|
return Feed(VerifyKey(public))
|
||||||
|
|
||||||
|
|
||||||
|
def test_local_feed():
|
||||||
secret = b64decode('Mz2qkNOP2K6upnqibWrR+z8pVUI1ReA1MLc7QMtF2qQ=')
|
secret = b64decode('Mz2qkNOP2K6upnqibWrR+z8pVUI1ReA1MLc7QMtF2qQ=')
|
||||||
feed = LocalFeed(SigningKey(secret))
|
feed = LocalFeed(SigningKey(secret))
|
||||||
assert bytes(feed.private_key) == secret
|
assert bytes(feed.private_key) == secret
|
||||||
@ -21,10 +27,17 @@ def test_feed():
|
|||||||
assert feed.id == '@I/4cyN/jPBbDsikbHzAEvmaYlaJK33lW3UhWjNXjyrU=.ed25519'
|
assert feed.id == '@I/4cyN/jPBbDsikbHzAEvmaYlaJK33lW3UhWjNXjyrU=.ed25519'
|
||||||
|
|
||||||
|
|
||||||
def test_message(feed):
|
def test_remote_feed():
|
||||||
m1 = LocalMessage(feed, OrderedDict([
|
public = b64decode('I/4cyN/jPBbDsikbHzAEvmaYlaJK33lW3UhWjNXjyrU=')
|
||||||
|
feed = Feed(VerifyKey(public))
|
||||||
|
assert bytes(feed.public_key) == public
|
||||||
|
assert feed.id == '@I/4cyN/jPBbDsikbHzAEvmaYlaJK33lW3UhWjNXjyrU=.ed25519'
|
||||||
|
|
||||||
|
|
||||||
|
def test_local_message(local_feed):
|
||||||
|
m1 = LocalMessage(local_feed, OrderedDict([
|
||||||
('type', 'about'),
|
('type', 'about'),
|
||||||
('about', feed.id),
|
('about', local_feed.id),
|
||||||
('name', 'neo'),
|
('name', 'neo'),
|
||||||
('description', 'The Chosen One')
|
('description', 'The Chosen One')
|
||||||
]), timestamp=1495706260190)
|
]), timestamp=1495706260190)
|
||||||
@ -35,9 +48,9 @@ def test_message(feed):
|
|||||||
'lPsQ9P10OgeyH6u0unFgiI2wV/RQ7Q2x2ebxnXYCzsJ055TBMXphRADTKhOMS2EkUxXQ9k3amj5fnWPudGxwBQ==.sig.ed25519'
|
'lPsQ9P10OgeyH6u0unFgiI2wV/RQ7Q2x2ebxnXYCzsJ055TBMXphRADTKhOMS2EkUxXQ9k3amj5fnWPudGxwBQ==.sig.ed25519'
|
||||||
assert m1.key == '%xRDqws/TrQmOd4aEwZ32jdLhP873ZKjIgHlggPR0eoo=.sha256'
|
assert m1.key == '%xRDqws/TrQmOd4aEwZ32jdLhP873ZKjIgHlggPR0eoo=.sha256'
|
||||||
|
|
||||||
m2 = LocalMessage(feed, OrderedDict([
|
m2 = LocalMessage(local_feed, OrderedDict([
|
||||||
('type', 'about'),
|
('type', 'about'),
|
||||||
('about', feed.id),
|
('about', local_feed.id),
|
||||||
('name', 'morpheus'),
|
('name', 'morpheus'),
|
||||||
('description', 'Dude with big jaw')
|
('description', 'Dude with big jaw')
|
||||||
]), previous=m1, timestamp=1495706447426)
|
]), previous=m1, timestamp=1495706447426)
|
||||||
@ -47,3 +60,42 @@ def test_message(feed):
|
|||||||
assert m2.signature == \
|
assert m2.signature == \
|
||||||
'3SY85LX6/ppOfP4SbfwZbKfd6DccbLRiB13pwpzbSK0nU52OEJxOqcJ2Uensr6RkrWztWLIq90sNOn1zRAoOAw==.sig.ed25519'
|
'3SY85LX6/ppOfP4SbfwZbKfd6DccbLRiB13pwpzbSK0nU52OEJxOqcJ2Uensr6RkrWztWLIq90sNOn1zRAoOAw==.sig.ed25519'
|
||||||
assert m2.key == '%nx13uks5GUwuKJC49PfYGMS/1pgGTtwwdWT7kbVaroM=.sha256'
|
assert m2.key == '%nx13uks5GUwuKJC49PfYGMS/1pgGTtwwdWT7kbVaroM=.sha256'
|
||||||
|
|
||||||
|
|
||||||
|
def test_remote_message(remote_feed):
|
||||||
|
signature = 'lPsQ9P10OgeyH6u0unFgiI2wV/RQ7Q2x2ebxnXYCzsJ055TBMXphRADTKhOMS2EkUxXQ9k3amj5fnWPudGxwBQ==.sig.ed25519'
|
||||||
|
m1 = Message(remote_feed, OrderedDict([
|
||||||
|
('type', 'about'),
|
||||||
|
('about', remote_feed.id),
|
||||||
|
('name', 'neo'),
|
||||||
|
('description', 'The Chosen One')
|
||||||
|
]), signature, timestamp=1495706260190)
|
||||||
|
assert m1.timestamp == 1495706260190
|
||||||
|
assert m1.previous is None
|
||||||
|
assert m1.sequence == 1
|
||||||
|
assert m1.signature == signature
|
||||||
|
assert m1.key == '%xRDqws/TrQmOd4aEwZ32jdLhP873ZKjIgHlggPR0eoo=.sha256'
|
||||||
|
|
||||||
|
signature = '3SY85LX6/ppOfP4SbfwZbKfd6DccbLRiB13pwpzbSK0nU52OEJxOqcJ2Uensr6RkrWztWLIq90sNOn1zRAoOAw==.sig.ed25519'
|
||||||
|
m2 = Message(remote_feed, OrderedDict([
|
||||||
|
('type', 'about'),
|
||||||
|
('about', remote_feed.id),
|
||||||
|
('name', 'morpheus'),
|
||||||
|
('description', 'Dude with big jaw')
|
||||||
|
]), signature, previous=m1, timestamp=1495706447426)
|
||||||
|
assert m2.timestamp == 1495706447426
|
||||||
|
assert m2.previous is m1
|
||||||
|
assert m2.sequence == 2
|
||||||
|
assert m2.signature == signature
|
||||||
|
m2.verify(signature)
|
||||||
|
assert m2.key == '%nx13uks5GUwuKJC49PfYGMS/1pgGTtwwdWT7kbVaroM=.sha256'
|
||||||
|
|
||||||
|
|
||||||
|
def test_remote_no_signature(remote_feed):
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
Message(remote_feed, OrderedDict([
|
||||||
|
('type', 'about'),
|
||||||
|
('about', remote_feed.id),
|
||||||
|
('name', 'neo'),
|
||||||
|
('description', 'The Chosen One')
|
||||||
|
]), None, timestamp=1495706260190)
|
||||||
|
Loading…
Reference in New Issue
Block a user