Module: XMLSecurity
- Extended by:
- FFI::Library
- Defined in:
- lib/xml_sec.rb
Defined Under Namespace
Modules: SignedDocument Classes: SignatureFailure, XmlSecDSigCtx, XmlSecError, XmlSecKeyInfoCtx, XmlSecKeyReq, XmlSecPtrList, XmlSecTransformCtx
Constant Summary collapse
- XMLSEC_ERRORS_R_INVALID_DATA =
12- ErrorCallback =
FFI::Function.new(:void, [ :string, :int, :string, :string, :string, :int, :string ] ) do |file, line, func, errorObject, errorSubject, reason, msg | XMLSecurity.handle_xmlsec_error_callback(file, line, func, errorObject, errorSubject, reason, msg) end
Class Method Summary collapse
- .handle_xmlsec_error_callback(*args) ⇒ Object
- .mute(&block) ⇒ Object
- .raise_exception_if_necessary(file, line, func, errorObject, errorSubject, reason, msg) ⇒ Object
-
.register_xml_id_attribute(doc, root) ⇒ Object
Register 'ID' as an XML id attribute so we can properly sign/validate signatures with references of the form:.
- .sign(reference_id, xml_string, private_key, certificate) ⇒ Object
- .xmlFree(ptr) ⇒ Object
- .xmlMalloc(size) ⇒ Object
Class Method Details
.handle_xmlsec_error_callback(*args) ⇒ Object
254 255 256 257 |
# File 'lib/xml_sec.rb', line 254 def self.handle_xmlsec_error_callback(*args) raise_exception_if_necessary(*args) xmlSecErrorsDefaultCallback(*args) end |
.mute(&block) ⇒ Object
266 267 268 269 270 |
# File 'lib/xml_sec.rb', line 266 def self.mute(&block) xmlSecErrorsDefaultCallbackEnableOutput(false) block.call xmlSecErrorsDefaultCallbackEnableOutput(true) end |
.raise_exception_if_necessary(file, line, func, errorObject, errorSubject, reason, msg) ⇒ Object
259 260 261 262 263 |
# File 'lib/xml_sec.rb', line 259 def self.raise_exception_if_necessary(file, line, func, errorObject, errorSubject, reason, msg) if reason == XMLSEC_ERRORS_R_INVALID_DATA raise XmlSecError.new(msg) end end |
.register_xml_id_attribute(doc, root) ⇒ Object
Register 'ID' as an XML id attribute so we can properly sign/validate signatures with references of the form:
<dsig:Reference URI="#IdOfElementImSigning" />
Which refer to another element in the same document like:
For more information see:
http://www.aleksey.com/xmlsec/faq.html#section_3_4
519 520 521 522 523 524 |
# File 'lib/xml_sec.rb', line 519 def self.register_xml_id_attribute(doc, root) idary = FFI::MemoryPointer.new(:pointer, 2) idary[0].put_pointer(0, FFI::MemoryPointer.from_string("ID")) idary[1].put_pointer(0, nil) XMLSecurity.xmlSecAddIDs(doc, root, idary) end |
.sign(reference_id, xml_string, private_key, certificate) ⇒ Object
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/xml_sec.rb', line 449 def self.sign(reference_id, xml_string, private_key, certificate) doc = self.xmlParseMemory(xml_string, xml_string.size) raise SignatureFailure.new("could not parse XML document") if doc.null? canonicalization_method_id = self.xmlSecTransformExclC14NGetKlass sign_method_id = self.xmlSecOpenSSLTransformRsaSha1GetKlass sign_node = self.xmlSecTmplSignatureCreate(doc, canonicalization_method_id, sign_method_id, nil) raise SignatureFailure.new("failed to create signature template") if sign_node.null? root = self.xmlDocGetRootElement(doc) self.xmlAddChild(root, sign_node) XMLSecurity.register_xml_id_attribute(doc, root) ref_node = self.xmlSecTmplSignatureAddReference(sign_node, self.xmlSecOpenSSLTransformSha1GetKlass, nil, reference_id && "##{reference_id}", nil) raise SignatureFailure.new("failed to add a reference") if ref_node.null? envelope_result = self.xmlSecTmplReferenceAddTransform(ref_node, self.xmlSecTransformEnvelopedGetKlass) raise SignatureFailure.new("failed to add envelope transform to reference") if envelope_result.null? key_info_node = self.xmlSecTmplSignatureEnsureKeyInfo(sign_node, nil) raise SignatureFailure.new("failed to add key info") if key_info_node.null? digital_signature_context = self.xmlSecDSigCtxCreate(nil) raise SignatureFailure.new("failed to create signature context") if digital_signature_context.null? digital_signature_context[:signKey] = self.xmlSecOpenSSLAppKeyLoad(private_key, :xmlSecKeyDataFormatPem, nil, nil, nil) raise SignatureFailure.new("failed to load private pem key from #{private_key}") if digital_signature_context[:signKey].null? if self.xmlSecOpenSSLAppKeyCertLoad(digital_signature_context[:signKey], certificate, :xmlSecKeyDataFormatPem) < 0 raise SignatureFailure.new("failed to load public cert from #{certificate}") end x509_data_node = self.xmlSecTmplKeyInfoAddX509Data(key_info_node) raise SignatureFailure.new("failed to add <dsig:X509Data/> node") if x509_data_node.null? if self.xmlSecDSigCtxSign(digital_signature_context, sign_node) < 0 raise SignatureFailure.new("signature failed!") end ptr = FFI::MemoryPointer.new(:pointer, 1) sizeptr = FFI::MemoryPointer.new(:pointer, 1) self.xmlDocDumpFormatMemory(doc, ptr, sizeptr, 0) strptr = ptr.read_pointer return strptr.null? ? nil : strptr.read_string ensure ptr.free if defined?(ptr) && ptr sizeptr.free if defined?(sizeptr) && sizeptr self.xmlFreeDoc(doc) if defined?(doc) && doc && !doc.null? self.xmlSecDSigCtxDestroy(digital_signature_context) if defined?(digital_signature_context) && digital_signature_context && !digital_signature_context.null? self.xmlFree(strptr) if defined?(strptr) && strptr && !strptr.null? end |
.xmlFree(ptr) ⇒ Object
244 245 246 |
# File 'lib/xml_sec.rb', line 244 def self.xmlFree(ptr) __xmlFree.call(ptr) end |
.xmlMalloc(size) ⇒ Object
240 241 242 |
# File 'lib/xml_sec.rb', line 240 def self.xmlMalloc(size) __xmlMalloc.call(size) end |