improve documentation
This commit is contained in:
parent
eef6ca19d2
commit
dc0f786b2c
8 changed files with 70 additions and 24 deletions
|
|
@ -32,6 +32,8 @@ module DiasporaFederation
|
|||
end
|
||||
|
||||
# Generates XML and updates signatures
|
||||
# @see Entity#to_xml
|
||||
# @return [Nokogiri::XML::Element] root element containing properties as child elements
|
||||
def to_xml
|
||||
entity_xml.tap do |xml|
|
||||
hash = to_h
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ module DiasporaFederation
|
|||
# {http://www.rubydoc.info/gems/nokogiri/Nokogiri/XML/Element Nokogiri::XML::Element}s
|
||||
#
|
||||
# @see Nokogiri::XML::Node.to_xml
|
||||
# @see Salmon::XmlPayload.pack
|
||||
# @see XmlPayload#pack
|
||||
#
|
||||
# @return [Nokogiri::XML::Element] root element containing properties as child elements
|
||||
def to_xml
|
||||
|
|
|
|||
|
|
@ -18,8 +18,11 @@ module DiasporaFederation
|
|||
# @param [String] key AES key
|
||||
# @param [String] iv AES initialization vector
|
||||
# @return [String] base64 encoded ciphertext
|
||||
# @raise [ArgumentError] if any of the arguments is missing or not the correct type
|
||||
def self.encrypt(data, key, iv)
|
||||
raise ArgumentError unless data.instance_of?(String)
|
||||
raise ArgumentError unless data.instance_of?(String) &&
|
||||
key.instance_of?(String) &&
|
||||
iv.instance_of?(String)
|
||||
|
||||
cipher = OpenSSL::Cipher.new(CIPHER)
|
||||
cipher.encrypt
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ module DiasporaFederation
|
|||
|
||||
# Creates a new instance of MagicEnvelope.
|
||||
#
|
||||
# @param rsa_pkey [OpenSSL::PKey::RSA] private key used for signing
|
||||
# @param payload [Entity] Entity instance
|
||||
# @param [OpenSSL::PKey::RSA] rsa_pkey private key used for signing
|
||||
# @param [Entity] payload Entity instance
|
||||
# @raise [ArgumentError] if either argument is not of the right type
|
||||
def initialize(rsa_pkey, payload)
|
||||
raise ArgumentError unless rsa_pkey.instance_of?(OpenSSL::PKey::RSA) &&
|
||||
|
|
@ -55,7 +55,7 @@ module DiasporaFederation
|
|||
# Builds the XML structure for the magic envelope, inserts the {ENCODING}
|
||||
# encoded data and signs the envelope using {DIGEST}.
|
||||
#
|
||||
# @return [Nokogiri::XML::Element] XML root node
|
||||
# @param [Nokogiri::XML::Builder] xml Salmon XML builder
|
||||
def envelop(xml)
|
||||
xml["me"].env {
|
||||
xml["me"].data(Base64.urlsafe_encode64(@payload), type: DATA_TYPE)
|
||||
|
|
@ -71,7 +71,8 @@ module DiasporaFederation
|
|||
# This must happen after the MagicEnvelope instance was created and before
|
||||
# {MagicEnvelope#envelop} is called.
|
||||
#
|
||||
# @see Salmon.aes_encrypt
|
||||
# @see AES#generate_key_and_iv
|
||||
# @see AES#encrypt
|
||||
#
|
||||
# @return [Hash] AES key and iv. E.g.: { key: "...", iv: "..." }
|
||||
def encrypt!
|
||||
|
|
@ -85,8 +86,8 @@ module DiasporaFederation
|
|||
#
|
||||
# Does some sanity checking to avoid bad surprises...
|
||||
#
|
||||
# @see XmlPayload.unpack
|
||||
# @see Salmon.aes_decrypt
|
||||
# @see XmlPayload#unpack
|
||||
# @see AES#decrypt
|
||||
#
|
||||
# @param [Nokogiri::XML::Element] magic_env XML root node of a magic envelope
|
||||
# @param [OpenSSL::PKey::RSA] rsa_pubkey public key to verify the signature
|
||||
|
|
@ -118,6 +119,8 @@ module DiasporaFederation
|
|||
private
|
||||
|
||||
# create the signature for all fields according to specification
|
||||
#
|
||||
# @return [String] the signature
|
||||
def signature
|
||||
subject = self.class.sig_subject([@payload,
|
||||
DATA_TYPE,
|
||||
|
|
@ -126,7 +129,7 @@ module DiasporaFederation
|
|||
@rsa_pkey.sign(DIGEST, subject)
|
||||
end
|
||||
|
||||
# @param [Nokogiri::XML::Element] env envelope
|
||||
# @param [Nokogiri::XML::Element] env magic envelope XML
|
||||
def self.envelope_valid?(env)
|
||||
(env.instance_of?(Nokogiri::XML::Element) &&
|
||||
env.name == "env" &&
|
||||
|
|
@ -137,8 +140,9 @@ module DiasporaFederation
|
|||
end
|
||||
private_class_method :envelope_valid?
|
||||
|
||||
# @param [Nokogiri::XML::Element] env
|
||||
# @param [Nokogiri::XML::Element] env magic envelope XML
|
||||
# @param [OpenSSL::PKey::RSA] pkey public key
|
||||
# @return [Boolean]
|
||||
def self.signature_valid?(env, pkey)
|
||||
subject = sig_subject([Base64.urlsafe_decode64(env.at_xpath("me:data").content),
|
||||
env.at_xpath("me:data")["type"],
|
||||
|
|
@ -154,20 +158,28 @@ module DiasporaFederation
|
|||
# the given array should consist of the data, data_type (mimetype), encoding
|
||||
# and the algorithm
|
||||
# @param [Array<String>] data_arr
|
||||
# @return [String] signature subject
|
||||
def self.sig_subject(data_arr)
|
||||
data_arr.map {|i| Base64.urlsafe_encode64(i) }.join(".")
|
||||
end
|
||||
|
||||
# @param [Nokogiri::XML::Element] magic_env magic envelope XML
|
||||
# @return [Boolean]
|
||||
def self.encoding_valid?(magic_env)
|
||||
magic_env.at_xpath("me:encoding").content == ENCODING
|
||||
end
|
||||
private_class_method :encoding_valid?
|
||||
|
||||
# @param [Nokogiri::XML::Element] magic_env magic envelope XML
|
||||
# @return [Boolean]
|
||||
def self.algorithm_valid?(magic_env)
|
||||
magic_env.at_xpath("me:alg").content == ALGORITHM
|
||||
end
|
||||
private_class_method :algorithm_valid?
|
||||
|
||||
# @param [Nokogiri::XML::Element] magic_env magic envelope XML
|
||||
# @param [Hash] cipher_params hash containing the key and iv
|
||||
# @return [String] data
|
||||
def self.read_and_decrypt_data(magic_env, cipher_params)
|
||||
data = Base64.urlsafe_decode64(magic_env.at_xpath("me:data").content)
|
||||
data = AES.decrypt(data, cipher_params[:key], cipher_params[:iv]) unless cipher_params.nil?
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ module DiasporaFederation
|
|||
end
|
||||
end
|
||||
|
||||
# Builds the xml for the Salmon Slap.
|
||||
#
|
||||
# @yield [xml] Invokes the block with the
|
||||
# {http://www.rubydoc.info/gems/nokogiri/Nokogiri/XML/Builder Nokogiri::XML::Builder}
|
||||
# @return [String] Slap XML
|
||||
def self.build_xml
|
||||
builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
|
||||
xml.diaspora("xmlns" => Salmon::XMLNS, "xmlns:me" => MagicEnvelope::XMLNS) {
|
||||
|
|
@ -102,6 +107,9 @@ module DiasporaFederation
|
|||
builder.to_xml
|
||||
end
|
||||
|
||||
# Parses the magic envelop from the document.
|
||||
#
|
||||
# @param [Nokogiri::XML::Document] doc Salmon XML Document
|
||||
def add_magic_env_from_doc(doc)
|
||||
@magic_envelope = doc.at_xpath("d:diaspora/me:env", Slap::NS).tap do |env|
|
||||
raise MissingMagicEnvelope if env.nil?
|
||||
|
|
|
|||
|
|
@ -82,18 +82,18 @@ module DiasporaFederation
|
|||
# Works recursively on nested Entities and Arrays thereof.
|
||||
#
|
||||
# @param [Class] klass entity class
|
||||
# @param [Nokogiri::XML::Element] node xml nodes
|
||||
# @param [Nokogiri::XML::Element] root_node xml nodes
|
||||
# @return [Entity] instance
|
||||
def self.populate_entity(klass, node)
|
||||
def self.populate_entity(klass, root_node)
|
||||
# Use all known properties to build the Entity. All other elements are respected
|
||||
# and attached to resulted hash as string. It is intended to build a hash
|
||||
# invariable of an Entity definition, in order to support receiving objects
|
||||
# from the future versions of Diaspora, where new elements may have been added.
|
||||
data = node.element_children.map { |child|
|
||||
data = root_node.element_children.map { |child|
|
||||
xml_name = child.name
|
||||
property = klass.class_props.find {|prop| prop[:xml_name].to_s == xml_name }
|
||||
if property
|
||||
parse_element_from_node(property[:name], property[:type], xml_name, node)
|
||||
parse_element_from_node(property[:name], property[:type], xml_name, root_node)
|
||||
else
|
||||
[xml_name, child.text]
|
||||
end
|
||||
|
|
@ -105,6 +105,11 @@ module DiasporaFederation
|
|||
end
|
||||
private_class_method :populate_entity
|
||||
|
||||
# @param [Symbol] name property name
|
||||
# @param [Class] type target type to parse
|
||||
# @param [String] xml_name xml tag to parse
|
||||
# @param [Nokogiri::XML::Element] node XML node to parse
|
||||
# @return [Array<Symbol, Object>] parsed data
|
||||
def self.parse_element_from_node(name, type, xml_name, node)
|
||||
if type == String
|
||||
[name, parse_string_from_node(xml_name, node)]
|
||||
|
|
@ -117,26 +122,35 @@ module DiasporaFederation
|
|||
private_class_method :parse_element_from_node
|
||||
|
||||
# create simple entry in data hash
|
||||
#
|
||||
# @param [String] name xml tag to parse
|
||||
# @param [Nokogiri::XML::Element] root_node XML root_node to parse
|
||||
# @return [String] data
|
||||
def self.parse_string_from_node(name, node)
|
||||
n = node.xpath(name.to_s)
|
||||
n.first.text if n.any?
|
||||
def self.parse_string_from_node(name, root_node)
|
||||
node = root_node.xpath(name.to_s)
|
||||
node.first.text if node.any?
|
||||
end
|
||||
private_class_method :parse_string_from_node
|
||||
|
||||
# create an entry in the data hash for the nested entity
|
||||
#
|
||||
# @param [Class] type target type to parse
|
||||
# @param [Nokogiri::XML::Element] root_node XML node to parse
|
||||
# @return [Entity] parsed child entity
|
||||
def self.parse_entity_from_node(type, node)
|
||||
n = node.xpath(type.entity_name)
|
||||
populate_entity(type, n.first) if n.any?
|
||||
def self.parse_entity_from_node(type, root_node)
|
||||
node = root_node.xpath(type.entity_name)
|
||||
populate_entity(type, node.first) if node.any?
|
||||
end
|
||||
private_class_method :parse_entity_from_node
|
||||
|
||||
# collect all nested children of that type and create an array in the data hash
|
||||
#
|
||||
# @param [Array<Class>] type target type to parse
|
||||
# @param [Nokogiri::XML::Element] root_node XML node to parse
|
||||
# @return [Array<Entity>] array with parsed child entities
|
||||
def self.parse_array_from_node(type, node)
|
||||
n = node.xpath(type.first.entity_name)
|
||||
n.map {|child| populate_entity(type.first, child) }
|
||||
def self.parse_array_from_node(type, root_node)
|
||||
node = root_node.xpath(type.first.entity_name)
|
||||
node.map {|child| populate_entity(type.first, child) }
|
||||
end
|
||||
private_class_method :parse_array_from_node
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@ module DiasporaFederation
|
|||
# this module defines operations of signing an arbitrary hash with an arbitrary key
|
||||
module Signing
|
||||
extend Logging
|
||||
|
||||
# Sign the data with the key
|
||||
#
|
||||
# @param [Hash] hash data to sign
|
||||
# @param [OpenSSL::PKey::RSA] key An RSA key
|
||||
# @return [String] A Base64 encoded signature of #signable_string with key
|
||||
def self.sign_with_key(hash, key)
|
||||
|
|
@ -17,6 +21,7 @@ module DiasporaFederation
|
|||
|
||||
# Check that signature is a correct signature
|
||||
#
|
||||
# @param [Hash] hash data to verify
|
||||
# @param [String] signature The signature to be verified.
|
||||
# @param [OpenSSL::PKey::RSA] key An RSA key
|
||||
# @return [Boolean]
|
||||
|
|
@ -40,6 +45,8 @@ module DiasporaFederation
|
|||
|
||||
private
|
||||
|
||||
# @param [Hash] hash data to sign
|
||||
# @return [String] signature data string
|
||||
def self.signable_string(hash)
|
||||
hash.map { |name, value|
|
||||
value.to_s unless name.match(/signature/)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
require "diaspora_federation/test/factories"
|
||||
|
||||
module DiasporaFederation
|
||||
# This module incapsulates helper functions maybe wanted by a testsuite of a diaspora_federation gem user application
|
||||
# This module encapsulates helper functions maybe wanted by a testsuite of a diaspora_federation gem user application
|
||||
module Test
|
||||
# Sort hash according to an entity class's property sequence.
|
||||
# This is used for rspec tests in order to generate correct input hash to
|
||||
|
|
|
|||
Loading…
Reference in a new issue