🤞 One failure left...
This commit is contained in:
parent
68c4c45427
commit
49a3623b28
|
@ -60,6 +60,12 @@ module Pigeon
|
|||
# /Constants for internal use only
|
||||
|
||||
class Helpers
|
||||
VERFIY_ERROR = "Expected field `%s` to equal %s, got: %s"
|
||||
MSG_SIZE_ERROR = "Messages cannot have more than 64 keys. Got %s."
|
||||
|
||||
class VerificationError < StandardError; end
|
||||
class MessageSizeError < StandardError; end
|
||||
|
||||
B32_ENC = {
|
||||
"00000" => "0", "00001" => "1", "00010" => "2", "00011" => "3",
|
||||
"00100" => "4", "00101" => "5", "00110" => "6", "00111" => "7",
|
||||
|
@ -145,7 +151,7 @@ module Pigeon
|
|||
verify_key.verify(binary_signature, string)
|
||||
end
|
||||
|
||||
def assert(field, actual, expected)
|
||||
def self.assert(field, actual, expected)
|
||||
unless actual == expected
|
||||
message = VERFIY_ERROR % [field, actual || "nil", expected || "nil"]
|
||||
raise VerificationError, message
|
||||
|
@ -171,24 +177,30 @@ module Pigeon
|
|||
message
|
||||
end
|
||||
|
||||
def publish_message(db, msg)
|
||||
return db.read_message(multihash) if db.message?(multihash)
|
||||
def self.verify_message(db, msg)
|
||||
msg_hash = msg.multihash
|
||||
body = msg.body
|
||||
key_count = body.count
|
||||
author = msg.author
|
||||
signature = msg.signature
|
||||
|
||||
return db.read_message(msg_hash) if db.message?(msg_hash)
|
||||
|
||||
if key_count > 64
|
||||
msg = MSG_SIZE_ERROR % key_count
|
||||
raise MessageSizeError, msg
|
||||
end
|
||||
count = db.get_message_count_for(author.multihash)
|
||||
expected_prev = db.get_message_by_depth(author.multihash, count - 1) || Pigeon::NOTHING
|
||||
assert("depth", count, depth)
|
||||
assert("depth", count, msg.depth)
|
||||
# TODO: Re-visit this. Our current verification method
|
||||
# is probably too strict and won't allow for partial
|
||||
# verification of feeds.
|
||||
assert("lipmaa", Helpers.lipmaa(depth), lipmaa)
|
||||
assert("prev", prev, expected_prev)
|
||||
verify_signature
|
||||
assert("lipmaa", Helpers.lipmaa(msg.depth), msg.lipmaa)
|
||||
assert("prev", msg.prev, expected_prev)
|
||||
tpl = msg.template.render_without_signature
|
||||
Helpers.verify_string(author, signature, tpl)
|
||||
msg.freeze
|
||||
db.save_message(msg)
|
||||
msg
|
||||
end
|
||||
|
||||
|
|
|
@ -21,7 +21,11 @@ module Pigeon
|
|||
def all_peers(); store.all_peers(); end
|
||||
def all_blocks(); store.all_blocks(); end
|
||||
def message?(multihash); store.message?(multihash); end
|
||||
def save_message(msg_obj); store.save_message(msg_obj); end
|
||||
|
||||
def save_message(msg_obj)
|
||||
store.insert_message(Helpers.verify_message(self, msg_obj))
|
||||
end
|
||||
|
||||
def read_message(multihash); store.read_message(multihash); end
|
||||
|
||||
def get_message_count_for(multihash)
|
||||
|
@ -84,13 +88,14 @@ module Pigeon
|
|||
# Store a message that someone (not the LocalIdentity)
|
||||
# has authored.
|
||||
def ingest(author:, body:, depth:, kind:, lipmaa:, prev:, signature:)
|
||||
self.save_message(Message.new(author: RemoteIdentity.new(author),
|
||||
kind: kind,
|
||||
body: body,
|
||||
prev: prev,
|
||||
lipmaa: lipmaa,
|
||||
signature: signature,
|
||||
depth: depth))
|
||||
msg = Message.new(author: RemoteIdentity.new(author),
|
||||
kind: kind,
|
||||
body: body,
|
||||
prev: prev,
|
||||
lipmaa: lipmaa,
|
||||
signature: signature,
|
||||
depth: depth)
|
||||
save_message(msg)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -98,7 +103,7 @@ module Pigeon
|
|||
attr_reader :store
|
||||
|
||||
def init_local_identity(new_seed)
|
||||
key = store.get_config(SEED_CONFIG_KEY)
|
||||
key = get_config(SEED_CONFIG_KEY)
|
||||
if key
|
||||
@local_identity = LocalIdentity.new(key)
|
||||
else
|
||||
|
|
|
@ -4,12 +4,6 @@ module Pigeon
|
|||
class Message
|
||||
attr_reader :author, :kind, :body, :signature, :depth, :lipmaa, :prev
|
||||
|
||||
class VerificationError < StandardError; end
|
||||
class MessageSizeError < StandardError; end
|
||||
|
||||
VERFIY_ERROR = "Expected field `%s` to equal %s, got: %s"
|
||||
MSG_SIZE_ERROR = "Messages cannot have more than 64 keys. Got %s."
|
||||
|
||||
def render
|
||||
template.render.chomp
|
||||
end
|
||||
|
@ -21,13 +15,6 @@ module Pigeon
|
|||
"#{MESSAGE_SIGIL}#{sha256}#{BLOB_FOOTER}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def verify_signature
|
||||
tpl = template.render_without_signature
|
||||
Helpers.verify_string(author, signature, tpl)
|
||||
end
|
||||
|
||||
def initialize(author:,
|
||||
kind:,
|
||||
body:,
|
||||
|
|
|
@ -100,7 +100,7 @@ module Pigeon
|
|||
read { store[MESG_NS].fetch(multihash) }
|
||||
end
|
||||
|
||||
def save_message(msg)
|
||||
def insert_message(msg)
|
||||
write do
|
||||
return msg if store[MESG_NS][msg.multihash]
|
||||
insert_and_update_index(msg)
|
||||
|
|
|
@ -31,12 +31,12 @@ RSpec.describe Pigeon::Message do
|
|||
|
||||
it "discards a draft after signing" do
|
||||
db.publish_draft(draft)
|
||||
expect { db.current_draft }.to raise_error("NO DRAFT FOUND")
|
||||
expect(db.current_draft).to be(nil)
|
||||
end
|
||||
|
||||
it "creates a single message" do
|
||||
message = db.publish_draft(draft)
|
||||
expect(message.author.multihash).to eq(Pigeon::LocalIdentity.current.multihash)
|
||||
expect(message.author.multihash).to eq(db.local_identity.multihash)
|
||||
expect(message.body).to eq(draft.body)
|
||||
expect(message.depth).to eq(0)
|
||||
expect(message.kind).to eq("unit_test")
|
||||
|
@ -100,7 +100,7 @@ RSpec.describe Pigeon::Message do
|
|||
end
|
||||
expect do
|
||||
create_message(body)
|
||||
end.to raise_error(Pigeon::Message::MessageSizeError, error)
|
||||
end.to raise_error(Pigeon::Helpers::MessageSizeError, error)
|
||||
end
|
||||
|
||||
it "verifies accuracy of signatures" do
|
||||
|
@ -110,7 +110,7 @@ RSpec.describe Pigeon::Message do
|
|||
plaintext = template.render_without_signature
|
||||
|
||||
# Make fake pairs of data for cross-checking
|
||||
key1 = Pigeon::LocalIdentity.current.instance_variable_get(:@signing_key)
|
||||
key1 = db.local_identity.instance_variable_get(:@signing_key)
|
||||
key2 = Ed25519::SigningKey.new(secret)
|
||||
|
||||
sig1 = key1.sign(plaintext)
|
||||
|
@ -128,20 +128,22 @@ RSpec.describe Pigeon::Message do
|
|||
end
|
||||
|
||||
it "crashes on forged fields" do
|
||||
tokens = [
|
||||
[:AUTHOR, "@DYdgK1KUInVtG3lS45hA1HZ-jTuvfLKsxDpXPFCve04=.ed25519"],
|
||||
[:KIND, "invalid"],
|
||||
[:PREV, "NONE"],
|
||||
[:DEPTH, 10],
|
||||
[:LIPMAA, Pigeon::Helpers.lipmaa(10)],
|
||||
[:HEADER_END],
|
||||
[:BODY_ENTRY, "duplicate", "This key is a duplicate."],
|
||||
[:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ==.sig.ed25519"],
|
||||
[:MESSAGE_END],
|
||||
]
|
||||
e = Pigeon::Helpers::VerificationError
|
||||
m = "Expected field `depth` to equal 0, got: 10"
|
||||
expect do
|
||||
Pigeon::Parser.parse(db, [
|
||||
[:AUTHOR, "@DYdgK1KUInVtG3lS45hA1HZ-jTuvfLKsxDpXPFCve04=.ed25519"],
|
||||
[:KIND, "invalid"],
|
||||
[:PREV, "NONE"],
|
||||
[:DEPTH, 10],
|
||||
[:LIPMAA, Pigeon::Helpers.lipmaa(10)],
|
||||
[:HEADER_END],
|
||||
[:BODY_ENTRY, "duplicate", "This key is a duplicate."],
|
||||
[:SIGNATURE, "DN7yPTE-m433ND3jBL4oM23XGxBKafjq0Dp9ArBQa_TIGU7DmCxTumieuPBN-NKxlx_0N7-c5zjLb5XXVHYPCQ==.sig.ed25519"],
|
||||
[:MESSAGE_END],
|
||||
]).first.save!
|
||||
end.to raise_error(Pigeon::Message::VerificationError, m)
|
||||
msg = Pigeon::Parser.parse(db, tokens)[0]
|
||||
end.to raise_error(e, m)
|
||||
end
|
||||
|
||||
# Every ASCII character that is not a letter:
|
||||
|
|
Loading…
Reference in New Issue