Merge branch 'federation_update'
This commit is contained in:
commit
482e423f45
17 changed files with 212 additions and 74 deletions
|
|
@ -13,8 +13,6 @@ module Jobs
|
||||||
MAX_RETRIES = 3
|
MAX_RETRIES = 3
|
||||||
|
|
||||||
def self.perform(user_id, encoded_object_xml, person_ids, dispatcher_class_as_string, retry_count=0)
|
def self.perform(user_id, encoded_object_xml, person_ids, dispatcher_class_as_string, retry_count=0)
|
||||||
return true if user_id == '91842' #NOTE 09/08/11 blocking diapsorahqposts
|
|
||||||
|
|
||||||
user = User.find(user_id)
|
user = User.find(user_id)
|
||||||
people = Person.where(:id => person_ids)
|
people = Person.where(:id => person_ids)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,5 +9,5 @@
|
||||||
<Link rel='http://webfinger.net/rel/profile-page' type='text/html' <%="#{person_href(@person, :absolute => true)}"%>/>
|
<Link rel='http://webfinger.net/rel/profile-page' type='text/html' <%="#{person_href(@person, :absolute => true)}"%>/>
|
||||||
<Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="<%=@person.public_url%>.atom"/>
|
<Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="<%=@person.public_url%>.atom"/>
|
||||||
|
|
||||||
<Link rel="diaspora-public-key" type = 'RSA' href="<%=Base64.encode64(@person.exported_key)%>"/>
|
<Link rel="diaspora-public-key" type = 'RSA' href="<%=Base64.encode64s(@person.exported_key)%>"/>
|
||||||
</XRD>
|
</XRD>
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,9 @@ Diaspora::Application.routes.draw do
|
||||||
|
|
||||||
get 'mobile/toggle', :to => 'home#toggle_mobile', :as => 'toggle_mobile'
|
get 'mobile/toggle', :to => 'home#toggle_mobile', :as => 'toggle_mobile'
|
||||||
|
|
||||||
|
#Protocol Url
|
||||||
|
get 'protocol' => redirect("https://github.com/diaspora/diaspora/wiki/Diaspora%27s-federation-protocol")
|
||||||
|
|
||||||
# Startpage
|
# Startpage
|
||||||
|
|
||||||
root :to => 'home#show'
|
root :to => 'home#show'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
module Diaspora
|
module Diaspora
|
||||||
module Encryptable
|
module Encryptable
|
||||||
|
|
||||||
|
LAST_FALLBACK_TIME = "Sept 19 2011 17:00 UTC "
|
||||||
# Check that signature is a correct signature of #signable_string by person
|
# Check that signature is a correct signature of #signable_string by person
|
||||||
#
|
#
|
||||||
# @param [String] signature The signature to be verified.
|
# @param [String] signature The signature to be verified.
|
||||||
|
|
@ -17,7 +19,10 @@ module Diaspora
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
log_string = "event=verify_signature status=complete guid=#{self.guid}"
|
log_string = "event=verify_signature status=complete guid=#{self.guid}"
|
||||||
|
validity = person.public_key.verify OpenSSL::Digest::SHA256.new, Base64.decode64(signature), signable_string
|
||||||
|
if !validity && Time.now < Time.parse(LAST_FALLBACK_TIME)
|
||||||
validity = person.public_key.verify "SHA", Base64.decode64(signature), signable_string
|
validity = person.public_key.verify "SHA", Base64.decode64(signature), signable_string
|
||||||
|
end
|
||||||
log_string += " validity=#{validity}"
|
log_string += " validity=#{validity}"
|
||||||
Rails.logger.info(log_string)
|
Rails.logger.info(log_string)
|
||||||
validity
|
validity
|
||||||
|
|
@ -26,7 +31,7 @@ module Diaspora
|
||||||
# @param [OpenSSL::PKey::RSA] key An RSA key
|
# @param [OpenSSL::PKey::RSA] key An RSA key
|
||||||
# @return [String] A Base64 encoded signature of #signable_string with key
|
# @return [String] A Base64 encoded signature of #signable_string with key
|
||||||
def sign_with_key(key)
|
def sign_with_key(key)
|
||||||
sig = Base64.encode64(key.sign "SHA", signable_string)
|
sig = Base64.encode64s(key.sign( OpenSSL::Digest::SHA256.new, signable_string ))
|
||||||
log_hash = {:event => :sign_with_key, :status => :complete}
|
log_hash = {:event => :sign_with_key, :status => :complete}
|
||||||
log_hash.merge(:model_id => self.id) if self.respond_to?(:persisted?)
|
log_hash.merge(:model_id => self.id) if self.respond_to?(:persisted?)
|
||||||
Rails.logger.info(log_hash)
|
Rails.logger.info(log_hash)
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,14 @@ module Encryptor
|
||||||
ciphertext = aes_encrypt(cleartext, aes_key)
|
ciphertext = aes_encrypt(cleartext, aes_key)
|
||||||
encrypted_key = encrypt_aes_key aes_key
|
encrypted_key = encrypt_aes_key aes_key
|
||||||
cipher_hash = {:aes_key => encrypted_key, :ciphertext => ciphertext}
|
cipher_hash = {:aes_key => encrypted_key, :ciphertext => ciphertext}
|
||||||
Base64.encode64( cipher_hash.to_json )
|
Base64.encode64s( cipher_hash.to_json )
|
||||||
end
|
end
|
||||||
|
|
||||||
def gen_aes_key
|
def gen_aes_key
|
||||||
cipher = OpenSSL::Cipher.new('AES-256-CBC')
|
cipher = OpenSSL::Cipher.new('AES-256-CBC')
|
||||||
key = cipher.random_key
|
key = cipher.random_key
|
||||||
iv = cipher.random_iv
|
iv = cipher.random_iv
|
||||||
{'key' => Base64.encode64(key), 'iv' => Base64.encode64(iv)}
|
{'key' => Base64.encode64s(key), 'iv' => Base64.encode64s(iv)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def aes_encrypt(txt, key)
|
def aes_encrypt(txt, key)
|
||||||
|
|
@ -27,11 +27,11 @@ module Encryptor
|
||||||
ciphertext = ''
|
ciphertext = ''
|
||||||
ciphertext << cipher.update(txt)
|
ciphertext << cipher.update(txt)
|
||||||
ciphertext << cipher.final
|
ciphertext << cipher.final
|
||||||
Base64.encode64 ciphertext
|
Base64.encode64s(ciphertext)
|
||||||
end
|
end
|
||||||
|
|
||||||
def encrypt_aes_key key
|
def encrypt_aes_key key
|
||||||
Base64.encode64 public_key.public_encrypt( key.to_json )
|
Base64.encode64s(public_key.public_encrypt( key.to_json ))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,11 @@ class Postzord::Dispatcher
|
||||||
raise 'this object does not respond_to? to_diaspora xml. try including Diaspora::Webhooks into your object'
|
raise 'this object does not respond_to? to_diaspora xml. try including Diaspora::Webhooks into your object'
|
||||||
end
|
end
|
||||||
|
|
||||||
#if self.object_should_be_processed_as_public?(object)
|
if self.object_should_be_processed_as_public?(object)
|
||||||
# Postzord::Dispatcher::Public.new(user, object, opts)
|
Postzord::Dispatcher::Public.new(user, object, opts)
|
||||||
#else
|
else
|
||||||
Postzord::Dispatcher::Private.new(user, object, opts)
|
Postzord::Dispatcher::Private.new(user, object, opts)
|
||||||
#end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param object [Object]
|
# @param object [Object]
|
||||||
|
|
@ -59,7 +59,7 @@ class Postzord::Dispatcher
|
||||||
self.deliver_to_local(local_people)
|
self.deliver_to_local(local_people)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.deliver_to_remote(remote_people) unless @sender.username == 'diasporahq' #NOTE: 09/08/11 this is temporary (~3days max) till we fix fanout in federation
|
self.deliver_to_remote(remote_people)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Array<Person>] Recipients of the object, minus any additional subscribers
|
# @return [Array<Person>] Recipients of the object, minus any additional subscribers
|
||||||
|
|
@ -152,7 +152,7 @@ class Postzord::Dispatcher
|
||||||
# @param remote_people [Array<Person>] Recipients of the post on other pods
|
# @param remote_people [Array<Person>] Recipients of the post on other pods
|
||||||
# @return [void]
|
# @return [void]
|
||||||
def queue_remote_delivery_job(remote_people)
|
def queue_remote_delivery_job(remote_people)
|
||||||
Resque.enqueue(Jobs::HttpMulti, @sender.id, Base64.encode64(@object.to_diaspora_xml), remote_people.map{|p| p.id}, self.class.to_s)
|
Resque.enqueue(Jobs::HttpMulti, @sender.id, Base64.encode64s(@object.to_diaspora_xml), remote_people.map{|p| p.id}, self.class.to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ module Postzord
|
||||||
@user_person = @user.person
|
@user_person = @user.person
|
||||||
@salmon_xml = opts[:salmon_xml]
|
@salmon_xml = opts[:salmon_xml]
|
||||||
|
|
||||||
@sender = opts[:person] || Webfinger.new(self.salmon.author_email).fetch
|
@sender = opts[:person] || Webfinger.new(self.salmon.author_id).fetch
|
||||||
@author = @sender
|
@author = @sender
|
||||||
|
|
||||||
@object = opts[:object]
|
@object = opts[:object]
|
||||||
|
|
@ -23,7 +23,7 @@ module Postzord
|
||||||
if @sender && self.salmon.verified_for_key?(@sender.public_key)
|
if @sender && self.salmon.verified_for_key?(@sender.public_key)
|
||||||
parse_and_receive(salmon.parsed_data)
|
parse_and_receive(salmon.parsed_data)
|
||||||
else
|
else
|
||||||
Rails.logger.info("event=receive status=abort recipient=#{@user.diaspora_handle} sender=#{@salmon.author_email} reason='not_verified for key'")
|
Rails.logger.info("event=receive status=abort recipient=#{@user.diaspora_handle} sender=#{@salmon.author_id} reason='not_verified for key'")
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ module Postzord
|
||||||
|
|
||||||
def initialize(xml)
|
def initialize(xml)
|
||||||
@salmon = Salmon::Slap.from_xml(xml)
|
@salmon = Salmon::Slap.from_xml(xml)
|
||||||
@author = Webfinger.new(@salmon.author_email).fetch
|
@author = Webfinger.new(@salmon.author_id).fetch
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,21 @@ module Salmon
|
||||||
def header(person)
|
def header(person)
|
||||||
<<XML
|
<<XML
|
||||||
<encrypted_header>
|
<encrypted_header>
|
||||||
#{person.encrypt("<decrypted_header>#{plaintext_header}</decrypted_header>")}
|
#{person.encrypt(plaintext_header)}
|
||||||
</encrypted_header>
|
</encrypted_header>
|
||||||
XML
|
XML
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def plaintext_header
|
||||||
|
header =<<HEADER
|
||||||
|
<decrypted_header>
|
||||||
|
<iv>#{iv}</iv>
|
||||||
|
<aes_key>#{aes_key}</aes_key>
|
||||||
|
<author_id>#{@author.diaspora_handle}</author_id>
|
||||||
|
</decrypted_header>
|
||||||
|
HEADER
|
||||||
|
end
|
||||||
|
|
||||||
# @return [String, Boolean] False if RSAError; XML if no error
|
# @return [String, Boolean] False if RSAError; XML if no error
|
||||||
def xml_for(person)
|
def xml_for(person)
|
||||||
begin
|
begin
|
||||||
|
|
@ -25,11 +35,20 @@ XML
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Takes in a doc of the header and sets the author id
|
||||||
|
# returns an empty hash
|
||||||
|
# @return [Hash]
|
||||||
|
def process_header(doc)
|
||||||
|
self.author_id = doc.search('author_id').text
|
||||||
|
self.aes_key = doc.search('aes_key').text
|
||||||
|
self.iv = doc.search('iv').text
|
||||||
|
end
|
||||||
|
|
||||||
# Decrypts an encrypted magic sig envelope
|
# Decrypts an encrypted magic sig envelope
|
||||||
# @param key_hash [Hash] Contains 'key' (aes) and 'iv' values
|
# @param key_hash [Hash] Contains 'key' (aes) and 'iv' values
|
||||||
# @param user [User]
|
# @param user [User]
|
||||||
def parse_data(key_hash, user)
|
def parse_data(user)
|
||||||
user.aes_decrypt(super, key_hash)
|
user.aes_decrypt(super, {'key' => self.aes_key, 'iv' => self.iv})
|
||||||
end
|
end
|
||||||
|
|
||||||
# Decrypts and parses out the salmon header
|
# Decrypts and parses out the salmon header
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ module Salmon
|
||||||
# @return [String]
|
# @return [String]
|
||||||
def to_xml
|
def to_xml
|
||||||
<<ENTRY
|
<<ENTRY
|
||||||
<me:env xmlns:me="http://salmon-protocol.org/ns/magic-env">
|
<me:env>
|
||||||
<me:data type='#{@data_type}'>#{@data}</me:data>
|
<me:data type='#{@data_type}'>#{@data}</me:data>
|
||||||
<me:encoding>#{@encoding}</me:encoding>
|
<me:encoding>#{@encoding}</me:encoding>
|
||||||
<me:alg>#{@alg}</me:alg>
|
<me:alg>#{@alg}</me:alg>
|
||||||
|
|
@ -70,7 +70,7 @@ ENTRY
|
||||||
|
|
||||||
# @return [String]
|
# @return [String]
|
||||||
def get_data_type
|
def get_data_type
|
||||||
'application/atom+xml'
|
'application/xml'
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [String]
|
# @return [String]
|
||||||
|
|
|
||||||
|
|
@ -5,27 +5,12 @@
|
||||||
# Add URL safe Base64 support
|
# Add URL safe Base64 support
|
||||||
module Base64
|
module Base64
|
||||||
module_function
|
module_function
|
||||||
# Returns the Base64-encoded version of +bin+.
|
|
||||||
# This method complies with RFC 4648.
|
|
||||||
# No line feeds are added.
|
|
||||||
def strict_encode64(bin)
|
|
||||||
[bin].pack("m0")
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns the Base64-decoded version of +str+.
|
|
||||||
# This method complies with RFC 4648.
|
|
||||||
# ArgumentError is raised if +str+ is incorrectly padded or contains
|
|
||||||
# non-alphabet characters. Note that CR or LF are also rejected.
|
|
||||||
def strict_decode64(str)
|
|
||||||
str.unpack("m0").first
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns the Base64-encoded version of +bin+.
|
# Returns the Base64-encoded version of +bin+.
|
||||||
# This method complies with ``Base 64 Encoding with URL and Filename Safe
|
# This method complies with ``Base 64 Encoding with URL and Filename Safe
|
||||||
# Alphabet'' in RFC 4648.
|
# Alphabet'' in RFC 4648.
|
||||||
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
||||||
def urlsafe_encode64(bin)
|
def urlsafe_encode64(bin)
|
||||||
strict_encode64(bin).tr("+/", "-_")
|
self.encode64s(bin).tr("+/", "-_")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the Base64-decoded version of +str+.
|
# Returns the Base64-decoded version of +str+.
|
||||||
|
|
@ -33,7 +18,7 @@ module Base64
|
||||||
# Alphabet'' in RFC 4648.
|
# Alphabet'' in RFC 4648.
|
||||||
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
||||||
def urlsafe_decode64(str)
|
def urlsafe_decode64(str)
|
||||||
strict_decode64(str.tr("-_", "+/"))
|
self.decode64(str.tr("-_", "+/"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
module Salmon
|
module Salmon
|
||||||
class Slap
|
class Slap
|
||||||
attr_accessor :magic_sig, :author, :author_email, :parsed_data
|
attr_accessor :magic_sig, :author, :author_id, :parsed_data
|
||||||
attr_accessor :aes_key, :iv
|
attr_accessor :aes_key, :iv
|
||||||
|
|
||||||
delegate :sig, :data_type, :to => :magic_sig
|
delegate :sig, :data_type, :to => :magic_sig
|
||||||
|
|
@ -29,22 +29,16 @@ module Salmon
|
||||||
slap = self.new
|
slap = self.new
|
||||||
doc = Nokogiri::XML(xml)
|
doc = Nokogiri::XML(xml)
|
||||||
|
|
||||||
entry_doc = doc.search('entry')
|
root_doc = doc.search('diaspora')
|
||||||
|
|
||||||
### Header ##
|
### Header ##
|
||||||
header_doc = slap.salmon_header(doc, receiving_user)
|
header_doc = slap.salmon_header(doc, receiving_user)
|
||||||
slap.author_email= header_doc.search('uri').text.split("acct:").last
|
slap.process_header(header_doc)
|
||||||
|
|
||||||
slap.aes_key = header_doc.search('aes_key').text
|
### Envelope ##
|
||||||
slap.iv = header_doc.search('iv').text
|
slap.magic_sig = MagicSigEnvelope.parse(root_doc)
|
||||||
|
|
||||||
slap.magic_sig = MagicSigEnvelope.parse(entry_doc)
|
slap.parsed_data = slap.parse_data(receiving_user)
|
||||||
|
|
||||||
|
|
||||||
#should be in encrypted salmon only
|
|
||||||
key_hash = {'key' => slap.aes_key, 'iv' => slap.iv}
|
|
||||||
|
|
||||||
slap.parsed_data = slap.parse_data(key_hash, receiving_user)
|
|
||||||
|
|
||||||
slap
|
slap
|
||||||
end
|
end
|
||||||
|
|
@ -54,8 +48,15 @@ module Salmon
|
||||||
activity
|
activity
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Takes in a doc of the header and sets the author id
|
||||||
|
# returns an empty hash
|
||||||
|
# @return [String] Author id
|
||||||
|
def process_header(doc)
|
||||||
|
self.author_id = doc.search('author_id').text
|
||||||
|
end
|
||||||
|
|
||||||
# @return [String]
|
# @return [String]
|
||||||
def parse_data(key_hash, user=nil)
|
def parse_data(user=nil)
|
||||||
Slap.decode64url(self.magic_sig.data)
|
Slap.decode64url(self.magic_sig.data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -69,10 +70,10 @@ module Salmon
|
||||||
def xml_for(person)
|
def xml_for(person)
|
||||||
@xml =<<ENTRY
|
@xml =<<ENTRY
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<entry xmlns='http://www.w3.org/2005/Atom'>
|
<diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env">
|
||||||
#{header(person)}
|
#{header(person)}
|
||||||
#{@magic_sig.to_xml}
|
#{@magic_sig.to_xml}
|
||||||
</entry>
|
</diaspora>
|
||||||
ENTRY
|
ENTRY
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -86,19 +87,14 @@ ENTRY
|
||||||
# @return [String] Header XML (sans <header></header> tags)
|
# @return [String] Header XML (sans <header></header> tags)
|
||||||
def plaintext_header
|
def plaintext_header
|
||||||
header =<<HEADER
|
header =<<HEADER
|
||||||
<iv>#{iv}</iv>
|
<author_id>#{@author.diaspora_handle}</author_id>
|
||||||
<aes_key>#{aes_key}</aes_key>
|
|
||||||
<author>
|
|
||||||
<name>#{@author.name}</name>
|
|
||||||
<uri>acct:#{@author.diaspora_handle}</uri>
|
|
||||||
</author>
|
|
||||||
HEADER
|
HEADER
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Person] Author of the salmon object
|
# @return [Person] Author of the salmon object
|
||||||
def author
|
def author
|
||||||
if @author.nil?
|
if @author.nil?
|
||||||
@author ||= Person.by_account_identifier @author_email
|
@author ||= Person.by_account_identifier @author_id
|
||||||
raise "did you remember to async webfinger?" if @author.nil?
|
raise "did you remember to async webfinger?" if @author.nil?
|
||||||
end
|
end
|
||||||
@author
|
@author
|
||||||
|
|
|
||||||
38
spec/lib/diaspora/encryptable_spec.rb
Normal file
38
spec/lib/diaspora/encryptable_spec.rb
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||||
|
# licensed under the Affero General Public License version 3 or later. See
|
||||||
|
# the COPYRIGHT file.
|
||||||
|
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Diaspora::Encryptable do
|
||||||
|
before do
|
||||||
|
@comment = Factory(:comment, :author => bob.person)
|
||||||
|
end
|
||||||
|
describe '#sign_with_key' do
|
||||||
|
it 'signs the object with RSA256 signature' do
|
||||||
|
sig = @comment.sign_with_key bob.encryption_key
|
||||||
|
bob.public_key.verify(OpenSSL::Digest::SHA256.new, Base64.decode64(sig), @comment.signable_string).should be_true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#verify_signature' do
|
||||||
|
it 'verifies SHA256 signatures' do
|
||||||
|
sig = @comment.sign_with_key bob.encryption_key
|
||||||
|
@comment.verify_signature(sig, bob.person).should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
context "fallback" do
|
||||||
|
it "checks the SHA if it's within the week of the rollout window" do
|
||||||
|
sig = Base64.encode64s(bob.encryption_key.sign( "SHA", @comment.signable_string ))
|
||||||
|
@comment.verify_signature(sig, bob.person).should be_true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not verify the fallback after rollout window' do
|
||||||
|
Kernel::silence_warnings { Diaspora::Encryptable.const_set(:LAST_FALLBACK_TIME,((Time.now - 1.week).to_s))}
|
||||||
|
|
||||||
|
sig = Base64.encode64s(bob.encryption_key.sign( "SHA", @comment.signable_string ))
|
||||||
|
@comment.verify_signature(sig, bob.person).should be_false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -36,7 +36,7 @@ describe Postzord::Receiver::Private do
|
||||||
salmon_mock = mock()
|
salmon_mock = mock()
|
||||||
web_mock = mock()
|
web_mock = mock()
|
||||||
web_mock.should_receive(:fetch).and_return true
|
web_mock.should_receive(:fetch).and_return true
|
||||||
salmon_mock.should_receive(:author_email).and_return(true)
|
salmon_mock.should_receive(:author_id).and_return(true)
|
||||||
Salmon::EncryptedSlap.should_receive(:from_xml).with(@salmon_xml, @user).and_return(salmon_mock)
|
Salmon::EncryptedSlap.should_receive(:from_xml).with(@salmon_xml, @user).and_return(salmon_mock)
|
||||||
Webfinger.should_receive(:new).and_return(web_mock)
|
Webfinger.should_receive(:new).and_return(web_mock)
|
||||||
|
|
||||||
|
|
|
||||||
11
spec/lib/salmon/base64_spec.rb
Normal file
11
spec/lib/salmon/base64_spec.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Base64 do
|
||||||
|
describe ".urlsafe_encode64_stripped" do
|
||||||
|
it "strips the trailing '=' from the url_safe characters" do
|
||||||
|
pending
|
||||||
|
Base64.should_receive(:urlsafe_encode64).and_return("MTIzMTIzMQ==")
|
||||||
|
Base64.urlsafe_encode64_stripped("random stuff").should == "MTIzMTIzMQ"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -23,6 +23,25 @@ describe Salmon::EncryptedSlap do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#process_header" do
|
||||||
|
before do
|
||||||
|
@new_slap = Salmon::EncryptedSlap.new
|
||||||
|
@new_slap.process_header(Nokogiri::XML(@created_salmon.plaintext_header))
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the author id' do
|
||||||
|
@new_slap.author_id.should == alice.diaspora_handle
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the aes_key' do
|
||||||
|
@new_slap.aes_key.should == @created_salmon.aes_key
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the aes_key' do
|
||||||
|
@new_slap.iv.should == @created_salmon.iv
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'marshalling' do
|
context 'marshalling' do
|
||||||
let(:xml) {@created_salmon.xml_for(eve.person)}
|
let(:xml) {@created_salmon.xml_for(eve.person)}
|
||||||
let(:parsed_salmon) { Salmon::EncryptedSlap.from_xml(xml, alice)}
|
let(:parsed_salmon) { Salmon::EncryptedSlap.from_xml(xml, alice)}
|
||||||
|
|
@ -41,16 +60,33 @@ describe Salmon::EncryptedSlap do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#xml_for' do
|
describe '#xml_for' do
|
||||||
let(:xml) {@created_salmon.xml_for eve.person}
|
before do
|
||||||
|
@xml = @created_salmon.xml_for eve.person
|
||||||
it 'has a encrypted header field' do
|
|
||||||
xml.include?("encrypted_header").should be true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'the encrypted_header field should contain the aes key' do
|
it 'has a encrypted header field' do
|
||||||
doc = Nokogiri::XML(xml)
|
doc = Nokogiri::XML(@xml)
|
||||||
|
doc.find("encrypted_header").should_not be_blank
|
||||||
|
end
|
||||||
|
|
||||||
|
context "encrypted header" do
|
||||||
|
before do
|
||||||
|
doc = Nokogiri::XML(@xml)
|
||||||
decrypted_header = eve.decrypt(doc.search('encrypted_header').text)
|
decrypted_header = eve.decrypt(doc.search('encrypted_header').text)
|
||||||
decrypted_header.include?(@created_salmon.aes_key).should be true
|
@dh_doc = Nokogiri::XML(decrypted_header)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'contains the aes key' do
|
||||||
|
@dh_doc.search('aes_key').map(&:text).should == [@created_salmon.aes_key]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'contains the initialization vector' do
|
||||||
|
@dh_doc.search('iv').map(&:text).should == [@created_salmon.iv]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'contains the author id' do
|
||||||
|
@dh_doc.search('author_id').map(&:text).should == [alice.diaspora_handle]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,21 @@ describe Salmon::Slap do
|
||||||
salmon.parsed_data.should == @post.to_diaspora_xml
|
salmon.parsed_data.should == @post.to_diaspora_xml
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#from_xml' do
|
||||||
|
it 'procsses the header' do
|
||||||
|
Salmon::Slap.any_instance.should_receive(:process_header)
|
||||||
|
Salmon::Slap.from_xml(@created_salmon.xml_for(eve.person))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#process_header" do
|
||||||
|
it 'sets the author id' do
|
||||||
|
slap = Salmon::Slap.new
|
||||||
|
slap.process_header(Nokogiri::XML(@created_salmon.plaintext_header))
|
||||||
|
slap.author_id.should == alice.diaspora_handle
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#author' do
|
describe '#author' do
|
||||||
let(:xml) {@created_salmon.xml_for(eve.person)}
|
let(:xml) {@created_salmon.xml_for(eve.person)}
|
||||||
let(:parsed_salmon) { Salmon::Slap.from_xml(xml, alice)}
|
let(:parsed_salmon) { Salmon::Slap.from_xml(xml, alice)}
|
||||||
|
|
@ -33,7 +48,7 @@ describe Salmon::Slap do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should fail if no author is found' do
|
it 'should fail if no author is found' do
|
||||||
parsed_salmon.author_email = 'tom@tom.joindiaspora.com'
|
parsed_salmon.author_id = 'tom@tom.joindiaspora.com'
|
||||||
expect {
|
expect {
|
||||||
parsed_salmon.author.public_key
|
parsed_salmon.author.public_key
|
||||||
}.should raise_error "did you remember to async webfinger?"
|
}.should raise_error "did you remember to async webfinger?"
|
||||||
|
|
@ -45,7 +60,7 @@ describe Salmon::Slap do
|
||||||
let(:parsed_salmon) { Salmon::Slap.from_xml(xml)}
|
let(:parsed_salmon) { Salmon::Slap.from_xml(xml)}
|
||||||
|
|
||||||
it 'should parse out the authors diaspora_handle' do
|
it 'should parse out the authors diaspora_handle' do
|
||||||
parsed_salmon.author_email.should == alice.person.diaspora_handle
|
parsed_salmon.author_id.should == alice.person.diaspora_handle
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'verifies the signature for the sender' do
|
it 'verifies the signature for the sender' do
|
||||||
|
|
@ -60,4 +75,36 @@ describe Salmon::Slap do
|
||||||
parsed_salmon.parsed_data.should == @post.to_diaspora_xml
|
parsed_salmon.parsed_data.should == @post.to_diaspora_xml
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#xml_for" do
|
||||||
|
before do
|
||||||
|
@xml = @created_salmon.xml_for(eve.person)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "has diaspora as the root" do
|
||||||
|
doc = Nokogiri::XML(@xml)
|
||||||
|
doc.root.name.should == "diaspora"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "it has the descrypted header" do
|
||||||
|
doc = Nokogiri::XML(@xml)
|
||||||
|
doc.search("header").should_not be_blank
|
||||||
|
end
|
||||||
|
|
||||||
|
context "header" do
|
||||||
|
|
||||||
|
it "it has author_id node " do
|
||||||
|
doc = Nokogiri::XML(@xml)
|
||||||
|
search = doc.search("header").search("author_id")
|
||||||
|
search.map(&:text).should == [alice.diaspora_handle]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
it "it has the magic envelope " do
|
||||||
|
doc = Nokogiri::XML(@xml)
|
||||||
|
doc.find("/me:env").should_not be_blank
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue