<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Konstantin Shemyak - Tech Notes</title><link>https://technotes.shemyak.com/</link><description>Findings with tags "network", "security" and "privacy"</description><atom:link href="https://technotes.shemyak.com/rss.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2021 &lt;a href="mailto:konstantin@shemyak.com"&gt;Konstantin Shemyak&lt;/a&gt; </copyright><lastBuildDate>Sat, 03 Apr 2021 16:33:05 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>XML Signatures and Python ElementTree</title><link>https://technotes.shemyak.com/posts/xml-signatures-and-python-elementtree/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;h3&gt;I just need to sign XML...&lt;/h3&gt;
&lt;p&gt;Python has a standard library module to handle XML, and there seems to be exactly one library for the signing part: &lt;code&gt;signxml&lt;/code&gt;.
So it should be straighforward:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;signxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;XMLVerifier&lt;/span&gt;

&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cert.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"key.pem"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Test/&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;XMLVerifier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Simple?&lt;/p&gt;
&lt;p&gt;But the receiver tells you that your signature does not verify?&lt;/p&gt;
&lt;p&gt;The solution code is at the &lt;a href="https://technotes.shemyak.com/posts/xml-signatures-and-python-elementtree/#tldr"&gt;end of the article&lt;/a&gt;. The rest explains what is happening.&lt;/p&gt;
&lt;p&gt;An optional parameter of the &lt;code&gt;sign()&lt;/code&gt; method specifies &lt;strong&gt;type of the XML signature&lt;/strong&gt;, which
can be &lt;em&gt;enveloped&lt;/em&gt;, &lt;em&gt;enveloping&lt;/em&gt;, or &lt;em&gt;detached&lt;/em&gt;. This article covers only the default
case of &lt;em&gt;enveloped&lt;/em&gt; signature.&lt;/p&gt;
&lt;h3&gt;...and send it forward&lt;/h3&gt;
&lt;p&gt;When you sign something, usually it is for the purpose of verifying the signature by someone else.
Unless that someone else has access to your Python object, we need to serialize the latter:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;data_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Sending&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;XMLVerifier&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_serialized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;And this is not simple any more, because verification of the serialized data fails:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="ss"&gt;"/path/to/python3.6/site-packages/signxml/__init__.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;729&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt;
    &lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signing_cert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;raw_signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signed_info_c14n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature_digest_method&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="ss"&gt;"/path/to/python3.6/site-packages/OpenSSL/crypto.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;2928&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt;
    &lt;span class="n"&gt;_raise_current_error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="ss"&gt;"/path/to/python3.6/site-packages/OpenSSL/_util.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;exception_from_error_queue&lt;/span&gt;
    &lt;span class="n"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;exception_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;OpenSSL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s1"&gt;'rsa routines'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'int_rsa_verify'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bad signature'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;During&lt;/span&gt; &lt;span class="n"&gt;handling&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;above&lt;/span&gt; &lt;span class="k"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;another&lt;/span&gt; &lt;span class="k"&gt;exception&lt;/span&gt; &lt;span class="n"&gt;occurred&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="k"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="ss"&gt;"1.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;XMLVerifier&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_serialized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="ss"&gt;"/path/to/python3.6/site-packages/signxml/__init__.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;735&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;verify&lt;/span&gt;
    &lt;span class="n"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;InvalidSignature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;"Signature verification failed: {}"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;signxml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvalidSignature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Signature&lt;/span&gt; &lt;span class="n"&gt;verification&lt;/span&gt; &lt;span class="n"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bad&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;So, did the serialization break the signature?
"When nothing helps, read the instructions". Documentation of &lt;code&gt;signxml&lt;/code&gt;
&lt;a href="https://signxml.readthedocs.io/en/latest/#signxml.XMLSigner"&gt;tells&lt;/a&gt; that
the return value of &lt;code&gt;sign()&lt;/code&gt; is an &lt;code&gt;lxml.etree.Element&lt;/code&gt; object, not an &lt;code&gt;xml.etree.ElementTree&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;Next try is the serialization with &lt;code&gt;lxml&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;signxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;XMLVerifier&lt;/span&gt;

&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cert.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"key.pem"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Test/&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sending the data...&lt;/span&gt;

&lt;span class="n"&gt;XMLVerifier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_serialized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;The moment of happiness, this works. Simple?&lt;/p&gt;
&lt;p&gt;Good if this works for you. But we are sending the serialized XML somewhere faraway and 
the receiver might first deserialize it, and verify the signature after that on a
deserialized version. (Which is not smart, but is probably out of your control.)
And do it with ElementTree.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;signxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;XMLVerifier&lt;/span&gt;

&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cert.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"key.pem"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Test/&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sending the data...&lt;/span&gt;

&lt;span class="n"&gt;data_parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_serialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;XMLVerifier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_parsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;And this fails with the same &lt;code&gt;InvalidSignature&lt;/code&gt;. Bump. Now reading the instructions does not help.&lt;/p&gt;
&lt;h3&gt;Debugging starts&lt;/h3&gt;
&lt;p&gt;We can check that the string representation of our &lt;strong&gt;signed&lt;/strong&gt; data "looks right" (although you never can be sure with the XML).
Compare it to &lt;code&gt;ElementTree.tostring(data_parsed)&lt;/code&gt; to note that they are not identical.
We do not know yet what is inside ElementTree object, but in its serialized string the signature will fail:&lt;/p&gt;
&lt;p&gt;Sent string:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;Test&amp;gt;&amp;lt;ds:Signature&lt;/span&gt; &lt;span class="na"&gt;xmlns:ds=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/09/xmldsig#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;ds:SignedInfo&amp;gt;&amp;lt;ds:CanonicalizationMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2006/12/xml-c14n11"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&amp;lt;ds:SignatureMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&amp;lt;ds:Reference&lt;/span&gt; &lt;span class="na"&gt;URI=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;ds:Transforms&amp;gt;&amp;lt;ds:Transform&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/09/xmldsig#enveloped-signature"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&amp;lt;ds:Transform&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2006/12/xml-c14n11"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&amp;lt;/ds:Transforms&amp;gt;&amp;lt;ds:DigestMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/04/xmlenc#sha256"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&amp;lt;ds:DigestValue&amp;gt;&lt;/span&gt;KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=&lt;span class="nt"&gt;&amp;lt;/ds:DigestValue&amp;gt;&lt;/span&gt;....
&lt;/pre&gt;


&lt;p&gt;De-serialized ElementTree object:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;Test&lt;/span&gt; &lt;span class="na"&gt;xmlns:ns0=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/09/xmldsig#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;ns0:Signature&amp;gt;&amp;lt;ns0:SignedInfo&amp;gt;&amp;lt;ns0:CanonicalizationMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2006/12/xml-c14n11"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;ns0:SignatureMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;ns0:Reference&lt;/span&gt; &lt;span class="na"&gt;URI=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;ns0:Transforms&amp;gt;&amp;lt;ns0:Transform&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/09/xmldsig#enveloped-signature"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;ns0:Transform&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2006/12/xml-c14n11"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;/ns0:Transforms&amp;gt;&amp;lt;ns0:DigestMethod&lt;/span&gt; &lt;span class="na"&gt;Algorithm=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2001/04/xmlenc#sha256"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&amp;lt;ns0:DigestValue&amp;gt;&lt;/span&gt;KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=&lt;span class="nt"&gt;&amp;lt;/ns0:DigestValue&amp;gt;&lt;/span&gt;...
&lt;/pre&gt;


&lt;p&gt;So far we see two problems in the string produced from the &lt;code&gt;ElementTree&lt;/code&gt; object:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Namespace name &lt;code&gt;ds&lt;/code&gt; has been changed to &lt;code&gt;ns0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Its declaration is not under the &lt;code&gt;&amp;lt;Signature&amp;gt;&lt;/code&gt; tag, but under the &lt;code&gt;&amp;lt;Test&amp;gt;&lt;/code&gt; tag.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;InvalidSignature&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;InvalidSignature&lt;/code&gt; exception we are getting is caused by the first problem.
&lt;code&gt;signxml&lt;/code&gt; first does &lt;a href="https://tools.ietf.org/html/rfc3275#section-3.2.2"&gt;signature validation&lt;/a&gt;,
where the signature value (read from the XML string in our case) is calculated over the
&lt;code&gt;&amp;lt;SignedInfo&amp;gt;&lt;/code&gt; XML element (&lt;em&gt;canonicalized&lt;/em&gt;, but we can skip this &lt;strong&gt;complicated&lt;/strong&gt; issue for now).
&lt;code&gt;&amp;lt;SignedInfo&amp;gt;&lt;/code&gt; has changed as &lt;code&gt;ds&lt;/code&gt; has been replaced by where-did-it-come-from &lt;code&gt;ns0&lt;/code&gt;, so the
signature does not match.&lt;/p&gt;
&lt;p&gt;The solution is &lt;a href="https://docs.python.org/3/library/xml.etree.elementtree.html#xml.etree.ElementTree.register_namespace"&gt;register_namespace(prefix, uri)&lt;/a&gt;
function of &lt;code&gt;ElementTree&lt;/code&gt;. Its documentation reads: 
&lt;em&gt;(...) Tags and attributes in this namespace will be serialized with the given prefix, if at all possible.&lt;/em&gt;
That's what we need (the author needs to understand why &lt;code&gt;ElementTree&lt;/code&gt; is not made to get this from our XML string).
The function must be called before verification, not necessarily before the parsing; as the documentation says,
&lt;em&gt;(...) any existing mapping for either the given prefix or the namespace URI will be removed.&lt;/em&gt;&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;signxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;XMLVerifier&lt;/span&gt;

&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cert.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"key.pem"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Test/&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sending the data...&lt;/span&gt;

&lt;span class="n"&gt;data_parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_serialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ds"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"http://www.w3.org/2000/09/xmldsig#"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;XMLVerifier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_parsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Now if we inspect &lt;code&gt;ET.tostring(data_parsed)&lt;/code&gt;, we'll see the correct &lt;code&gt;ds&lt;/code&gt; namespace in use.
The result?&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;Traceback&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;most&lt;/span&gt; &lt;span class="nv"&gt;recent&lt;/span&gt; &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nl"&gt;last&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
  &lt;span class="nv"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.py&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;, &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;, &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nv"&gt;XMLVerifier&lt;/span&gt;&lt;span class="ss"&gt;()&lt;/span&gt;.&lt;span class="nv"&gt;verify&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data_parsed&lt;/span&gt;, &lt;span class="nv"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;cert&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/path/to/python3.6/site-packages/signxml/__init__.py&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;, &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;765&lt;/span&gt;, &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;verify&lt;/span&gt;
    &lt;span class="nv"&gt;raise&lt;/span&gt; &lt;span class="nv"&gt;InvalidDigest&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Digest mismatch for reference {}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;.&lt;span class="nv"&gt;format&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;len&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;verify_results&lt;/span&gt;&lt;span class="ss"&gt;)))&lt;/span&gt;
&lt;span class="nv"&gt;signxml&lt;/span&gt;.&lt;span class="nv"&gt;exceptions&lt;/span&gt;.&lt;span class="nv"&gt;InvalidDigest&lt;/span&gt;: &lt;span class="nv"&gt;Digest&lt;/span&gt; &lt;span class="nv"&gt;mismatch&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;reference&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/pre&gt;


&lt;h3&gt;InvalidDigest&lt;/h3&gt;
&lt;p&gt;Now &lt;code&gt;signxml&lt;/code&gt; has successfully verified &lt;code&gt;&amp;lt;SignatureValue&amp;gt;&lt;/code&gt; over the &lt;code&gt;&amp;lt;SignedInfo&amp;gt;&lt;/code&gt;
(in &lt;em&gt;canonicalized&lt;/em&gt; form, but again we may skip this topic for now).
The "digest mismatch", about which &lt;code&gt;signxml&lt;/code&gt; is complaining now, is between the calculated digest over the
&lt;strong&gt;original XML document&lt;/strong&gt; (in canonicalized form...) and the digest string read from the &lt;code&gt;&amp;lt;DigestValue&amp;gt;&lt;/code&gt;
element under the &lt;code&gt;&amp;lt;Signagure&amp;gt;&lt;/code&gt;. It is caused by the "Problem 2" mentioned above.
&lt;code&gt;DigestValue&lt;/code&gt; is &lt;code&gt;KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=&lt;/code&gt;,
and it was, in fact, made over the string &lt;code&gt;&amp;lt;Test&amp;gt;&amp;lt;/Test&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ echo -n '&lt;span class="nt"&gt;&amp;lt;Test&amp;gt;&amp;lt;/Test&amp;gt;&lt;/span&gt;' | openssl sha256 -binary | base64
KP3ncf09YSgkeTt+i4PR+W0AMvUTo7M8gu0z15piPMc=
&lt;/pre&gt;


&lt;p&gt;But in the deserialized ElementTree object the XML string became
&lt;code&gt;&amp;lt;Test xmlns:ds="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&amp;lt;/Test&amp;gt;&lt;/code&gt;, which of course produces a different SHA-256 digest.
It is possible to see (with a debugger) that &lt;code&gt;verify()&lt;/code&gt; tries to match the digest of &lt;strong&gt;this&lt;/strong&gt; string.&lt;/p&gt;
&lt;p&gt;Such modification of the original XML looks like result of some of &lt;em&gt;canonicalization&lt;/em&gt;
transforms, but I have not found it in the specs.
The &lt;a href="https://www.w3.org/TR/xml-c14n11/#Example-SETags"&gt;examples given&lt;/a&gt; show that the
namespace declarations are not moved out of the tag inside which they are used.&lt;/p&gt;
&lt;p&gt;If we want the receiver of our XML string to be able to parse it with ElementTree
and then to successfully verify, we have no other option but to sign exactly
such string. I.e. we must produce such argument for &lt;code&gt;sign()&lt;/code&gt; which, when canonicalized,
produces the string &lt;code&gt;&amp;lt;Test xmlns:ds="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&amp;lt;/Test&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Understanding how to do this requires knowledge about how ElementTree stores its XML objects.
What is important here is that it represents namespaces by string prefixes of the tags under them.
Because of this, if we only &lt;strong&gt;declare&lt;/strong&gt; a namespace, it will not be saved.
We must create some elements under this namespace &lt;strong&gt;and&lt;/strong&gt; call &lt;code&gt;register_namespace()&lt;/code&gt;.
Let's create element &lt;code&gt;ds:foo&lt;/code&gt;. To be valid XML, the string must represent just
one root XML element, so add an element &lt;code&gt;&amp;lt;wrapper&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;signxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;XMLVerifier&lt;/span&gt;

&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cert.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"key.pem"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ds"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"http://www.w3.org/2000/09/xmldsig#"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;wrapper&amp;gt;&amp;lt;ds:foo xmlns:ds=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/09/xmldsig#&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;/&amp;gt;&amp;lt;Test/&amp;gt;&amp;lt;/wrapper&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sending the data...&lt;/span&gt;

&lt;span class="n"&gt;data_parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_serialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;XMLVerifier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_parsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Now the &lt;code&gt;ds&lt;/code&gt; namespace is available in the ElementTree object passed to &lt;code&gt;sign()&lt;/code&gt;.
When &lt;code&gt;sign()&lt;/code&gt; is called, it performs &lt;strong&gt;canonicalization&lt;/strong&gt; which puts the namespace
declaration for &lt;code&gt;ds&lt;/code&gt; under the first tag in the document. Addition of the signature,
which brings in this namespace, already does not change anything inside our &lt;code&gt;&amp;lt;Test&amp;gt;&lt;/code&gt; element.&lt;/p&gt;
&lt;h3&gt;Almost Done&lt;/h3&gt;
&lt;p&gt;The signagure verifies, but we have added content to the XML we are signing - and
also signed it! 
&lt;code&gt;verify().signed_data&lt;/code&gt; will return the content with our additions.
Probably, software which signs things (even XML) with &lt;strong&gt;such&lt;/strong&gt; side effects
would not gain wide acceptance :-)&lt;/p&gt;
&lt;p&gt;This is solved - by luck or by intention - with the possibility provided by &lt;code&gt;signxml&lt;/code&gt;
to specify the location of the enveloped signature.
As the &lt;a href="https://signxml.readthedocs.io/en/latest/#signxml.XMLSigner"&gt;documentation&lt;/a&gt; says,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To specify the location of an enveloped signature within data, insert a 
&lt;signature id="placeholder"&gt;&lt;/signature&gt; element in data 
(where “ds” is the “http://www.w3.org/2000/09/xmldsig#” namespace). 
This element will be replaced by the generated signature, and excised when generating the digest.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Such insert will introduce the &lt;code&gt;ds&lt;/code&gt; namespace into the &lt;code&gt;xml_obj&lt;/code&gt;,
but no any new elements outside of the &lt;code&gt;&amp;lt;ds:Signature&amp;gt;&lt;/code&gt; element.
So we'll not add anything to the content which is signed.&lt;/p&gt;
&lt;p&gt;&lt;a name="tldr"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;lxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;etree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;signxml&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;XMLVerifier&lt;/span&gt;

&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rb"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"cert.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"key.pem"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_namespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ds"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"http://www.w3.org/2000/09/xmldsig#"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Test&amp;gt;&amp;lt;ds:Signature xmlns:ds=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;http://www.w3.org/2000/09/xmldsig#&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; Id=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;placeholder&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;&amp;lt;/ds:Signature&amp;gt;&amp;lt;/Test&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XMLSigner&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;xml_obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;data_serialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lxml_ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signed_xml_obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Sending the data...&lt;/span&gt;

&lt;span class="n"&gt;data_parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_serialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;XMLVerifier&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_parsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x509_cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Such signed serialized data can be also parsed by &lt;code&gt;lxml.etree&lt;/code&gt; and successfully verified.&lt;/p&gt;
&lt;p&gt;Do not forget that if the receiver is using ElementTree, they must call 
&lt;code&gt;ElementTree.register_namespace("ds", "http://www.w3.org/2000/09/xmldsig#")&lt;/code&gt; 
before calling &lt;code&gt;XMLSigner().verify()&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Afterword&lt;/h3&gt;
&lt;p&gt;After reading this post, you should have no doubts that 
&lt;a href="http://www.cs.auckland.ac.nz/~pgut001/pubs/xmlsec.txt"&gt;XML signing is broken&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;</description><category>Python</category><category>signature</category><category>XML</category><guid>https://technotes.shemyak.com/posts/xml-signatures-and-python-elementtree/</guid><pubDate>Sun, 16 Jun 2019 13:00:00 GMT</pubDate></item><item><title>Docker behind SSL intercepting proxy</title><link>https://technotes.shemyak.com/posts/docker-behind-ssl-proxy/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;h3&gt;Situation&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;You need to build a Docker image from a repository in the Internet.&lt;/li&gt;
&lt;li&gt;Your application running in the Docker container accesses an HTTPS server in the Internet.&lt;/li&gt;
&lt;li&gt;You are behind intercepting SSL proxy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The examples below are for Debian-based systems unless noted otherwise.&lt;/p&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;SSL intercepting proxy requires that the application:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sends HTTPS requests to the proxy (as opposed to the target host directly)&lt;/li&gt;
&lt;li&gt;Trusts the intercepting certificate.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These two actions are configured separately:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;For the former, one usually sets the environment variable &lt;code&gt;https_proxy&lt;/code&gt;.
HTTPS clients which read the environment are supposed to use it; others require
own specific configuration.&lt;/li&gt;
&lt;li&gt;For the latter, the trust can be configured
either "system-wide", or on the application basis. Being behind the intercepting
proxy you might want the system-wide configuration. &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Pulling images&lt;/h3&gt;
&lt;p&gt;Images are pulled by the Docker daemon.
The daemon is (normally) not aware of the environment of the shell you are using,
so the &lt;code&gt;$http_proxy&lt;/code&gt; in your environment, if set, will not have any effect. &lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ docker pull hello-world
Using default tag: latest
Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on &lt;span class="m"&gt;127&lt;/span&gt;.0.1.1:53: no such host
&lt;/pre&gt;


&lt;p&gt;We need to configure the daemon to use the proxy according to the
&lt;a href="https://docs.docker.com/config/daemon/systemd/#httphttps-proxy"&gt;manual&lt;/a&gt;
in &lt;code&gt;/etc/systemd/system/docker.service.d/http-proxy.conf&lt;/code&gt;: &lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[Service]&lt;/span&gt;
&lt;span class="na"&gt;Environment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"HTTPS_PROXY=https://proxy.example.com:443/" "NO_PROXY=localhost,127.0.0.1,docker-registry.somecorporation.com"&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;And restart the daemon:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ &lt;span class="nv"&gt;sudo&lt;/span&gt; &lt;span class="nv"&gt;systemctl&lt;/span&gt; &lt;span class="nv"&gt;daemon&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;reload&lt;/span&gt;
$ &lt;span class="nv"&gt;sudo&lt;/span&gt; &lt;span class="nv"&gt;systemctl&lt;/span&gt; &lt;span class="nv"&gt;restart&lt;/span&gt; &lt;span class="nv"&gt;docker&lt;/span&gt;
$ &lt;span class="nv"&gt;systemctl&lt;/span&gt; &lt;span class="k"&gt;show&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;property&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;Environment&lt;/span&gt; &lt;span class="nv"&gt;docker&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Docker daemon uses the proxy, but does not yet trust the intercepting certificate:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ docker pull hello-world
&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;
docker: error pulling image configuration: Get https://&lt;span class="o"&gt;[&lt;/span&gt;...&lt;span class="o"&gt;]&lt;/span&gt;: x509: certificate signed by unknown authority.
&lt;/pre&gt;


&lt;p&gt;You need to obtain your intercepting proxy certificate and add it to the system storage.
(Q: How to add it to docker only, without root access?):&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ sudo cp my-intercepting-cert.crt /usr/local/share/ca-certificates/
$ sudo update-ca-certificates 
Updating certificates in /etc/ssl/certs...
&lt;span class="m"&gt;0&lt;/span&gt; added, &lt;span class="m"&gt;0&lt;/span&gt; removed&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;.
Running hooks in /etc/ca-certificates/update.d...

&lt;span class="k"&gt;done&lt;/span&gt;.
&lt;span class="k"&gt;done&lt;/span&gt;.
&lt;/pre&gt;


&lt;p&gt;Or on RedHat-based systems:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;cp&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;intercepting&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;crt&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;pki&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;trust&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;source&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;anchors&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="k"&gt;update&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;trust&lt;/span&gt; &lt;span class="k"&gt;extract&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Now do &lt;code&gt;sudo systemctl restart docker&lt;/code&gt; and you should be able to pull images.&lt;/p&gt;
&lt;h3&gt;Running containers&lt;/h3&gt;
&lt;p&gt;The steps above affected the &lt;strong&gt;daemon&lt;/strong&gt; only. If your &lt;strong&gt;container&lt;/strong&gt; needs
to access the Internet
behind the proxy, you want your dockerized application to be aware of it.
While the build is run by the docker daemon, the daemon is not instructed to make
"proxy-aware" images; in the end, you can build non-proxified images if you need to.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.docker.com/network/proxy/"&gt;Docker documentation&lt;/a&gt; describes
three ways to pass environment variables to the image.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In &lt;code&gt;Dockerfile&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;ENV&lt;/span&gt; &lt;span class="n"&gt;http_proxy&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="n"&gt;ENV&lt;/span&gt; &lt;span class="n"&gt;https_proxy&lt;/span&gt; &lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;443&lt;/span&gt;
&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;In the build command line:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxified&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
            &lt;span class="c1"&gt;--build-arg http_proxy="http://proxy.example.com:80" \&lt;/span&gt;
            &lt;span class="c1"&gt;--build-arg https_proxy="https://proxy.example.com:443" \&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;
&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;Configuring the Docker &lt;strong&gt;client&lt;/strong&gt; (since Docker 17.07):&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Add the snip to &lt;code&gt;~/.docker/config.json&lt;/code&gt; in the user's home directory:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt;
 &lt;span class="ss"&gt;"proxies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="err"&gt;{&lt;/span&gt;
   &lt;span class="ss"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="err"&gt;{&lt;/span&gt;
     &lt;span class="ss"&gt;"httpsProxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;"http://127.0.0.1:80"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="ss"&gt;"noProxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;"*.test.example.com,.example2.com"&lt;/span&gt;
   &lt;span class="err"&gt;}&lt;/span&gt;
 &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Your image can contain programs which require proxy to operate, but obtain it from
somewhere else than the environment.
Configuration for such programs must be provided on the individual basis.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example: if you want to be able to install software with "apt" in your Debian-based image:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;RUN&lt;/span&gt; &lt;span class="nt"&gt;echo&lt;/span&gt; &lt;span class="err"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'Acquire::http::proxy "http://proxy.example.com:80/";\n\&lt;/span&gt;
&lt;span class="s1"&gt;   Acquire::https::proxy "https://proxy.example.com:443/";'&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;
   &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;apt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;d&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;00proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;conf&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; the application in the container needs to be able to resolve the
given proxy domain name.
A restrictive environment behind SSL proxy may not provide you with a 
general DNS access, in which case you'd have to use the IP address of the proxy.&lt;/p&gt;
&lt;p&gt;Again, for SSL interception, in addition to the proxy itself the intercepting
certificate must be configured as trusted. A snippet from &lt;code&gt;Dockerfile&lt;/code&gt; for a
"system-wide" configuration in a Debian-based system:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;containing&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;intercepting&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cert&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;certificates&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt; &lt;span class="k"&gt;update&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;certificates&lt;/span&gt;
&lt;/pre&gt;


&lt;h4&gt;At the runtime&lt;/h4&gt;
&lt;p&gt;The environment variable can be passed individually per container:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ docker run -e &lt;span class="s2"&gt;"https_proxy=http://proxy.example.com:80"&lt;/span&gt; my-image
&lt;/pre&gt;


&lt;h3&gt;Afterword&lt;/h3&gt;
&lt;p&gt;SSL intercepting proxies &lt;a href="https://zakird.com/papers/https_interception.pdf"&gt;&lt;strong&gt;reduce&lt;/strong&gt; the connection security in many cases&lt;/a&gt;.
Additionally to that, an application which performs certificate check but is not
configured to trust the intercepting certificate will show a security warning (or just silently fail);
as not every user is capable of properly configuring the trust in every case - 
in the end, users just need the application to work - 
many will ignore the warning and/or "set the insecure mode" if possible.
In this way, the SSL intercepting proxy
&lt;em&gt;teaches to ignore security warnings&lt;/em&gt;, exactly rendering users vulnerable to attacks.&lt;/p&gt;
&lt;h3&gt;Acknowledgements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://crondev.com/running-docker-behind-proxy/"&gt;crondev&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</description><category>docker</category><guid>https://technotes.shemyak.com/posts/docker-behind-ssl-proxy/</guid><pubDate>Thu, 07 Jun 2018 21:00:00 GMT</pubDate></item><item><title>Minimal openssl.cnf</title><link>https://technotes.shemyak.com/posts/min-openssl-cnf/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Need to create X.509 certificate chain?
This post explains how to do it with OpenSSL commands and gives minimal
working examples of the configuration for typical test/demo cases.&lt;/p&gt;
&lt;h3&gt;A config file is needed&lt;/h3&gt;
&lt;p&gt;OpenSSL commands (that is, the ones invoked from the command line) are mostly
controlled by their options. But in order to issue X.509 certificates or CSRs
OpenSSL needs a configuration file.
This file may contain no useful information, but is still required.
This post gives and explains minimal configuration files for OpenSSL commands
used for certificate generation: &lt;code&gt;x509&lt;/code&gt;, &lt;code&gt;req&lt;/code&gt; and &lt;code&gt;ca&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;OpenSSL installation should supply a default configuration file,
often called &lt;code&gt;openssl.cnf&lt;/code&gt;.
Below, we'll use expressions &lt;code&gt;openssl.cnf&lt;/code&gt; and "OpenSSL configuration file"
interchangeably.&lt;/p&gt;
&lt;p&gt;The topic of this post is the &lt;em&gt;minimal configuration file&lt;/em&gt;.
Sometimes the command will need more parameters than such minimum
contains; in these cases they will be provided via command-line options.
These options are kept at minimum too, so in real applications
you'd likely need to pass more parameters - either via the config file
or through the options.&lt;/p&gt;
&lt;p&gt;Let's proceed to creating the certificate chain, i.e. one CA certificate and
one "leaf" certificate issued by the CA.&lt;/p&gt;
&lt;h3&gt;Generate the private key&lt;/h3&gt;
&lt;p&gt;Generation of the private key can be included in some of the commands below,
but for clarity let's create a private key with a separate command.
To sound modern, pick an elliptic curve
from &lt;code&gt;openssl ecparam -list_curves&lt;/code&gt; with the name which sounds cute,
such as &lt;code&gt;secp521r1&lt;/code&gt;
(on a serious note - selection of the elliptic curve is out of scope
of this post):&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ openssl ecparam -genkey -name secp521r1 -out privkey.pem
&lt;/pre&gt;


&lt;p&gt;We'll use this same key for all certificates which appear later;
of course such practice is acceptable only for demonstration or testing.&lt;/p&gt;
&lt;h3&gt;Create a self-signed CA certificate&lt;/h3&gt;
&lt;p&gt;This command needs a config file. Unless one is provided, OpenSSL will
use the default, which may not contain what you want.
There are two ways to provide a custom config:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-config&lt;/code&gt; option&lt;/li&gt;
&lt;li&gt;&lt;code&gt;OPENSSL_CONF&lt;/code&gt; environment variable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We'll use the first way to show the config file in a
more explicit manner.&lt;/p&gt;
&lt;p&gt;There are two OpenSSL subcommands which can be used to create a self-signed
CA certificate: &lt;code&gt;req -x509&lt;/code&gt; and &lt;code&gt;ca&lt;/code&gt;. Examples of both are below.&lt;/p&gt;
&lt;h4&gt;Using "req -x509" command&lt;/h4&gt;
&lt;p&gt;The minimum config file for this command is:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[ req ]&lt;/span&gt;
&lt;span class="na"&gt;distinguished_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;req_dn&lt;/span&gt;

&lt;span class="k"&gt;[ req_dn ]&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;Call this file &lt;code&gt;openssl-min-req.cnf&lt;/code&gt;.
With it, you can issue self-signed certificates:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ openssl req -new -x509 -nodes -key privkey.pem -config openssl-min-req.cnf -subj &lt;span class="s2"&gt;"/CN=My self-signed CA certificate"&lt;/span&gt; -out ca.pem
&lt;/pre&gt;


&lt;p&gt;If we do not specify the version explicitly or request any of
&lt;strong&gt;X.509v3 extensions&lt;/strong&gt;, then OpenSSL sets the version the certificate
to &lt;strong&gt;1&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Check with &lt;code&gt;openssl x509 -purpose -in ca.pem&lt;/code&gt; and
observe that various "CA" purposes come with &lt;code&gt;Yes (WARNING code=3)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Surprisingly, for a V3 certificate, there seems to be no clear indication
whether it is a CA certificate or not. Two extensions claim properties
related to CA functionality. OpenSSL's C API function &lt;code&gt;X509_check_ca&lt;/code&gt;
returns non-zero when the certificate either has &lt;code&gt;CA:TRUE&lt;/code&gt; in
&lt;code&gt;basicConstraints&lt;/code&gt; extension, or &lt;code&gt;keyCertSign&lt;/code&gt; in &lt;code&gt;keyUsage&lt;/code&gt; extension.
Other software may follow other rules (for example, require &lt;code&gt;CA:TRUE&lt;/code&gt;).
To satisfy OpenSSL's interpretation, the minimal &lt;code&gt;openssl.cnf&lt;/code&gt; can be
like this:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[ req ]&lt;/span&gt;
&lt;span class="na"&gt;distinguished_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;req_dn&lt;/span&gt;
&lt;span class="na"&gt;x509_extensions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;v3_ext&lt;/span&gt;

&lt;span class="k"&gt;[ req_dn ]&lt;/span&gt;

&lt;span class="k"&gt;[ v3_ext ]&lt;/span&gt;
&lt;span class="na"&gt;basicConstraints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;CA:true&lt;/span&gt;
&lt;/pre&gt;


&lt;h4&gt;Using "ca -selfsign" command&lt;/h4&gt;
&lt;p&gt;Below is the minimal &lt;code&gt;openssl-ca.cnf&lt;/code&gt; which would do the job.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;[ ca ]&lt;/span&gt;
&lt;span class="na"&gt;default_ca&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;CA_default&lt;/span&gt;

&lt;span class="k"&gt;[ CA_default ]&lt;/span&gt;
&lt;span class="na"&gt;database&lt;/span&gt;        &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;index.txt&lt;/span&gt;
&lt;span class="na"&gt;serial&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;serial.txt&lt;/span&gt;
&lt;span class="na"&gt;policy&lt;/span&gt;          &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;policy_default&lt;/span&gt;

&lt;span class="k"&gt;[ policy_default ]&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;For this command to succeed, three files referenced above must be created:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ touch index.txt index.txt.attr
$ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'01'&lt;/span&gt; &amp;gt; serial.txt
&lt;/pre&gt;


&lt;p&gt;When done, self-signed CA certificate is created with this command:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ openssl ca -config openssl-ca.cnf -selfsign -in csr.pem -keyfile privkey.pem -md default -out ca.pem -outdir . -days &lt;span class="m"&gt;365&lt;/span&gt; -batch
&lt;/pre&gt;


&lt;p&gt;Now we have the CA certificate. Next, create leaf certificates signed by it.&lt;/p&gt;
&lt;h3&gt;Create a certificate signed by your new CA&lt;/h3&gt;
&lt;h4&gt;Create a CSR&lt;/h4&gt;
&lt;p&gt;A CSR (Certificate Signing Request) is made with &lt;code&gt;req&lt;/code&gt; command.
For it, the "minimum request openssl.cnf" is sufficient:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ openssl req -new -config openssl-min-req.cnf -key privkey.pem -nodes -subj &lt;span class="s2"&gt;"/CN=Non-CA example certificate"&lt;/span&gt; -out csr.pem
&lt;/pre&gt;


&lt;p&gt;Inspect the CSR with &lt;code&gt;openssl req -text -noout -in csr.pem&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Having a CSR, the corresponding certificate can be issued using either &lt;code&gt;x509&lt;/code&gt;
or &lt;code&gt;ca&lt;/code&gt; commands. Below are examples for both.&lt;/p&gt;
&lt;h4&gt;Sign the CSR using "x509 -req" command&lt;/h4&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ openssl x509 -req -in csr.pem -CA ca.pem -CAkey privkey.pem -CAcreateserial -out cert.pem
&lt;/pre&gt;


&lt;p&gt;The &lt;code&gt;x509&lt;/code&gt; command seems to have no option &lt;code&gt;-config&lt;/code&gt;, but it honors the
environment variable &lt;code&gt;OPENSSL_CONF&lt;/code&gt;. If the file is not readable, OpenSSL prints&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;WARNING&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/usr/lib/ssl/&lt;/span&gt;&lt;span class="n"&gt;openssl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cnf&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;and continues. For the example above, config file is not needed;
and if it is not needed, you should &lt;strong&gt;not&lt;/strong&gt; use it, because it may bring in
items which you do not want. It looks like the way to "disable" config file
processing is to set &lt;code&gt;OPENSSL_CONF=some_nonexisting_file&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Sign the CSR using "ca" command&lt;/h4&gt;
&lt;p&gt;Previously mentioned &lt;code&gt;openssl-ca.cnf&lt;/code&gt; works also for this case, and cannot
be reduced.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;$ openssl ca -config openssl-ca.cnf -cert ca.pem -keyfile privkey.pem -in csr.pem -out cert.pem -outdir . -md default -days &lt;span class="m"&gt;365&lt;/span&gt; -batch
&lt;/pre&gt;


&lt;p&gt;By default the &lt;code&gt;ca&lt;/code&gt; command does not copy the X.509v3 extensions from the
CSR (the ones specified in &lt;code&gt;x509_extensions&lt;/code&gt; section of the &lt;code&gt;[ req ]&lt;/code&gt; part
in our example &lt;code&gt;openssl-min-req.cnf&lt;/code&gt;) to the signed certificate.
To do so, add &lt;code&gt;copy_extensions = copy&lt;/code&gt; line to the CA section
(&lt;code&gt;[ CA_default ]&lt;/code&gt; in our example &lt;code&gt;openssl-ca.cnf&lt;/code&gt;).
Alternatively, the CA may add own extensions when signing a CSR -
for example, set &lt;code&gt;CA:FALSE&lt;/code&gt;.
These should be listed in the section with the name given by the variable
&lt;code&gt;x509_extensions&lt;/code&gt; in the &lt;code&gt;[ CA_default ]&lt;/code&gt; section.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;To create certificate chains with OpenSSL, a configuration file is needed.&lt;/li&gt;
&lt;li&gt;OpenSSL will use the default config file unless you provide another one
  via command-line option or an environment variable.&lt;ul&gt;
&lt;li&gt;Except that &lt;code&gt;x509 -req&lt;/code&gt; is missing the option.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;While the default may work for some cases, if you need any control over
  your certificates, you'll need to create the config file.&lt;/li&gt;
&lt;li&gt;You get more control over the content of your certificates when starting
  with the bare minimum than with the default.
  The minimal examples are provided in this post.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</description><category>openssl</category><category>x.509</category><guid>https://technotes.shemyak.com/posts/min-openssl-cnf/</guid><pubDate>Sat, 29 Apr 2017 17:00:00 GMT</pubDate></item><item><title>OpenSSL PKCS7 verification and certificate "Extended Key Usage" extension</title><link>https://technotes.shemyak.com/posts/smimesign-extended-key-usage-extension-for-openssl-pkcs7-verification/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;h3&gt;Problem&lt;/h3&gt;
&lt;p&gt;You verify a signature of &lt;strong&gt;PKCS#7&lt;/strong&gt; structure with OpenSSL and get error&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  &lt;span class="n"&gt;unsupported&lt;/span&gt; &lt;span class="n"&gt;certificate&lt;/span&gt; &lt;span class="n"&gt;purpose&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;This post explains the reason for this error and ways to proceed.&lt;/p&gt;
&lt;h3&gt;Background&lt;/h3&gt;
&lt;p&gt;By "verify a signature", one probably means that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The signature itself (e.g. an RSA block) taken over the corresponding
   data (or its digest) validates against the &lt;strong&gt;signing certificate&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Two sets of certificates are available, which we'd call
   "&lt;strong&gt;trusted certificates&lt;/strong&gt;" and "&lt;strong&gt;chaining certificates&lt;/strong&gt;".
   A chain from the &lt;strong&gt;signing certificate&lt;/strong&gt; up to at
   least one of the &lt;strong&gt;trusted certificates&lt;/strong&gt; can be built with the
   &lt;strong&gt;chaining certificates&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;All certificates in this chain have "acceptable" X.509v3 extensions.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first requirement is clear.&lt;/p&gt;
&lt;p&gt;The second one is clear when the sets are defined.
OpenSSL API requires them to be passed as parameters for the
verification.&lt;/p&gt;
&lt;p&gt;The last requirement relies on X.509v3 extensions, which are 
a &lt;a href="https://cyberside.net.ee/docs/T2a_X509_Certs.pdf"&gt;terrible mess&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It's hard to provide a non-messy solution for a messy specification.
Section &lt;code&gt;CERTIFICATE EXTENSIONS&lt;/code&gt; in the OpenSSL manual for &lt;code&gt;x509&lt;/code&gt;
subcommand has this passage:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;The&lt;/span&gt; &lt;span class="nv"&gt;actual&lt;/span&gt; &lt;span class="nv"&gt;checks&lt;/span&gt; &lt;span class="nv"&gt;done&lt;/span&gt; &lt;span class="nv"&gt;are&lt;/span&gt; &lt;span class="nv"&gt;rather&lt;/span&gt; &lt;span class="nv"&gt;complex&lt;/span&gt; &lt;span class="nv"&gt;and&lt;/span&gt; &lt;span class="k"&gt;include&lt;/span&gt; &lt;span class="nv"&gt;various&lt;/span&gt; &lt;span class="nv"&gt;hacks&lt;/span&gt; &lt;span class="nv"&gt;and&lt;/span&gt;
&lt;span class="nv"&gt;workarounds&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;handle&lt;/span&gt; &lt;span class="nv"&gt;broken&lt;/span&gt; &lt;span class="nv"&gt;certificates&lt;/span&gt; &lt;span class="nv"&gt;and&lt;/span&gt; &lt;span class="nv"&gt;software&lt;/span&gt;.
&lt;/pre&gt;


&lt;p&gt;It looks like PKCS7 verification fell victim of these "hacks and workarounds".&lt;/p&gt;
&lt;h3&gt;OpenSSL certificate verification and X.509v3 extensions&lt;/h3&gt;
&lt;p&gt;Before getting to the topic (verifying PKCS#7 structures), look at
how OpenSSL verifies &lt;strong&gt;certificates&lt;/strong&gt;. Both command-line &lt;code&gt;openssl verify&lt;/code&gt;
and C API &lt;code&gt;X509_verify_cert()&lt;/code&gt; have a notion of &lt;strong&gt;purpose&lt;/strong&gt;, explained
in the section &lt;code&gt;CERTIFICATE EXTENSIONS&lt;/code&gt; of &lt;code&gt;man x509&lt;/code&gt;.
This notion seems to be particular to OpenSSL.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If the &lt;strong&gt;purpose&lt;/strong&gt; is not specified, then OpenSSL does not check the
  certificate extensions at all.&lt;/li&gt;
&lt;li&gt;Otherwise, for each &lt;strong&gt;purpose&lt;/strong&gt;, OpenSSL allows certain combinations
  of the extensions. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The correspondence between OpenSSL's &lt;strong&gt;purpose&lt;/strong&gt; and X.509v3 extensions
is nothing like one-to-one.
For example, purpose &lt;code&gt;S/MIME Signing&lt;/code&gt; (or in short variant &lt;code&gt;smimesign&lt;/code&gt;)
requires that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;"Common S/MIME Client Tests" pass (description of how they translate
   to X.509v3 extension takes a long paragraph in &lt;code&gt;man x509&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Either &lt;code&gt;KeyUsage&lt;/code&gt; extension is &lt;strong&gt;not present&lt;/strong&gt;, or it is present and
   contains at least one of &lt;code&gt;digigalSignature&lt;/code&gt; and &lt;code&gt;nonRepudiation&lt;/code&gt; flags.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For another example, there seems to be no OpenSSL command-line option
for &lt;code&gt;verify&lt;/code&gt; to require presense of Extended Key Usage bits like
&lt;code&gt;codeSigning&lt;/code&gt;.
For that, one must use C API to separately check every extension bit. &lt;/p&gt;
&lt;p&gt;So far, this sounds about as logical as it could be
to somehow handle The Terrible Mess of X.509v3 extensions.
OpenSSL CLI seems to have made an attempt to compose some "frequently used
combinations" of the extensions and call them with own term "purpose".&lt;/p&gt;
&lt;h3&gt;OpenSSL PKCS#7 verification and X.509v3 extensions&lt;/h3&gt;
&lt;p&gt;By reason unknown yet to the author, OpenSSL uses a &lt;em&gt;different&lt;/em&gt; strategy
when verifying PKCS#7.&lt;/p&gt;
&lt;h4&gt;Command-line&lt;/h4&gt;
&lt;p&gt;There are two command-line utilities which can do that:
&lt;code&gt;openssl smime -verify&lt;/code&gt; and &lt;code&gt;openssl cms -verify&lt;/code&gt; 
(S/MIME and CMS are both PKCS#7).
Both accept &lt;code&gt;-purpose&lt;/code&gt; option, which according to manual pages
has the same meaning as for certificate verification.
&lt;strong&gt;But it does not.&lt;/strong&gt; These are the differences:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If no &lt;code&gt;-purpose&lt;/code&gt; option is passed, both commands behave as though
   they received &lt;code&gt;-purpose smimesign&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It is possible to disable this &lt;code&gt;smimesign&lt;/code&gt; purpose checking by passing
   &lt;code&gt;-purpose any&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;C API&lt;/h4&gt;
&lt;p&gt;On the C API side, one is supposed to use &lt;code&gt;PKCS7_verify()&lt;/code&gt; for PKCS#7
verification. This function also behaves as though it verifies with
&lt;code&gt;smimesign&lt;/code&gt; purpose. 
(see setting &lt;code&gt;X509_PURPOSE_SMIME_SIGN&lt;/code&gt; in &lt;code&gt;pk7_doit.c:919&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Similarly as with the command-line, it is possible to disable checking
the extensions, although with more typing.&lt;/p&gt;
&lt;p&gt;In the C API, the verification "purpose" is a property of &lt;code&gt;X509_STORE&lt;/code&gt;,
passed to &lt;code&gt;PKCS7_verify()&lt;/code&gt;, which plays the role of the 
&lt;strong&gt;trusted certificate set&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Side note: manipulation of the parameters directly
on the store was added only to OpenSSL 1.1.0 
with &lt;code&gt;X509_STORE_get0_param(X509_STORE *store)&lt;/code&gt;.
In earlier versions, an &lt;code&gt;X509_STORE_CTX&lt;/code&gt; must have been created from
the store and parameters manipulates with &lt;code&gt;X509_STORE_CTX_get0_param()&lt;/code&gt;.
BTW support for OpenSSL v1.0.1 has ended just on the day of this writing.&lt;/p&gt;
&lt;h4&gt;Possible reasoning&lt;/h4&gt;
&lt;p&gt;One might imagine reasoning like this: for &lt;code&gt;openssl smime&lt;/code&gt;, &lt;code&gt;smimesign&lt;/code&gt; is
kind of "default purpose" and thus is implicitly required; and
&lt;code&gt;openssl cms&lt;/code&gt; is in fact an attempt to rewrite &lt;code&gt;openssl smime&lt;/code&gt;, thus
behaving in the same way.&lt;/p&gt;
&lt;p&gt;Such behavior is fine for S/MIME, and is not what you would expect for
anything else packed into PKCS#7.&lt;/p&gt;
&lt;p&gt;Translating from OpenSSL's "purpose" to X.509v3 extensions, verification
fails unless your &lt;strong&gt;signing certificate&lt;/strong&gt; satisfies the two conditions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;If&lt;/strong&gt; the &lt;code&gt;Key Usage&lt;/code&gt; extension is present, &lt;strong&gt;then&lt;/strong&gt; it must include
   the &lt;code&gt;digitalSignature&lt;/code&gt; bit or the &lt;code&gt;nonRepudiation&lt;/code&gt; bit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If&lt;/strong&gt; the &lt;code&gt;Extended Key Usage&lt;/code&gt; extension is present, &lt;strong&gt;then&lt;/strong&gt; it
   must include &lt;code&gt;email protection&lt;/code&gt; OID.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In fact, the first condition is "reasonable": RFC5280 states in 
&lt;a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.3"&gt;section "Key Usage"&lt;/a&gt;
that&lt;/p&gt;
&lt;p&gt;For example, when an RSA key should be used only to verify signatures on
   objects other than public key certificates and CRLs, the
   digitalSignature and/or nonRepudiation bits would be asserted.&lt;/p&gt;
&lt;p&gt;PKCS#7 qualifies as "object other than public key certificates and CRLs".
But the second condition is not relevant for anything else than S/MIME.
(Of course, in the end it is your certificate practice policy which
determines, what is accepted and what not; the above is just "common sense").&lt;/p&gt;
&lt;h3&gt;Demo&lt;/h3&gt;
&lt;h4&gt;Prepare the files&lt;/h4&gt;
&lt;p&gt;Create a chain of certificates: self-signed "&lt;strong&gt;root&lt;/strong&gt;",
then an "&lt;strong&gt;intermediate&lt;/strong&gt;" signed by the root,
then a "&lt;strong&gt;signing&lt;/strong&gt;" signed by the intermediate.
Add some &lt;code&gt;extendedKeyUsage&lt;/code&gt; extension to the &lt;strong&gt;signing&lt;/strong&gt;, but do not add &lt;code&gt;emailProtection&lt;/code&gt;.
For example, add &lt;code&gt;codeSigning&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Create appropriate OpenSSL config files, as explained in
&lt;a href="https://technotes.shemyak.com/posts/min-openssl-cnf"&gt;"minimum openssl.cnf" post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Create requests for all the three:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  $ openssl req -config openssl-CA.cnf -new -x509 -nodes -outform pem -out root.pem -keyout root-key.pem
  $ openssl req -config openssl-CA.cnf -new -nodes -out intermediate.csr -keyout intermediate-key.pem
  $ openssl req -config openssl-signing.cnf -new -nodes -outform pem -out signing.csr -keyout signing-key.pem
&lt;/pre&gt;


&lt;p&gt;Sign the &lt;strong&gt;intermediate&lt;/strong&gt; and the &lt;strong&gt;signing&lt;/strong&gt; certificates:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  $ mkdir -p demoCA/newcerts
  $ touch demoCA/index.txt
  $ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'01'&lt;/span&gt; &amp;gt; demoCA/serial
  $ openssl ca -config openssl-CA.cnf -in intermediate.csr -out intermediate.pem -keyfile root-key.pem -cert root.pem
  $ openssl ca -config openssl-signing.cnf -in signing.csr -out signing.pem -keyfile intermediate-key.pem -cert intermediate.pem
&lt;/pre&gt;


&lt;p&gt;Create some PKCS7 structure, signed with the &lt;strong&gt;signing&lt;/strong&gt; certificate. 
The &lt;strong&gt;chain certificates&lt;/strong&gt; must be provided during the verification, or
embedded into the signature. Let's embed the intermediate certificate.
(If there had been more than one certificate in the chain, they would
need to be simply placed in one &lt;code&gt;.pem&lt;/code&gt; file):&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  $ &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Hello, world!'&lt;/span&gt; &amp;gt; data.txt
  $ openssl smime -sign -in data.txt -inkey signing-crlsign-key.pem -signer signing-crlsign.pem -certfile intermediate.pem -nodetach &amp;gt; signed-crlsign.pkcs7
&lt;/pre&gt;


&lt;p&gt;We have everything ready for verifying.&lt;/p&gt;
&lt;h4&gt;Verification with command-line OpenSSL tools&lt;/h4&gt;
&lt;p&gt;Attempt to verify it:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  $ openssl smime -verify -CAfile root.pem -in signed-crlsign.pkcs7 -out /dev/null -signer signing-crlsign.pem 
  Verification failure
  &lt;span class="m"&gt;139944505955992&lt;/span&gt;:error:21075075:PKCS7 routines:PKCS7_verify:certificate verify error:pk7_smime.c:336:Verify error:unsupported certificate purpose
&lt;/pre&gt;


&lt;p&gt;Attempt to verify, skipping extension checks:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  $ openssl smime -verify -CAfile root.pem -in signed-crlsign.pkcs7 -out /dev/null -signer signing-crlsign.pem -purpose any
  Verification successful
&lt;/pre&gt;


&lt;p&gt;Attempt to verify it, specifying the OpenSSL "purpose" which the signing certificate satisfies:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  $ openssl smime -verify -CAfile root.pem -in signed-crlsign.pkcs7 -out /dev/null -signer signing-crlsign.pem -purpose crlsign
  Verification successful
&lt;/pre&gt;


&lt;h4&gt;Verification with the C OpenSSL API&lt;/h4&gt;
&lt;p&gt;The code below is "demo", any real application would have at least to
check return codes of all system calls and free any allocated resources.
But it shows how the verification of PKCS#7 structure (unexpectedly)
fails, and succeeds after setting the "purpose" which the signing
certificate satisfies:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fcntl.h&amp;gt;              /* open() */&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;

    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/bio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/err.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/ssl.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/pkcs7.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/safestack.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/x509.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/x509v3.h&amp;gt;     /* X509_PURPOSE_ANY */&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;
    &lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;openssl/x509_vfy.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;

    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;X509_STORE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;trusted_store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;X509_STORE_CTX&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;STACK_OF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X509&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;cert_chain&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;X509&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;intermediate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;signing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;BIO&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;X509_VERIFY_PARAM&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;verify_params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;PKCS7&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;p7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kt"&gt;FILE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="n"&gt;SSL_library_init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;SSL_load_error_strings&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="n"&gt;fd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"signed-ext-no-smimesign.pkcs7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;O_RDONLY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BIO_new_fd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BIO_NOCLOSE&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;p7&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SMIME_read_PKCS7&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;cert_chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sk_X509_new_null&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"root.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PEM_read_X509&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;sk_X509_push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cert_chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"intermediate.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;intermediate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PEM_read_X509&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;sk_X509_push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cert_chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;intermediate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;trusted_store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X509_STORE_new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;X509_STORE_add_cert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trusted_store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;fp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fopen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"signing-ext-no-smimesign.pem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;signing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PEM_read_X509&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PKCS7_verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cert_chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trusted_store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Verification without specifying params: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"failure"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="cm"&gt;/* Now set a suitable OpenSSL's "purpose", or disable its checking.&lt;/span&gt;
&lt;span class="cm"&gt;       * Note: since OpenSSL 1.1.0, we'd not need `ctx`, but could just use:&lt;/span&gt;
&lt;span class="cm"&gt;       * verify_params = X509_STORE_get0_param(trusted_store); */&lt;/span&gt;

      &lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X509_STORE_CTX_new&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="n"&gt;X509_STORE_CTX_init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trusted_store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cert_chain&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;verify_params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X509_STORE_CTX_get0_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;purpose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X509_PURPOSE_get_by_sname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"crlsign"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="cm"&gt;/* Or: purpose = X509_PURPOSE_ANY */&lt;/span&gt;
      &lt;span class="n"&gt;X509_VERIFY_PARAM_set_purpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;verify_params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;X509_STORE_set1_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;trusted_store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;verify_params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PKCS7_verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cert_chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trusted_store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Verification with 'crlsign' purpose: %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"failure"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;If our policy requires &lt;code&gt;crlSign&lt;/code&gt; Key Usage, then we can
use this example code. What if the policy needs some extension
combination for which there is no suitable OpenSSL "purpose" - for example,
&lt;code&gt;CodeSigning&lt;/code&gt; Extended Key Usage? In that case it would not be possible
to do it with just one call to &lt;code&gt;PKCS7_verify&lt;/code&gt;, but the extensions
need to be checked separately.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;If you use OpenSSL for verifying PKCS#7 signatures, you should check
whether either the following holds:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Your signing certificate has &lt;code&gt;Extended Key Usage&lt;/code&gt; extension,
   but no &lt;code&gt;emailProtection&lt;/code&gt; bit.&lt;/li&gt;
&lt;li&gt;Your signing certificate has &lt;code&gt;KeyUsage&lt;/code&gt; extension, but no
   &lt;code&gt;digitalSignature&lt;/code&gt; neither &lt;code&gt;nonRepudiation&lt;/code&gt; OID.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If this is the case, then verification with OpenSSL fails even if your
signature "should" verify correctly.&lt;/p&gt;
&lt;p&gt;For checking signatures with command-line &lt;code&gt;openssl smime -verify&lt;/code&gt;,
a partial workaround can be adding option &lt;code&gt;-purpose any&lt;/code&gt;.
In this case OpenSSL will not check Extended Key Usage extensions at all.
This can be acceptable or not by your verification policy.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;-purpose&lt;/code&gt; option allows to check only for certain
(although probably common) x509v3 extension combinations.
OpenSSL defines a number of what it calls "purposes".
If you need to check a combination which does not correspond to any
of these "purposes", it must be done in a separate operation.&lt;/p&gt;
&lt;p&gt;For checking signatures with C API &lt;code&gt;PKCS7_verify()&lt;/code&gt;, the algorithm
can be the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If your policy does not care about X.509v3 extensions, set your
   verification parameters to &lt;code&gt;X509_PURPOSE_ANY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Otherwise, check X509v3 extensions of the signing certificate as required
   by your policy
   (&lt;a href="https://zakird.com/2013/10/13/certificate-parsing-with-openssl#other-x509-extensions"&gt;example&lt;/a&gt;).
   Set a custom verification callback with &lt;code&gt;X509_STORE_CTX_set_verify_cb()&lt;/code&gt;,
   which might either ignore the "unsupported certificate purpose" error, i.e.
   &lt;code&gt;X509_V_ERR_INVALID_PURPOSE&lt;/code&gt;, or have some more complicated logic.&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;</description><category>openssl</category><category>pkcs#7</category><category>signature</category><category>x.509</category><guid>https://technotes.shemyak.com/posts/smimesign-extended-key-usage-extension-for-openssl-pkcs7-verification/</guid><pubDate>Sat, 31 Dec 2016 20:34:22 GMT</pubDate></item><item><title>ARP messages: Request, Reply, Probe, Announcement</title><link>https://technotes.shemyak.com/posts/arp-messages/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;p&gt;ARP, as originally specified in &lt;a href="http://tools.ietf.org/html/rfc5227"&gt;RFC 826&lt;/a&gt;,
had two message types: &lt;code&gt;REQUEST&lt;/code&gt; and &lt;code&gt;REPLY&lt;/code&gt;.
But besides that one can hear of two "other" ARP messages:
&lt;code&gt;PROBE&lt;/code&gt; &lt;code&gt;ANNOUNCEMENT&lt;/code&gt;, the latter also called "&lt;strong&gt;gratuitous ARP&lt;/strong&gt;".
They happen when a host send the &lt;strong&gt;reply&lt;/strong&gt; message not in response to any
preceding request; this has been formalized in
&lt;a href="http://tools.ietf.org/html/rfc5227"&gt;RFC 5227&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;One may find confusing that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The two "new" messages do not extend the protocol. In particular,
they do not introduce new ARP message types. How can we speak about
"new messages"?&lt;/li&gt;
&lt;li&gt;Source and destination MAC addresses are present in the MAC headers,
but there are also "&lt;strong&gt;Source Hardware Address&lt;/strong&gt;" and 
"&lt;strong&gt;Target Hardware Address&lt;/strong&gt;" fields in the ARP body.
Why this duplication?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These two questions are related. The table below shows the 
&lt;strong&gt;MAC headers&lt;/strong&gt; and (relevant) &lt;strong&gt;ARP protocol fields&lt;/strong&gt; for each of the
four messages. The differences help to understand how each field is used.&lt;/p&gt;
&lt;table border="1"&gt;&lt;tbody&gt;
&lt;tr style="background-color: #e0e0e0;"&gt;&lt;td rowspan="2"&gt;Message&lt;/td&gt;&lt;td rowspan="2"&gt;Sent when the host...&lt;/td&gt;&lt;td colspan="2"&gt;MAC headers&lt;/td&gt;&lt;td colspan="5"&gt;ARP body&lt;/td&gt;&lt;/tr&gt; 
&lt;tr style="background-color: #e0e0e0;"&gt;&lt;td&gt;src MAC&lt;/td&gt;&lt;td&gt;dst MAC&lt;/td&gt;&lt;td&gt;message type&lt;/td&gt;&lt;td&gt;Source Hardware Address&lt;/td&gt;&lt;td&gt;Source Protocol Address&lt;/td&gt;&lt;td&gt;Target Hardware Address&lt;/td&gt;&lt;td&gt;Target Protocol Address&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;request&lt;/td&gt;&lt;td&gt;wants to send an IP packet, but does not know the MAC address of the destination&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;broadcast&lt;/td&gt;&lt;td&gt;REQUEST&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;destination's&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;reply&lt;/td&gt;&lt;td&gt;receives an ARP request to an IP address this host owns&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;destination's, or broadcast&lt;sup&gt;1&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;REPLY&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;requestor's&lt;/td&gt;&lt;td&gt;requestor's&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;probe (RFC 5227, 2.1)&lt;/td&gt;&lt;td&gt;configures a new IP address for an interface&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;broadcast&lt;/td&gt;&lt;td&gt;REQUEST&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;0&lt;sup&gt;3&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;probed&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;announcement (RFC 5227, 2.3)&lt;/td&gt;&lt;td&gt;after a probe, concludes that it will use the probed address&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;broadcast&lt;/td&gt;&lt;td&gt;REQUEST&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;own&lt;/td&gt;&lt;td&gt;new own&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;td&gt;new own&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

&lt;h3&gt;Notes to the table&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://tools.ietf.org/html/rfc5227#section-2.6"&gt;RFC 5227, section 2.6&lt;/a&gt;
   explains why "Broadcast replies are not
   universally recommended, but may be appropriate in some cases".&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tools.ietf.org/html/rfc5227#section-3"&gt;RFC 5227, section 3&lt;/a&gt;
   notes that the type here could be REPLY as well,
   then continues to give reasons why REQUEST is recommended.&lt;/li&gt;
&lt;li&gt;Zero is specified here in order not to pollute ARP caches of other
   hosts in case when the probed address is already taken by someone else.&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;</description><category>network</category><guid>https://technotes.shemyak.com/posts/arp-messages/</guid><pubDate>Tue, 26 Jan 2016 18:46:00 GMT</pubDate></item><item><title>Possible implications of netmask mismatch</title><link>https://technotes.shemyak.com/posts/netmask-mismatch/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; an IPv4 host with a netmask not matching that of the subnet to which the interface is connected likely builds incorrect routing tables, misses some broadcasts, may incorrectly identify broadcasts as unicasts, and unintentionally broadcast to own subnet.&lt;/p&gt;
&lt;h3&gt;What does it mean - a "wrong netmask"?&lt;/h3&gt;
&lt;p&gt;The &lt;em&gt;netmask&lt;/em&gt; (in IPv4 terminology) and &lt;em&gt;network prefix&lt;/em&gt; (in IPv6 terminology)
can be associated with an &lt;em&gt;IP subnet&lt;/em&gt;, and correspondingly with a 
&lt;em&gt;network interface&lt;/em&gt;. This post handles IPv4 only, so the term "netmask"
will be used. Together with own IP address, the netmask determines whether
another IP address belongs to the same IP subnet as the NIC.&lt;/p&gt;
&lt;p&gt;Good, so how is this knowledge used?&lt;/p&gt;
&lt;p&gt;Processing of &lt;strong&gt;multicast&lt;/strong&gt; packets is not affected by the netmask,
thus multicast would not be mentioned here further. For &lt;strong&gt;unicast&lt;/strong&gt;
and &lt;strong&gt;broadcast&lt;/strong&gt;, the netmask is consulted in three different situations,
listed in the following sections.&lt;/p&gt;
&lt;h3&gt;Case 1. Netmask can be used as input for constructing the routing table.&lt;/h3&gt;
&lt;p&gt;The routing system normally automatically creates routes to the subnet
to which each network interface belongs. I.e. for each network interface
&lt;code&gt;I&lt;/code&gt; with address &lt;code&gt;AI&lt;/code&gt; and netmask &lt;code&gt;M&lt;/code&gt;, the host calculates the subnet of
this interface as &lt;code&gt;SI = AI &amp;amp; M&lt;/code&gt;.
Outgoing packets to any address &lt;code&gt;AP&lt;/code&gt; such that &lt;code&gt;AP &amp;amp; M = SI&lt;/code&gt; would be
emitted from the interface &lt;code&gt;I&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;While this behavior is typical, nothing mandates hosts to create such
routing table entry. For example, if a host has two interfaces on the
same subnet, then obviously some more information is needed to decide,
which of the interfaces shall emit the packets destined to their common
subnet. Another example is a firewall with more restrictive forwarding
policy than just &lt;em&gt;"put every packet for subnet &lt;code&gt;SI&lt;/code&gt; to interface &lt;code&gt;I&lt;/code&gt;"&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;Case 2. Netmask is used to determine whether an arrived packet is a (directed) broadcast to a subnet of some local interface.&lt;/h3&gt;
&lt;p&gt;After the routing is covered, we can limit our further 
investigation to only:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Unicast&lt;/strong&gt; packets, destined to "this host" (i.e. one of its interfaces).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Directed broadcast&lt;/strong&gt; packets to "this network". There can be more than 
  one "this" network if the host has more than one network interface
  (the host can be or not be a router).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Really,&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Directed broadcast&lt;/strong&gt; to a network not in "our network" set is handled as
  any other packet subject to possible routing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Local broadcast&lt;/strong&gt; packets are obviously not affected by the netmask
  setting.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For hosts which are &lt;strong&gt;not routers&lt;/strong&gt; &lt;a href="https://tools.ietf.org/html/rfc922"&gt;RFC922&lt;/a&gt;
defines handling of broadcast packets in a simple way:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;In&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;absence&lt;/span&gt; &lt;span class="nv"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;broadcasting&lt;/span&gt;, &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;host&lt;/span&gt; &lt;span class="nv"&gt;determines&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;it&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt;
&lt;span class="nv"&gt;recipient&lt;/span&gt; &lt;span class="nv"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;datagram&lt;/span&gt; &lt;span class="nv"&gt;by&lt;/span&gt; &lt;span class="nv"&gt;matching&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;destination&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt; &lt;span class="nv"&gt;against&lt;/span&gt;
&lt;span class="nv"&gt;all&lt;/span&gt; &lt;span class="nv"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;its&lt;/span&gt; &lt;span class="nv"&gt;IP&lt;/span&gt; &lt;span class="nv"&gt;addresses&lt;/span&gt;.  &lt;span class="nv"&gt;With&lt;/span&gt; &lt;span class="nv"&gt;broadcasting&lt;/span&gt;, &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;host&lt;/span&gt; &lt;span class="nv"&gt;must&lt;/span&gt; &lt;span class="nv"&gt;compare&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt;
&lt;span class="nv"&gt;destination&lt;/span&gt; &lt;span class="nv"&gt;address&lt;/span&gt; &lt;span class="nv"&gt;not&lt;/span&gt; &lt;span class="nv"&gt;only&lt;/span&gt; &lt;span class="nv"&gt;against&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;host&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s addresses, but also&lt;/span&gt;
&lt;span class="nv"&gt;against&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;possible&lt;/span&gt; &lt;span class="nv"&gt;broadcast&lt;/span&gt; &lt;span class="nv"&gt;addresses&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;that&lt;/span&gt; &lt;span class="nv"&gt;host&lt;/span&gt;.
&lt;/pre&gt;


&lt;p&gt;Now imagine that an interface of some host has netmask, which does not
match one of the subnet this interface is connected to. This is what
happens.&lt;/p&gt;
&lt;h4&gt;Netmask of the interface is shorter&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Interface misconfigured with a &lt;strong&gt;shorter netmask&lt;/strong&gt; fails to process broadcasts:
  they are understood as unicasts by such host.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Example: in &lt;code&gt;/24&lt;/code&gt; network &lt;span style="color: red;"&gt;1.1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;0&lt;/span&gt;, a packet to a broadcast address &lt;span style="color: red;"&gt;1.1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255&lt;/span&gt; will not be recognized as broadcast by a misconfigured interface &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.1&lt;/span&gt;/16.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is, unless the network has all bits in the netmask difference equal to 1.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Example: in &lt;code&gt;/24&lt;/code&gt; network &lt;span style="color: red;"&gt;1.1.255&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;0&lt;/span&gt;, a packet to a broadcast address &lt;span style="color: red;"&gt;1.1.255&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255&lt;/span&gt; will be, by a coincidence, correctly accepted as broadcast by a misconfigured interface &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.1&lt;/span&gt;/16.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Broadcast packet which is incorrectly understood as unicast by a 
  misconfigured interface can also happen to bear the destination address
  of this interface itself.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Example: in &lt;code&gt;/16&lt;/code&gt; network &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;0.0&lt;/span&gt;, a broadcast packet to &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255.255&lt;/span&gt; will be received as unicast by a misconfigured interface &lt;span style="color: red;"&gt;1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.255.255&lt;/span&gt;/8.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Additionally, the host may attempt to send a unicast packet which would
  appear as a valid broadcast on the network.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Example: in &lt;code&gt;/16&lt;/code&gt; network &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;0.0&lt;/span&gt;, a host misconfigured as &lt;span style="color: red;"&gt;1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.1.1&lt;/span&gt;/8 sends a unicast to destination address &lt;span style="color: red;"&gt;1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.255.255&lt;/span&gt;. It appears as broadcast on this network. In fact, there can be no host with address &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255.255&lt;/span&gt; on this network (as it is a broadcast address), so nobody answers ARP query and the host will not be able to send such packet.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Netmask of the interface is longer&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Interface misconfigured with a &lt;strong&gt;longer netmask&lt;/strong&gt; fails to process broadcasts
as well: it will consider them not belonging to own subnet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Example: in &lt;code&gt;/8&lt;/code&gt; network &lt;span style="color: red;"&gt;1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;0.0.0&lt;/span&gt;, a packet to a broadcast address &lt;span style="color: red;"&gt;1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255.255.255&lt;/span&gt; will not be received by a misconfigured interface &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.1&lt;/span&gt;/16.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Again, unless the address of the misconfigured interface happens to have
  all bits in the netmask difference being equal to 1.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example: in that same network, that same broadcast packet will be
    accepted just fine by a misconfigured interface
    &lt;span style="color: red;"&gt;1.255&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.1&lt;/span&gt;/16.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For hosts which &lt;strong&gt;are routers&lt;/strong&gt;, RFC922 adds the clause concerning for broadcast packets destined to other interface than the one on which the packet is received:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;...&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;datagram&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="nv"&gt;addressed&lt;/span&gt; &lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;hardware&lt;/span&gt; &lt;span class="nv"&gt;network&lt;/span&gt;
&lt;span class="nv"&gt;to&lt;/span&gt; &lt;span class="nv"&gt;which&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;gateway&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="nv"&gt;connected&lt;/span&gt;, &lt;span class="nv"&gt;it&lt;/span&gt; &lt;span class="nv"&gt;should&lt;/span&gt; &lt;span class="nv"&gt;be&lt;/span&gt; &lt;span class="nv"&gt;sent&lt;/span&gt; &lt;span class="nv"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;data&lt;/span&gt; &lt;span class="nv"&gt;link&lt;/span&gt; &lt;span class="nv"&gt;layer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;broadcast&lt;/span&gt; &lt;span class="nv"&gt;on&lt;/span&gt; &lt;span class="nv"&gt;that&lt;/span&gt; &lt;span class="nv"&gt;network&lt;/span&gt;.  &lt;span class="nv"&gt;Again&lt;/span&gt;, &lt;span class="nv"&gt;the&lt;/span&gt;
&lt;span class="nv"&gt;gateway&lt;/span&gt; &lt;span class="nv"&gt;should&lt;/span&gt; &lt;span class="nv"&gt;consider&lt;/span&gt; &lt;span class="nv"&gt;itself&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;destination&lt;/span&gt; &lt;span class="nv"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;datagram&lt;/span&gt;.
&lt;/pre&gt;


&lt;p&gt;In this case, the netmask of the router's interface, where the packet has been received, is not relevant - packet should be processed anyway. Instead, the packet's destination interface configuration is the basis for the decision. Correspondingly, mismatch between the netmask of the destination interface and the sender's expectation of the netmask leads to same consequences as listed above for non-forwarding hosts.&lt;/p&gt;
&lt;p&gt;Have we covered all cases? Three independent factors affect the outcome:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is the receiver's netmask shorter or longer than of the subnet it is connected to?&lt;/li&gt;
&lt;li&gt;Are the bits from the difference in netmask lengths all equal to one?&lt;/li&gt;
&lt;li&gt;Is the packet unicast or (directed) broadcast?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All 8 possibilities have been considered above.&lt;/p&gt;
&lt;h3&gt;Case 3. Netmask is used for setting destination address of outgoing broadcast packets.&lt;/h3&gt;
&lt;p&gt;When a host wishes to send a broadcast packet from certain interface,
it sets the destination address to that of the interface and puts &lt;code&gt;1&lt;/code&gt; to
all bits which are zeros in the netmask. Correspondingly:&lt;/p&gt;
&lt;h4&gt;Netmask of the network interface is shorter&lt;/h4&gt;
&lt;p&gt;Host with &lt;strong&gt;shorter netmask&lt;/strong&gt; will set too many bits to &lt;code&gt;1&lt;/code&gt;.
On the local subnet, these packets will be recognized as belonging
to other subnet by other hosts and consequently not processed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example: in &lt;code&gt;/24&lt;/code&gt; network &lt;span style="color: red;"&gt;1.1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;0&lt;/span&gt;/24, host misconfigured as &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.1&lt;/span&gt;/16 sends what it thinks a "broadcast" with destination &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255.255&lt;/span&gt;. (It will be sent as link-layer broadcast.) No other host on this network accepts it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unless if the network has all bits in the netmask difference being equal to one.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example: in /24 network &lt;span style="color: red;"&gt;1.1.255&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;0&lt;/span&gt;/24, a misconfigured host &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255.1&lt;/span&gt;/16 sends a "broadcast" packet to &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255.255&lt;/span&gt;, which happens to be a valid broadcast on this network.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Netmask of the network interface is longer&lt;/h4&gt;
&lt;p&gt;Host with &lt;strong&gt;longer netmask&lt;/strong&gt; will not set enough bits to &lt;code&gt;1&lt;/code&gt;.
The packets sent as broadcast will be recognized as unicast by other hosts
on this subnet.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Example: in &lt;code&gt;/8&lt;/code&gt; network &lt;span style="color: red;"&gt;1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;0.0.0&lt;/span&gt;/8, a host misconfigured as &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.1&lt;/span&gt;/16 sends what it thinks to be a broadcast packet to &lt;span style="color: red;"&gt;1.1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;255.255&lt;/span&gt;. It appears as valid unicast on this subnet. If there is a host with address &lt;span style="color: red;"&gt;1&lt;/span&gt;.&lt;span style="color: #38761d;"&gt;1.255.255&lt;/span&gt;, this host will accept this packet. (Besides probably unexpected IP content, the host may also notice that the layer 2 address of this packet was a layer 2 broadcast.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Naturally, these cases are "reversed" repetition of the cases for the receiving hosts.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Netmask is normally (but not necessarily) used as input for the &lt;strong&gt;routing table&lt;/strong&gt; construction. If used, then a wrong interface netmask makes possible the following routing failures:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Too long netmask&lt;/strong&gt;: the host will have no route for some packets, actually belonging to a subnet of this interface. Attempt to send packet to a host outside the too long misconfigured netmask but inside the correct netmask of the net results in ICMP error &lt;em&gt;"Destination net unreachable"&lt;/em&gt;. If there is a default outgoing interface, the host will not generate the error, but send the packets to the default interface instead of the interface of this subnet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Too short netmask&lt;/strong&gt;: the host may attempt to send to the interface packets, which would not be received by any host of the connected subnet. This attempt probably fails, because no host answers the ARP request. This results in ICMP error "Destination host unreachable".&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In IPv4, &lt;strong&gt;directed broadcast&lt;/strong&gt; packets are sent and received utilizing the netmask information. Directed broadcast is a marginal case; such packets are rarely used and dropped by most routers as per &lt;a href="https://tools.ietf.org/html/rfc2644"&gt;RFC2644&lt;/a&gt;.
But if directed broadcasts are used, then mismatched netmask results in any of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;failure to receive broadcast packets&lt;/li&gt;
&lt;li&gt;failure to forward broadcast packets by routers&lt;/li&gt;
&lt;li&gt;forwarding broadcast packets, destined to own network&lt;/li&gt;
&lt;li&gt;accepting unicast packets, destined to some host, as broadcasts&lt;/li&gt;
&lt;li&gt;accepting broadcast packets as unicast.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</description><category>network</category><guid>https://technotes.shemyak.com/posts/netmask-mismatch/</guid><pubDate>Sat, 03 Oct 2015 10:51:00 GMT</pubDate></item><item><title>Support for elliptic curves by jarsigner</title><link>https://technotes.shemyak.com/posts/support-for-elliptic-curves-by-jarsigner/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Support for cryptography features by jarsigner depends on available Java crypto providers.&lt;/p&gt;
&lt;p&gt;Suppose you are defining a PKI profile. You naturally want to use the
stronger algorithms with better performance, which (as of year 2014)
means elliptic curves. Besides bit strength and performance,
you want to be sure that the curve is supported by your software.
If the latter includes &lt;strong&gt;jarsigner&lt;/strong&gt;, you'll be surprised to find that 
&lt;a href="http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jarsigner.html"&gt;Oracle documentation&lt;/a&gt;
seems to not mention at all, 
&lt;em&gt;which elliptic curves does jarsigner support&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Signing a JAR means adding digests of the JAR entries to the &lt;em&gt;manifest file&lt;/em&gt;
(&lt;code&gt;META-INF/*.MF&lt;/code&gt;),
adding digest of the latter to the &lt;em&gt;manifest signature file&lt;/em&gt;
(&lt;code&gt;META-INF/*.EC&lt;/code&gt;, in case &lt;code&gt;E&lt;/code&gt;lliptic &lt;code&gt;C&lt;/code&gt;urve is used),
and then creating the
&lt;a href="https://technotes.shemyak.com/posts/jar-signature-block-file-format/"&gt;JAR signature block file&lt;/a&gt;.
The last step involves two operations:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;calculating a digest over the &lt;em&gt;manifest signature file&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;signing (i.e. encrypting with the private key) that digest.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Jarsigner has an option &lt;code&gt;-sigalg&lt;/code&gt;,
which is supposed to specify the two algorithms used in these two steps.
(There is also &lt;code&gt;-digestalg&lt;/code&gt;' option, but it is not used for the signature
block file; it defines the algorithm used in the two initial steps.)
Well, this option is irrelevant for our question: the curve is in fact
defined by the provided private key. So jarsigner will either do the job
or choke on the key which comes from an unsupported curve.&lt;/p&gt;
&lt;p&gt;A curve may "not work" because it is unknown to jarsigner itself, or to
an underlying crypto provider. (The latter case was a reason to a
&lt;a href="https://bugs.launchpad.net/ubuntu/+source/openjdk-6/+bug/1006776"&gt;bug 1006776&lt;/a&gt;,
a setup where only three curves actually worked.) Attempt to sign the JAR 
with &lt;code&gt;jarsigner&lt;/code&gt; using a non-supported private key would result in a
not very helpful error message:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;certificate&lt;/span&gt; &lt;span class="k"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IOException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Could&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;create&lt;/span&gt; &lt;span class="n"&gt;EC&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;key&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;To be on the safe side, it's best to test. For curves, supported by OpenSSL,
the test can be done by creating the keypair on each curve and attempting
the signing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create the list of curves with &lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;openssl&lt;/span&gt; &lt;span class="n"&gt;ecparam&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;list_curves&lt;/span&gt;
&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;remove manually some extra words openssl puts there in the beginning&lt;/li&gt;
&lt;li&gt;and feed it to the stdin:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;  &lt;span class="c1"&gt;#!/bin/bash&lt;/span&gt;
  &lt;span class="c1"&gt;# Test, which OpenSSL-supported elliptic curves from the list are supported also by jarsigner.&lt;/span&gt;
  &lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"supported- curves.txt"&lt;/span&gt;
  &lt;span class="nv"&gt;source_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"data.txt"&lt;/span&gt;
  &lt;span class="nv"&gt;jar&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"data.jar"&lt;/span&gt;
  &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"key.pem"&lt;/span&gt;
  &lt;span class="nv"&gt;cert&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cert.pem"&lt;/span&gt;
  &lt;span class="nv"&gt;pfx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"keystore.pfx"&lt;/span&gt;
  &lt;span class="nv"&gt;key_alias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"foo"&lt;/span&gt;         &lt;span class="c1"&gt;# Identificator of the key in the keystore&lt;/span&gt;
  &lt;span class="nv"&gt;storepass&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"123456"&lt;/span&gt;      &lt;span class="c1"&gt;# jarsigner requires some&lt;/span&gt;

  touch &lt;span class="nv"&gt;$source_data&lt;/span&gt;
  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; curve&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Generate an ECDSA private key for the selected curve:&lt;/span&gt;
    openssl ecparam -name &lt;span class="nv"&gt;$curve&lt;/span&gt; -genkey -out &lt;span class="nv"&gt;$key&lt;/span&gt;
    &lt;span class="c1"&gt;# Generate the certificate for the key; give some dummy subject:&lt;/span&gt;
    openssl req -new -x509 -nodes -key &lt;span class="nv"&gt;$key&lt;/span&gt; -out &lt;span class="nv"&gt;$cert&lt;/span&gt; -subj /CN&lt;span class="o"&gt;=&lt;/span&gt;foo
    &lt;span class="c1"&gt;# Wrap key+cert in a PKCS12, so that jarsigner can use it:&lt;/span&gt;
    openssl pkcs12 -export -in &lt;span class="nv"&gt;$cert&lt;/span&gt; -inkey &lt;span class="nv"&gt;$key&lt;/span&gt; -passout pass:&lt;span class="nv"&gt;$storepass&lt;/span&gt; -out &lt;span class="nv"&gt;$pfx&lt;/span&gt; -name &lt;span class="nv"&gt;$key_alias&lt;/span&gt;
    &lt;span class="c1"&gt;# Create a fresh jar and attempt to sign it&lt;/span&gt;
    jar cf &lt;span class="nv"&gt;$jar&lt;/span&gt; &lt;span class="nv"&gt;$source_data&lt;/span&gt;
    jarsigner -keystore &lt;span class="nv"&gt;$pfx&lt;/span&gt; -storetype PKCS12 -storepass &lt;span class="nv"&gt;$storepass&lt;/span&gt; &lt;span class="nv"&gt;$jar&lt;/span&gt; &lt;span class="nv"&gt;$key_alias&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; -eq &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$curve&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="nv"&gt;$result&lt;/span&gt;
  &lt;span class="k"&gt;done&lt;/span&gt;
  rm &lt;span class="nv"&gt;$source_data&lt;/span&gt; &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="nv"&gt;$cert&lt;/span&gt; &lt;span class="nv"&gt;$pfx&lt;/span&gt; &lt;span class="nv"&gt;$jar&lt;/span&gt;
&lt;/pre&gt;


&lt;p&gt;And enjoy the list in &lt;code&gt;supported-curves.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;support of elliptic curves by &lt;b&gt;jarsigner&lt;/b&gt; depends on jarsigner itself and on the used JRE.&lt;/li&gt;
&lt;li&gt;There is no command-line option to list all supported curves.&lt;/li&gt;
&lt;li&gt;For a particular system, support for curves known by &lt;b&gt;OpenSSL&lt;/b&gt; can be easily tested.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</description><category>elliptic curves</category><category>jarsigner</category><category>openssl</category><guid>https://technotes.shemyak.com/posts/support-for-elliptic-curves-by-jarsigner/</guid><pubDate>Sun, 21 Dec 2014 19:45:00 GMT</pubDate></item><item><title>JAR signature block file format</title><link>https://technotes.shemyak.com/posts/jar-signature-block-file-format/</link><dc:creator>Konstantin Shemyak</dc:creator><description>&lt;div&gt;&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; this post explains the content of the &lt;strong&gt;JAR signature block file&lt;/strong&gt; - 
that is, the file &lt;code&gt;META-INF/*.RSA&lt;/code&gt;, &lt;code&gt;META-INF/*.DSA&lt;/code&gt;, &lt;code&gt;META-INF/*.EC&lt;/code&gt;
or &lt;code&gt;SIG-*&lt;/code&gt; inside the JAR.&lt;/p&gt;
&lt;h3&gt;Oracle does not document it&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Signed JAR file&lt;/strong&gt; contains the following additions over a non-signed JAR:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Checksums over the JAR content, stored in text files
  &lt;code&gt;META-INF/MANIFEST.MF&lt;/code&gt; and &lt;code&gt;META-INF/*.SF&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The actual cryptographic signature (created with the private key
  of the signer) over the checksums in a binary &lt;strong&gt;signature block file&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Surprisingly, format of the latter does not seem to be documented by Oracle. &lt;a href="http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html#Digital_Signatures"&gt;JAR file specification&lt;/a&gt;
provides only a useful knowledge that
&lt;em&gt;"These are binary files not intended to be interpreted by humans"&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here, the content of this "signature block file" is explained.
We show how it can be created and verified with non-Java tool: OpenSSL.&lt;/p&gt;
&lt;h3&gt;Create a sample signature block file&lt;/h3&gt;
&lt;p&gt;For our investigation, generate such file by signing some data with &lt;strong&gt;jarsigner&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make an RSA private key (and store it unencrypted), corresponding
  self-signed certificate, pack them in a format jarsigner understands:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl genrsa -out key.pem
openssl req -x509 -new -key key.pem -out cert.pem -subj &lt;span class="s1"&gt;'/CN=foo'&lt;/span&gt;
openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.pfx -passout pass:123456 -name SEC_PAD
&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;openssl req&lt;/code&gt; command reads the default OpenSSL configuration file.
If you care about exact content of your certificate, you should
not rely on the system default but write your own (you can start with a
&lt;a href="https://technotes.shemyak.com/posts/min-openssl-cnf"&gt;minimal example&lt;/a&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create the data, jar it, sign the JAR, and unpack the "META-INF" directory:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Hello, world!'&lt;/span&gt; &amp;gt; data
jar cf data.jar data
jarsigner -keystore keystore.pfx -storetype PKCS12 -storepass &lt;span class="m"&gt;123456&lt;/span&gt; data.jar SEC_PAD
unzip data.jar META-INF/*
&lt;/pre&gt;


&lt;p&gt;The "signature block file" is &lt;code&gt;META-INF/SEC_PAD.RSA&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;What does this block contain&lt;/h3&gt;
&lt;p&gt;The file appears to be a &lt;a href="http://www.herongyang.com/Cryptography/Certificate-Format-DER-Distinguished-Encoding-Rules.html"&gt;DER-encoded&lt;/a&gt;
&lt;a href="https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One"&gt;ASN.1&lt;/a&gt;
&lt;a href="https://tools.ietf.org/html/rfc2315"&gt;PKCS#7&lt;/a&gt; data structure.
DER-encoded ASN.1 file can be examined with &lt;code&gt;asn1parse&lt;/code&gt; subcommand of the OpenSSL:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl asn1parse -in META-INF/SEC_PAD.RSA -inform der -i &amp;gt; jarsigner.txt
&lt;/pre&gt;


&lt;p&gt;For more verbosity, you may use some ASN.1 decoder such as one at
&lt;a href="http://lapo.it/asn1js/"&gt;lapo.it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You'll see that the two top-level components are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The certificate.&lt;/li&gt;
&lt;li&gt;256-byte RSA signature.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can extract the signature bytes from the binary data and
&lt;a href="http://qistoph.blogspot.com/2012/01/manual-verify-pkcs7-signed-data-with.html"&gt;verify&lt;/a&gt; (=decrypt with the public key) them with &lt;code&gt;openssl rsautl&lt;/code&gt;.
That includes some "low-level" operations and brings you one more step down 
to understanding the file's content.
A simple "high-level" verification command, not involving manual byte
manipulation, would be:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl cms -verify -noverify -content META-INF/SEC_PAD.SF -in META-INF/SEC_PAD.RSA -inform der
&lt;/pre&gt;


&lt;p&gt;This command tells: &lt;em&gt;"Check that the CMS structure in &lt;code&gt;META-INF/SEC_PAD.RSA&lt;/code&gt;
is really a signature of &lt;code&gt;META-INF/SEC_PAD.SF&lt;/code&gt;; do not attempt to validate
the certificate"&lt;/em&gt;. Congratulations, we have verified the JAR signature
without Java tools.&lt;/p&gt;
&lt;h3&gt;Creating the signature block file with OpenSSL&lt;/h3&gt;
&lt;p&gt;For this example, we created the signature block file with &lt;strong&gt;jarsigner&lt;/strong&gt;. 
There are at least two OpenSSL commands which can produce similar 
structures: &lt;code&gt;openssl cms&lt;/code&gt; and &lt;code&gt;openssl smime&lt;/code&gt;, with the options given below:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl cms -sign -binary -noattr -in META-INF/SEC_PAD.SF -outform der -out openssl-cms.der -signer cert.pem -inkey key.pem -md sha256
openssl smime -sign -noattr -in META-INF/SEC_PAD.SF -outform der -out openssl-smime.der -signer cert.pem -inkey key.pem -md sha256
&lt;/pre&gt;


&lt;p&gt;Let's decode the created files and compare them to what has been produced
with &lt;code&gt;jarsigner&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;openssl asn1parse -inform der -in openssl-cms.der -i &amp;gt; openssl-cms.txt
openssl asn1parse -inform der -in openssl-smime.der -i &amp;gt; openssl-smime.txt
&lt;/pre&gt;


&lt;h3&gt;Testing the "DIY signature"&lt;/h3&gt;
&lt;p&gt;Underlying ASN.1 structures are, in both &lt;strong&gt;cms&lt;/strong&gt; and &lt;strong&gt;smime&lt;/strong&gt; cases,
very close but not identical to those made by &lt;code&gt;jarsigner&lt;/code&gt;. 
As the format of the signature block file is not specified,
we can only do tests to have some ground to say that "it works".
Just replace the original signature block file with our signature
created by OpenSSL:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;cp openssl-cms.der META-INF/SEC_PAD.RSA
zip -u data.jar META-INF/SEC_PAD.RSA
jarsigner -verify -keystore keystore.pfx -storetype PKCS12 -storepass &lt;span class="m"&gt;123456&lt;/span&gt; data.jar SEC_PAD
&lt;/pre&gt;


&lt;p&gt;Lucky strike: a signature produced by &lt;code&gt;openssl cms&lt;/code&gt; is recognized by
&lt;code&gt;jarsigner&lt;/code&gt; (that is, at least "it worked for me").&lt;/p&gt;
&lt;p&gt;Note that the &lt;strong&gt;data&lt;/strong&gt; which is signed is &lt;code&gt;SEC_PAD.SF&lt;/code&gt;, and it was 
itself created by jarsigner. If not using the latter, you'll need to
produce that file in some way.&lt;/p&gt;
&lt;h3&gt;What's the use for this knowledge?&lt;/h3&gt;
&lt;p&gt;Besides better understanding your data, one can think of at least two
reasons to sign JARs with non-native tools. Both are somewhat untypical,
but not completely irrelevant:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;The signature must be produced in a system, where native Java tools are not available. 
Such system must have access to private key, and security administrators
may like the idea of not having such overbloated software as JRE in a
tightly controlled environment.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The signature must be produced or verified in a system, where available tools do not support the required signature algorithm.
Examples "why" include compliance with regulations or compatibility with
legacy systems. There are systems where &lt;a href="https://technotes.shemyak.com/posts/support-for-elliptic-curves-by-jarsigner/"&gt;testing which elliptic curves are supported by jarsigner&lt;/a&gt;
reveals just three curves (which is not much).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Summary (again)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JAR signature block file&lt;/strong&gt; is a DER-encoded PKCS#7 structure.&lt;/li&gt;
&lt;li&gt;Its exact content can be viewed with any ASN.1 decoder, e.g. with &lt;code&gt;openssl asn1parse&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;OpenSSL can verify signatures in signature block files and create almost
  identical structures, which have been reported to be accepted by Java
  tools.&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</description><category>jar</category><category>jarsigner</category><category>openssl</category><category>pkcs#7</category><category>signature</category><guid>https://technotes.shemyak.com/posts/jar-signature-block-file-format/</guid><pubDate>Mon, 08 Dec 2014 12:18:00 GMT</pubDate></item></channel></rss>