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):
|
||||
self.feed = feed
|
||||
self.content = content
|
||||
|
||||
if signature is None:
|
||||
raise ValueError("signature can't be None")
|
||||
self.signature = signature
|
||||
|
||||
self.previous = previous
|
||||
@ -93,11 +96,23 @@ class Message(object):
|
||||
|
||||
class LocalMessage(Message):
|
||||
def __init__(self, feed, content, signature=None, sequence=1, timestamp=None, previous=None):
|
||||
super(LocalMessage, self).__init__(feed, content, signature, sequence, timestamp, previous)
|
||||
if signature is None:
|
||||
self.signature = self.sign()
|
||||
self.feed = feed
|
||||
self.content = content
|
||||
|
||||
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
|
||||
data = dumps(self.to_dict(add_signature=False), indent=2)
|
||||
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
|
||||
|
||||
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()
|
||||
def feed():
|
||||
def local_feed():
|
||||
secret = b64decode('Mz2qkNOP2K6upnqibWrR+z8pVUI1ReA1MLc7QMtF2qQ=')
|
||||
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=')
|
||||
feed = LocalFeed(SigningKey(secret))
|
||||
assert bytes(feed.private_key) == secret
|
||||
@ -21,10 +27,17 @@ def test_feed():
|
||||
assert feed.id == '@I/4cyN/jPBbDsikbHzAEvmaYlaJK33lW3UhWjNXjyrU=.ed25519'
|
||||
|
||||
|
||||
def test_message(feed):
|
||||
m1 = LocalMessage(feed, OrderedDict([
|
||||
def test_remote_feed():
|
||||
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'),
|
||||
('about', feed.id),
|
||||
('about', local_feed.id),
|
||||
('name', 'neo'),
|
||||
('description', 'The Chosen One')
|
||||
]), timestamp=1495706260190)
|
||||
@ -35,9 +48,9 @@ def test_message(feed):
|
||||
'lPsQ9P10OgeyH6u0unFgiI2wV/RQ7Q2x2ebxnXYCzsJ055TBMXphRADTKhOMS2EkUxXQ9k3amj5fnWPudGxwBQ==.sig.ed25519'
|
||||
assert m1.key == '%xRDqws/TrQmOd4aEwZ32jdLhP873ZKjIgHlggPR0eoo=.sha256'
|
||||
|
||||
m2 = LocalMessage(feed, OrderedDict([
|
||||
m2 = LocalMessage(local_feed, OrderedDict([
|
||||
('type', 'about'),
|
||||
('about', feed.id),
|
||||
('about', local_feed.id),
|
||||
('name', 'morpheus'),
|
||||
('description', 'Dude with big jaw')
|
||||
]), previous=m1, timestamp=1495706447426)
|
||||
@ -47,3 +60,42 @@ def test_message(feed):
|
||||
assert m2.signature == \
|
||||
'3SY85LX6/ppOfP4SbfwZbKfd6DccbLRiB13pwpzbSK0nU52OEJxOqcJ2Uensr6RkrWztWLIq90sNOn1zRAoOAw==.sig.ed25519'
|
||||
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