Class: WSDL::Security::Canonicalizer

Inherits:
Object
  • Object
show all
Defined in:
lib/wsdl/security/canonicalizer.rb

Overview

Handles XML Canonicalization (C14N) for digital signatures.

Canonicalization transforms XML into a standard form before signing or digesting. This ensures that semantically equivalent XML documents produce the same byte representation.

This class wraps Nokogiri's C14N support, which uses libxml2.

Examples:

Basic usage

canonicalizer = Canonicalizer.new
canonical_xml = canonicalizer.canonicalize(node)

With inclusive namespaces

canonicalizer = Canonicalizer.new(algorithm: :exclusive_1_0)
canonical_xml = canonicalizer.canonicalize(node, inclusive_namespaces: ['soap', 'wsu'])

See Also:

Constant Summary collapse

C14N =

Local alias for canonicalization algorithm constants

Constants::Algorithms::Canonicalization
ALGORITHMS =

Supported canonicalization algorithms.

Each algorithm specifies:

  • :id - The URI used in XML SignedInfo/Transform elements
  • :mode - The Nokogiri constant for canonicalization
  • :with_comments - Whether to preserve comments
{
  # Exclusive XML Canonicalization 1.0 (most common for WS-Security)
  exclusive_1_0: {
    id: C14N::EXCLUSIVE_1_0,
    mode: Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
    with_comments: false
  },

  # Exclusive XML Canonicalization 1.0 with comments
  exclusive_1_0_with_comments: {
    id: C14N::EXCLUSIVE_1_0_WITH_COMMENTS,
    mode: Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
    with_comments: true
  },

  # Inclusive XML Canonicalization 1.0
  inclusive_1_0: {
    id: C14N::INCLUSIVE_1_0,
    mode: Nokogiri::XML::XML_C14N_1_0,
    with_comments: false
  },

  # Inclusive XML Canonicalization 1.0 with comments
  inclusive_1_0_with_comments: {
    id: C14N::INCLUSIVE_1_0_WITH_COMMENTS,
    mode: Nokogiri::XML::XML_C14N_1_0,
    with_comments: true
  },

  # Inclusive XML Canonicalization 1.1
  inclusive_1_1: {
    id: C14N::INCLUSIVE_1_1,
    mode: Nokogiri::XML::XML_C14N_1_1,
    with_comments: false
  },

  # Inclusive XML Canonicalization 1.1 with comments
  inclusive_1_1_with_comments: {
    id: C14N::INCLUSIVE_1_1_WITH_COMMENTS,
    mode: Nokogiri::XML::XML_C14N_1_1,
    with_comments: true
  }
}.freeze
DEFAULT_ALGORITHM =

Default algorithm to use

:exclusive_1_0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(algorithm: DEFAULT_ALGORITHM) ⇒ Canonicalizer

Creates a new Canonicalizer instance.

Parameters:

  • algorithm (Symbol) (defaults to: DEFAULT_ALGORITHM)

    the canonicalization algorithm to use (default: :exclusive_1_0)

Raises:

  • (ArgumentError)

    if an unknown algorithm is specified



96
97
98
99
100
# File 'lib/wsdl/security/canonicalizer.rb', line 96

def initialize(algorithm: DEFAULT_ALGORITHM)
  @algorithm = ALGORITHMS[algorithm] or
    raise ArgumentError, "Unknown canonicalization algorithm: #{algorithm.inspect}. " \
                         "Valid options: #{ALGORITHMS.keys.join(', ')}"
end

Instance Attribute Details

#algorithmHash (readonly)

Returns the current algorithm configuration.

Returns:

  • (Hash)

    the algorithm settings



87
88
89
# File 'lib/wsdl/security/canonicalizer.rb', line 87

def algorithm
  @algorithm
end

Class Method Details

.canonicalize(node, **options) ⇒ String

Class method to canonicalize with default settings.

Parameters:

  • node (Nokogiri::XML::Node)

    the node to canonicalize

  • options (Hash)

    options passed to #initialize and #canonicalize

Returns:

  • (String)

    the canonicalized XML



165
166
167
168
# File 'lib/wsdl/security/canonicalizer.rb', line 165

def self.canonicalize(node, **options)
  algorithm = options.delete(:algorithm) || DEFAULT_ALGORITHM
  new(algorithm:).canonicalize(node, **options)
end

Instance Method Details

#algorithm_idString

Returns the algorithm URI for use in XML SignedInfo elements.

Returns:

  • (String)

    the canonicalization algorithm URI



126
127
128
# File 'lib/wsdl/security/canonicalizer.rb', line 126

def algorithm_id
  @algorithm[:id]
end

#canonicalize(node, inclusive_namespaces: nil) ⇒ String

Canonicalizes an XML node.

Examples:

Canonicalize a node

doc = WSDL::XML::Parser.parse('<root><child>text</child></root>')
canonicalizer.canonicalize(doc.root)
# => "<root><child>text</child></root>"

With inclusive namespaces

canonicalizer.canonicalize(node, inclusive_namespaces: ['soap'])

Parameters:

  • node (Nokogiri::XML::Node, Nokogiri::XML::Document)

    the node to canonicalize

  • inclusive_namespaces (Array<String>, nil) (defaults to: nil)

    namespace prefixes to include in the canonicalized output (only applicable for exclusive canonicalization)

Returns:

  • (String)

    the canonicalized XML as a string



118
119
120
# File 'lib/wsdl/security/canonicalizer.rb', line 118

def canonicalize(node, inclusive_namespaces: nil)
  node.canonicalize(@algorithm[:mode], inclusive_namespaces, @algorithm[:with_comments])
end

#exclusive?Boolean

Returns whether this is an exclusive canonicalization algorithm.

Exclusive canonicalization only includes namespace declarations that are visibly used in the canonicalized content, unless explicitly listed in the inclusive namespaces list.

Returns:

  • (Boolean)

    true if using exclusive canonicalization



154
155
156
# File 'lib/wsdl/security/canonicalizer.rb', line 154

def exclusive?
  @algorithm[:mode] == Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
end

#modeInteger

Returns the Nokogiri canonicalization mode constant.

Returns:

  • (Integer)

    the Nokogiri C14N mode



134
135
136
# File 'lib/wsdl/security/canonicalizer.rb', line 134

def mode
  @algorithm[:mode]
end

#with_comments?Boolean

Returns whether this algorithm preserves comments.

Returns:

  • (Boolean)

    true if comments are preserved



142
143
144
# File 'lib/wsdl/security/canonicalizer.rb', line 142

def with_comments?
  @algorithm[:with_comments]
end