Class: Ticketbai::Signer

Inherits:
Object
  • Object
show all
Defined in:
lib/ticketbai/signer.rb

Constant Summary collapse

C14N =
'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'.freeze
DSIG =
'http://www.w3.org/2000/09/xmldsig#'.freeze
NOKOGIRI_OPTIONS =
Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NONET | Nokogiri::XML::ParseOptions::NOENT
RSA_SHA256 =
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'.freeze
SHA1 =
'http://www.w3.org/2000/09/xmldsig#sha1'.freeze
SHA256 =
'http://www.w3.org/2001/04/xmlenc#sha256'.freeze
SHA384 =
'http://www.w3.org/2001/04/xmldsig-more#sha384'.freeze
SHA512 =
'http://www.w3.org/2001/04/xmlenc#sha512'.freeze
ENVELOPED_SIG =
'http://www.w3.org/2000/09/xmldsig#enveloped-signature'.freeze
NAMESPACES =
'#default ds xs xsi xades xsd'.freeze
XADES =
'http://uri.etsi.org/01903/v1.3.2#'.freeze
POLITICA_NAME =
'Politica de firma TicketBAI 1.0'.freeze
POLITICA_URL =
'https://www.batuz.eus/fitxategiak/batuz/ticketbai/sinadura_elektronikoaren_zehaztapenak_especificaciones_de_la_firma_electronica_v1_0.pdf'.freeze
POLITICA_DIGEST =
'Quzn98x3PMbSHwbUzaj5f5KOpiH0u8bvmwbbbNkO9Es='.freeze

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Signer

Returns a new instance of Signer.

Raises:

  • (ArgumentError)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/ticketbai/signer.rb', line 27

def initialize(args = {})
  xml = args[:xml]
  certificate = args[:certificate]
  key = args[:key]
  @output_path = args[:output_path]

  raise ArgumentError, 'Invalid arguments' if xml.nil? || certificate.nil? || key.nil?

  @doc = Nokogiri::XML(xml) do |config|
    config.options = Nokogiri::XML::ParseOptions::NOBLANKS | Nokogiri::XML::ParseOptions::NOENT | Nokogiri::XML::ParseOptions::NOENT
  end

  @p12 = OpenSSL::PKCS12.new(certificate, key)

  @x509 = @p12.certificate
  @document_tag = @doc.elements.first.name
end

Instance Method Details

#signObject



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/ticketbai/signer.rb', line 45

def sign
  # Build parts for Digest Calculation
  key_info = build_key_info_element
  signed_properties = build_signed_properties_element
  signed_info_element = build_signed_info_element(key_info, signed_properties)

  # Compute Signature
  signed_info_canon = canonicalize_document(signed_info_element)
  signature_value = compute_signature(@p12.key, algorithm(RSA_SHA256).new, signed_info_canon)

  ds = Nokogiri::XML::Node.new('ds:Signature', @doc)

  ds['xmlns:ds'] = DSIG
  ds['Id'] = "xmldsig-#{uuid}"
  ds.add_child(signed_info_element.root)

  sv = Nokogiri::XML::Node.new('ds:SignatureValue', @doc)
  sv['Id'] = "xmldsig-#{uuid}-sigvalue"
  sv.content = signature_value
  ds.add_child(sv)

  ds.add_child(key_info.root)

  dsobj = Nokogiri::XML::Node.new('ds:Object', @doc)
  dsobj['Id'] = "XadesObjectId-xmldsig-#{uuid}" # XADES_OBJECT_ID
  qp = Nokogiri::XML::Node.new('xades:QualifyingProperties', @doc)
  qp['Id'] = "QualifyingProperties-xmldsig-#{uuid}"
  qp['xmlns:ds'] = DSIG
  qp['Target'] = "#xmldsig-#{uuid}"
  qp['xmlns:xades'] = XADES

  qp.add_child(signed_properties.root)

  dsobj.add_child(qp)
  ds.add_child(dsobj)

  name = @doc.root.namespace
  @doc.root.namespace = nil
  @doc.root.add_child(ds)
  @doc.root.namespace = name

  @doc.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML).gsub(/\r|\n/, '')
end