<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to Open Sesame!</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>Recent changes to Open Sesame!</description><atom:link href="https://sourceforge.net/p/opycua/wiki/Open%20Sesame!/feed" rel="self"/><language>en</language><lastBuildDate>Fri, 15 Jun 2012 19:19:38 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/opycua/wiki/Open%20Sesame!/feed" rel="self" type="application/rss+xml"/><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>&lt;pre&gt;--- v8
+++ v9
@@ -224,15 +224,29 @@
 
 In python, we can do this:
 
-    #!/usr/bin/python
-    import time
-    
-    def pytime_to_uatime(pytime):
-        uatime = int((10000000 * pytime) + 116444736000000000)
-        return uatime
-    
-    uatime = pytime_to_uatime(time.time())
-
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+#!/usr/bin/python
+import time
+
+def pytime_to_uatime(pytime):
+    uatime = long((10000000 * pytime) + 116444736000000000)
+    return uatime
+
+def uatime_to_pytime(uatime):
+    pytime = float(uatime - 116444736000000000) / 10000000
+    return pytime
+
+def main():
+    pytime = time.time()
+    print "Python: It 's ... "
+    print time.strftime('%Y-%m-%d %H:%M:%S')
+    print pytime
+    uatime = pytime_to_uatime(pytime)
+    print uatime
+    print uatime_to_pytime(uatime)
+
+if 	__name__ == "__main__":main()
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Some related articles are over here:
 
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Fri, 15 Jun 2012 19:19:38 -0000</pubDate><guid>https://sourceforge.net896bfddf95969c8fc7dc3dd676f696fe34bfd415</guid></item><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>&lt;pre&gt;--- v7
+++ v8
@@ -224,6 +224,7 @@
 
 In python, we can do this:
 
+    #!/usr/bin/python
     import time
     
     def pytime_to_uatime(pytime):
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Fri, 15 Jun 2012 19:12:53 -0000</pubDate><guid>https://sourceforge.net98ae3ec320d340e5e466da3f5f006a8d586d24e9</guid></item><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>&lt;pre&gt;--- v6
+++ v7
@@ -222,28 +222,15 @@
 &gt; opcua_time = (unix_time * 10000000) + 116444736000000000
 116444736000000000 = 10000000  * 60 * 60 * 24 * 365 * 369 + 89 leap days
 
- 
-Some conversion code from: &lt;http://pydoc.net/RSFile/1.1/rsbackends._utilities&gt;
-
-    def pyint_to_double_dwords(mylong, dwordsize=32):
-            if(mylong&lt;0):
-                    raise ValueError("Positive argument required")
+In python, we can do this:
+
+    import time
     
-            uloworder = mylong &amp; (2**dwordsize-1)
-            uhighorder = (mylong &gt;&gt; dwordsize) &amp; (2**dwordsize-1)
-            return (uloworder, uhighorder)
-     
-    def double_dwords_to_pyint(loworder, highorder , dwordsize=32): 
-            return  (highorder &lt;&lt; dwordsize) + loworder
-     
-    def win32_filetime_to_python_timestamp(loworder, highorder):
-        win32_timestamp = double_dwords_to_pyint(loworder, highorder)
-        return float(win32_timestamp - 116444736000000000) / 10000000
-     
-    def python_timestamp_to_win32_filetime(pytimestamp):
-        win32_timestamp = int((10000000 * pytimestamp) + 116444736000000000)
-        (loworder, highorder) = pyint_to_double_dwords(win32_timestamp)
-        return (loworder, highorder)
+    def pytime_to_uatime(pytime):
+        uatime = int((10000000 * pytime) + 116444736000000000)
+        return uatime
+    
+    uatime = pytime_to_uatime(time.time())
 
 
 Some related articles are over here:
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Fri, 15 Jun 2012 19:11:25 -0000</pubDate><guid>https://sourceforge.net07b4f9664015d5348272c4d26deac458b44db305</guid></item><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>&lt;pre&gt;--- v5
+++ v6
@@ -1,6 +1,6 @@
 "Open Sesame" (Arabic إفتح يا سمسم iftaḥ ya simsim 'open, O sesame') is a magical phrase in the story of "Ali Baba and the Forty Thieves" in One Thousand and One Nights. It opens the mouth of a cave in which forty thieves have hidden a treasure; "Close Sesame" re-seals the cave.
 
-~Wikipedia &lt;http://en.wikipedia.org/wiki/Open_Sesame_%28phrase%29&gt;
+~ [Wikipedia](http://en.wikipedia.org/wiki/Open_Sesame_%28phrase%29)
 
 ----
 Contents:
@@ -20,7 +20,7 @@
 The first 8 bytes are very similar to the Hello message.
 
  * MessageType: The first 3 bytes should say "OPN".
- * IsFinal: 1 byte. "F" if final chunk, otherwise "C"
+ * IsFinal: an ASCII letter. "F" for Final chunk, otherwise "C" for Chunk
  * MessageSize: the size of the entire message (without padding and signature)
 
 These 8 bytes will make it easy for the communication stack to retrieve the message (chunks) from the TCP stream.
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Fri, 15 Jun 2012 18:31:17 -0000</pubDate><guid>https://sourceforge.neta5a1f04fdf0b0c2e0d2fc8f7f8146027899827e5</guid></item><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>&lt;pre&gt;--- v4
+++ v5
@@ -1,11 +1,6 @@
 "Open Sesame" (Arabic إفتح يا سمسم iftaḥ ya simsim 'open, O sesame') is a magical phrase in the story of "Ali Baba and the Forty Thieves" in One Thousand and One Nights. It opens the mouth of a cave in which forty thieves have hidden a treasure; "Close Sesame" re-seals the cave.
 
 ~Wikipedia &lt;http://en.wikipedia.org/wiki/Open_Sesame_%28phrase%29&gt;
-
-----
-CLEAN UP ARTICLE AND EXTEND
-----
-
 
 ----
 Contents:
@@ -19,6 +14,40 @@
 ----
 
 ## 1. Python snippet ##
+
+Let's examine the OpenSecureChannel request 's message structure. Imagine you are an OPC ua server, getting a request.  
+
+The first 8 bytes are very similar to the Hello message.
+
+ * MessageType: The first 3 bytes should say "OPN".
+ * IsFinal: 1 byte. "F" if final chunk, otherwise "C"
+ * MessageSize: the size of the entire message (without padding and signature)
+
+These 8 bytes will make it easy for the communication stack to retrieve the message (chunks) from the TCP stream.
+
+Once we have  a message (or a chunk), we want to know how to decrypt it. We can figure this out with the next bytes in the message (chunk).
+
+ * SecureChannelId: this is set by server, and should be just 0 in the OpenSecureChannel request.
+ * SecurtiyPolicyUri: This identifies the type of security that is applied to the message (chunk). This can be [None](https://opcfoundation.org/profilereporting/index.htm?ModifyProfile.aspx?ProfileID=53605a50-a6ac-44ed-9baa-36c4873ff504), [Basic128Rsa15](https://opcfoundation.org/profilereporting/index.htm?ModifyProfile.aspx?ProfileID=53605a50-a6ac-44ed-9baa-36c4873ff504), ... .
+ * SenderCertificate: The X509v3 certificate of the client, DER encoded.
+ * ReceiverCertificateThumbprint: The SHA1 digest of the X509v3 certificate of the server, DER encoded.
+
+We were able to decrypt the message (chunk) using the public key of the client. So we now have a message. Or (probably) a bunch of chunks. To reassemble the message from the chunks we need to know the correct order. The next byte comes to the rescue:
+
+ * SequenceNumber: this number is incremented by the client all the time.
+
+We just keep concatenating chunks with increasing SequenceNumber until we find a final chunk (with IsFinal = "F"). 
+
+The next Byte is another number:
+
+ * RequestId: This number is used to map a certain response to a certain request. The server just needs to repeat this Id when sending the response to the request.
+
+Next comes the actual OpenSecureChannel request message.
+
+----
+  TO BE CONTINUED ...
+----
+
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 import socket
@@ -68,7 +97,7 @@
 x = Container(
             MessageType       = 'OPN' ,
             IsFinal           = 'F'   ,
-            MessageSize       =  1191   ,
+            MessageSize       =  154   ,
             SecureChannelId   =  0   ,
             SecurityPolicyUri = 
     'http://opcfoundation.org/UA/securitypolicy#None',
@@ -100,6 +129,7 @@
 
 packed_data = c.build(x)
 
+print len(packed_data)
 
 # Create a TCP/IP socket
 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@@ -139,9 +169,16 @@
 
 ----
 
-Some openSSL commands:
-
-Create a new private key:
+We can use the openSSL command line tool to generate keys and certificates.
+
+&gt;The x509 utility can be used to sign certificates and requests: it can thus behave like a ``mini CA''. 
+
+Find detailed documentation over here:
+
+ * &lt;http://www.openssl.org/docs/HOWTO/keys.txt&gt;
+ * &lt;http://www.openssl.org/docs/apps/x509.html#SIGNING_OPTIONS&gt;
+
+Create a new private key (without a password) :
 
     openssl genrsa -out privatekey.pem 2048
 
@@ -159,70 +196,15 @@
 
 ----
 
-WITH PYTHON:
-
-    f = open('test.pem', 'r')
+We can also call some of these function from within python like so:
+
+    import ssl
+    import hashlib
+    f = open('opycua.pem', 'r')
     pemcert = f.read()
     dercert = ssl.PEM_cert_to_DER_cert(pemcert)
-    import hashlib
     m = hashlib.sha1(dercert)
     thumbprint = m.hexdigest()
-
-
-The x509 utility can be used to sign certificates and requests: it can thus behave like a ``mini CA''. 
-
-1.Generate a private key (but don't password protect it)
-
-    openssl genrsa -out privatekey.pem 2048
-
-Based on: &lt;http://www.openssl.org/docs/HOWTO/keys.txt&gt;
-
-    2. To generate a RSA key
-    
-    A RSA key can be used both for encryption and for signing.
-    
-    Generating a key for the RSA algorithm is quite easy, all you have to
-    do is the following:
-    
-      openssl genrsa -des3 -out privkey.pem 2048
-    
-    With this variant, you will be prompted for a protecting password.  If
-    you don't want your key to be protected by a password, remove the flag
-    '-des3' from the command line above.
-    
-        NOTE: if you intend to use the key together with a server
-        certificate, it may be a good thing to avoid protecting it
-        with a password, since that would mean someone would have to
-        type in the password every time the server needs to access
-        the key.
-    
-    The number 2048 is the size of the key, in bits.  Today, 2048 or
-    higher is recommended for RSA keys, as fewer amount of bits is
-    consider insecure or to be insecure pretty soon.
-
-2. Create self signed certificate
-
-    openssl req -new -x509 -key privkey.pem -out opycua.pem -days 1
-
-
-Optional: create a certificate signing request (CSR)
-
-openssl req -new -key privatekey.pem -out cert.csr
-
-
-Convert PEM to DER like so:
-
-    openssl x509 -in opycua.pem -outform DER -out opycua.der
-
-command line options:
-http://www.openssl.org/docs/apps/x509.html#SIGNING_OPTIONS
-
-
-FINGERPRINTS
-
- openssl x509 -sha1 -in cert.pem -noout -fingerprint
-
-
 
 
 ## 4. OPC ua timeformat ##
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Wed, 13 Jun 2012 18:42:55 -0000</pubDate><guid>https://sourceforge.net9af23b909a197717e03e1fcc4cdeb1cc5fbba37a</guid></item><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>&lt;pre&gt;--- v3
+++ v4
@@ -71,7 +71,7 @@
             MessageSize       =  1191   ,
             SecureChannelId   =  0   ,
             SecurityPolicyUri = 
-    'http://opcfoundation.org/UA/securitypolicy#Basic128Rsa15',
+    'http://opcfoundation.org/UA/securitypolicy#None',
             SenderCertificateLength = 0, #len(dercert),
             SenderCertificate =  '', #dercert,
             ReceiverCertificateThumbprintLength = 0, #len(ThumbPrint),
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Tue, 12 Jun 2012 21:27:15 -0000</pubDate><guid>https://sourceforge.nete41b86508f74015ff5c26b31405ae8718cc5a29a</guid></item><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>&lt;pre&gt;--- v2
+++ v3
@@ -1,38 +1,30 @@
-# Open Sesame! #
-
-&gt; (Arabic إفتح يا سمسم iftaḥ ya simsim 'open, O sesame') 
-is a magical phrase in the story of "Ali Baba and the Forty Thieves" 
-in One Thousand and One Nights. It opens the mouth of a cave 
-in which forty thieves have hidden a treasure; 
-"Close Sesame" re-seals the cave.
+"Open Sesame" (Arabic إفتح يا سمسم iftaḥ ya simsim 'open, O sesame') is a magical phrase in the story of "Ali Baba and the Forty Thieves" in One Thousand and One Nights. It opens the mouth of a cave in which forty thieves have hidden a treasure; "Close Sesame" re-seals the cave.
 
 ~Wikipedia &lt;http://en.wikipedia.org/wiki/Open_Sesame_%28phrase%29&gt;
 
------------------------------------------------------------------
-
-NEEDS SOMEORE INFO !!
-
------------------------------------------------------------------
-
-## OpenSecureChannel Request ##
+----
+CLEAN UP ARTICLE AND EXTEND
+----
+
+
+----
+Contents:
+----
+
+1. python snippet
+2. NodeIds
+3. openSSL
+4. OPC ua timeformat
+5. signature and padding
+----
+
+## 1. Python snippet ##
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 import socket
 import sys
-import ssl
-# numpy for 64 bit time ?? --&gt; does not change anything.
-#import numpy
-# numpy.int64(12345)
 
 from construct import *
-
-
-f = open('test.pem', 'r')
-pemcert = f.read()
-dercert = ssl.PEM_cert_to_DER_cert(pemcert)
-
-ThumbPrint = '07:6B:16:EA:32:27:DC:54:72:EA:FD:D0:ED:FD:4B:00:C5:BD:12:6C'
-
 
 c = Struct('OPC UASC OpenSecureChannel Request',
 
@@ -40,31 +32,31 @@
             String('IsFinal', 1),
             ULInt32('MessageSize'),
             ULInt32('SecureChannelId'),
-            PascalString('SecurityPolicyUri', length_field=ULInt32('length')),            
+            PascalString('SecurityPolicyUri', 
+                          length_field=ULInt32('length')),            
             SLInt32('SenderCertificateLength'),
-            Bytes('SenderCertificate', lambda ctx:ctx['SenderCertificateLength']),            
+            Bytes('SenderCertificate', 
+                  lambda ctx:ctx['SenderCertificateLength']),            
             SLInt32('ReceiverCertificateThumbprintLength'),
-            Bytes('ReceiverCertificateThumbprint', lambda ctx:ctx['ReceiverCertificateThumbprintLength']),
+            Bytes('ReceiverCertificateThumbprint', 
+                  lambda ctx:ctx['ReceiverCertificateThumbprintLength']),
             ULInt32('SequenceNumber'),
             ULInt32('RequestId'),
             ULInt8('EncodingByte'),
             ULInt8('NameSpace'),
             ULInt16('Identifier'),
-# NOTE: no Encoding and Length fields for this ExtensionObjectPrefix
-# The length is defined by the Identifier
             ULInt8('AuthenticationTokenEncodingByte'),
             ULInt8('AuthenticationTokenIdentifier'),
             ULInt64('TimeStamp'),
             ULInt32('RequestHandle'),
             ULInt32('ReturnDiagnostics'),
-            PascalString('AuditEntryId', length_field=ULInt32('length'), encoding='utf8'),
+            PascalString('AuditEntryId', 
+                         length_field=ULInt32('length'), 
+                         encoding='utf8'),
             ULInt32('TimeOutHint'),
-# AdditionalHeader
-            ULInt8('AHEncodingByte'),
+            ULInt8('AHEncodingByte'), # AH = AdditionalHeader
             ULInt8('AHIdentifier'),
             ULInt8('AHEncoding'),
-    #        SLInt32('AHLength'),
-
             ULInt32('ProtocolVersion'),
             ULInt32('RequestType'),
             ULInt32('SecurityMode'),
@@ -78,12 +70,12 @@
             IsFinal           = 'F'   ,
             MessageSize       =  1191   ,
             SecureChannelId   =  0   ,
-            SecurityPolicyUri = 'http://opcfoundation.org/UA/securitypolicy#Basic128Rsa15',
-
-            SenderCertificateLength = len(dercert),
-            SenderCertificate = dercert,
-            ReceiverCertificateThumbprintLength = len(ThumbPrint),
-            ReceiverCertificateThumbprint = ThumbPrint,
+            SecurityPolicyUri = 
+    'http://opcfoundation.org/UA/securitypolicy#Basic128Rsa15',
+            SenderCertificateLength = 0, #len(dercert),
+            SenderCertificate =  '', #dercert,
+            ReceiverCertificateThumbprintLength = 0, #len(ThumbPrint),
+            ReceiverCertificateThumbprint = '', #ThumbPrint,
             SequenceNumber    =  0   ,
             RequestId         =  0   ,
             EncodingByte      =  1   ,
@@ -91,23 +83,19 @@
             Identifier        =  446   ,
             AuthenticationTokenEncodingByte = 0,
             AuthenticationTokenIdentifier   = 0,
-            TimeStamp = 1000000, # needs work
-
+            TimeStamp = 129839102184810000,
             RequestHandle     = 1,
             ReturnDiagnostics = 0,
             AuditEntryId      = u'This is an audit entry' ,
-            TimeOutHint       = 0 ,
-#AdditionalHeader
-            AHEncodingByte    = 0 ,
-            AHIdentifier      = 0 ,
-            AHEncoding        = 0 ,
-
-            ProtocolVersion   =  1   ,
+            TimeOutHint       = 1000 , 
+            AHEncodingByte    = 0 , # 2-byte NodeId
+            AHIdentifier      = 0 , # placeholder extensionObject
+            AHEncoding        = 0 , # the extensionObject has no body
+            ProtocolVersion   =  0   ,
             RequestType       =  0   , # 0 = ISSUE NEW
             SecurityMode      =  1   , # 1 = NONE
             ClientNonce       =   0   , #bytestring !!
-            RequestedLifetime = 20,
-# add padding and signature
+            RequestedLifetime = 60000,
         )
 
 packed_data = c.build(x)
@@ -129,3 +117,158 @@
     print &gt;&gt;sys.stderr, 'closing socket'
     sock.close()
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+----
+
+## 2. NodeIds ##
+
+    Identifier        =  446   ,
+
+OPC ua message are encoded as an ExtensionObject. The NodeId identifier is used to identify the type of message. The Identifier for the OpenSecureChannel request message is 446. An overview of all identifiers can be found in NodeIds.csv :  &lt;http://www.opcfoundation.org/UAPart6/NodeIds.csv&gt;. 
+
+Some remarks about the ExtensionObject prefix of the OpenSecureChannel message: 
+
+ * Wireshark decodes the namespace byte of the NodeId as 'EncodingMask'.
+ * This ExtensionObject prefix does not contain an encoding mask or length.
+
+## 3. openSSL ##
+
+&gt; The OpenSSL Project is a collaborative effort to develop a robust, commercial-grade, full-featured, and Open Source toolkit implementing the Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) protocols as well as a full-strength general purpose cryptography library. 
+
+~ &lt;http://www.openssl.org/&gt;
+
+----
+
+Some openSSL commands:
+
+Create a new private key:
+
+    openssl genrsa -out privatekey.pem 2048
+
+Create a self-signed X509 certificate with the key:
+
+    openssl req -new -x509 -key privatekey.pem -out opycua.pem -days 1
+
+Convert the PEM encoded certificate to a DER encoded certificate:
+
+    openssl x509 -in opycua.pem -outform DER -out opycua.der
+
+Create a Thumbprint (SHA1 digest) from the DER encoded certificate
+
+    openssl x509 -sha1 -in opycua.der -noout -fingerprint
+
+----
+
+WITH PYTHON:
+
+    f = open('test.pem', 'r')
+    pemcert = f.read()
+    dercert = ssl.PEM_cert_to_DER_cert(pemcert)
+    import hashlib
+    m = hashlib.sha1(dercert)
+    thumbprint = m.hexdigest()
+
+
+The x509 utility can be used to sign certificates and requests: it can thus behave like a ``mini CA''. 
+
+1.Generate a private key (but don't password protect it)
+
+    openssl genrsa -out privatekey.pem 2048
+
+Based on: &lt;http://www.openssl.org/docs/HOWTO/keys.txt&gt;
+
+    2. To generate a RSA key
+    
+    A RSA key can be used both for encryption and for signing.
+    
+    Generating a key for the RSA algorithm is quite easy, all you have to
+    do is the following:
+    
+      openssl genrsa -des3 -out privkey.pem 2048
+    
+    With this variant, you will be prompted for a protecting password.  If
+    you don't want your key to be protected by a password, remove the flag
+    '-des3' from the command line above.
+    
+        NOTE: if you intend to use the key together with a server
+        certificate, it may be a good thing to avoid protecting it
+        with a password, since that would mean someone would have to
+        type in the password every time the server needs to access
+        the key.
+    
+    The number 2048 is the size of the key, in bits.  Today, 2048 or
+    higher is recommended for RSA keys, as fewer amount of bits is
+    consider insecure or to be insecure pretty soon.
+
+2. Create self signed certificate
+
+    openssl req -new -x509 -key privkey.pem -out opycua.pem -days 1
+
+
+Optional: create a certificate signing request (CSR)
+
+openssl req -new -key privatekey.pem -out cert.csr
+
+
+Convert PEM to DER like so:
+
+    openssl x509 -in opycua.pem -outform DER -out opycua.der
+
+command line options:
+http://www.openssl.org/docs/apps/x509.html#SIGNING_OPTIONS
+
+
+FINGERPRINTS
+
+ openssl x509 -sha1 -in cert.pem -noout -fingerprint
+
+
+
+
+## 4. OPC ua timeformat ##
+
+OPC ua uses a 64-bit time with 100 ns precision.
+
+&gt; a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC).
+
+Python uses POSIX time aka Unix time. 
+
+&gt; a 32-bit value representing the number of seconds that have elapsed since January 1, 1970 (UTC).
+
+### Conversion ###
+
+&gt; opcua_time = (unix_time * 10000000) + 116444736000000000
+116444736000000000 = 10000000  * 60 * 60 * 24 * 365 * 369 + 89 leap days
+
+ 
+Some conversion code from: &lt;http://pydoc.net/RSFile/1.1/rsbackends._utilities&gt;
+
+    def pyint_to_double_dwords(mylong, dwordsize=32):
+            if(mylong&lt;0):
+                    raise ValueError("Positive argument required")
+    
+            uloworder = mylong &amp; (2**dwordsize-1)
+            uhighorder = (mylong &gt;&gt; dwordsize) &amp; (2**dwordsize-1)
+            return (uloworder, uhighorder)
+     
+    def double_dwords_to_pyint(loworder, highorder , dwordsize=32): 
+            return  (highorder &lt;&lt; dwordsize) + loworder
+     
+    def win32_filetime_to_python_timestamp(loworder, highorder):
+        win32_timestamp = double_dwords_to_pyint(loworder, highorder)
+        return float(win32_timestamp - 116444736000000000) / 10000000
+     
+    def python_timestamp_to_win32_filetime(pytimestamp):
+        win32_timestamp = int((10000000 * pytimestamp) + 116444736000000000)
+        (loworder, highorder) = pyint_to_double_dwords(win32_timestamp)
+        return (loworder, highorder)
+
+
+Some related articles are over here:
+
+ * An article on the different time formats. &lt;http://blogs.msdn.com/b/mikekelly/archive/2009/01/17/unix-time-and-windows-time.aspx&gt;
+ * Using python to parse and present 64 bit times with python. &lt;http://integriography.wordpress.com/2010/01/16/using-phython-to-parse-and-present-windows-64-bit-timestamps/&gt;
+ * PEP410 was rejected. &lt;http://www.python.org/dev/peps/pep-0410/&gt;
+ * The windows FILETIME structure. &lt;http://msdn.microsoft.com/en-us/library/windows/desktop/ms724284%28v=vs.85%29.aspx&gt;
+
+
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Tue, 12 Jun 2012 21:26:10 -0000</pubDate><guid>https://sourceforge.nete96f05e351219993d219f21f67501e5b17c286df</guid></item><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description>&lt;pre&gt;&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Fri, 08 Jun 2012 22:44:03 -0000</pubDate><guid>https://sourceforge.net1fc19a9b53631fab40d281559b3941100c93e0ba</guid></item><item><title>WikiPage Open Sesame! modified by Jan Costermans</title><link>https://sourceforge.net/p/opycua/wiki/Open%2520Sesame%2521/</link><description># Open Sesame! #

&gt; (Arabic إفتح يا سمسم iftaḥ ya simsim 'open, O sesame') 
is a magical phrase in the story of "Ali Baba and the Forty Thieves" 
in One Thousand and One Nights. It opens the mouth of a cave 
in which forty thieves have hidden a treasure; 
"Close Sesame" re-seals the cave.

~Wikipedia &lt;http://en.wikipedia.org/wiki/Open_Sesame_%28phrase%29&gt;

-----------------------------------------------------------------

NEEDS SOMEORE INFO !!

-----------------------------------------------------------------

## OpenSecureChannel Request ##

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import socket
import sys
import ssl
# numpy for 64 bit time ?? --&gt; does not change anything.
#import numpy
# numpy.int64(12345)

from construct import *


f = open('test.pem', 'r')
pemcert = f.read()
dercert = ssl.PEM_cert_to_DER_cert(pemcert)

ThumbPrint = '07:6B:16:EA:32:27:DC:54:72:EA:FD:D0:ED:FD:4B:00:C5:BD:12:6C'


c = Struct('OPC UASC OpenSecureChannel Request',

            String('MessageType', 3),
            String('IsFinal', 1),
            ULInt32('MessageSize'),
            ULInt32('SecureChannelId'),
            PascalString('SecurityPolicyUri', length_field=ULInt32('length')),            
            SLInt32('SenderCertificateLength'),
            Bytes('SenderCertificate', lambda ctx:ctx['SenderCertificateLength']),            
            SLInt32('ReceiverCertificateThumbprintLength'),
            Bytes('ReceiverCertificateThumbprint', lambda ctx:ctx['ReceiverCertificateThumbprintLength']),
            ULInt32('SequenceNumber'),
            ULInt32('RequestId'),
            ULInt8('EncodingByte'),
            ULInt8('NameSpace'),
            ULInt16('Identifier'),
# NOTE: no Encoding and Length fields for this ExtensionObjectPrefix
# The length is defined by the Identifier
            ULInt8('AuthenticationTokenEncodingByte'),
            ULInt8('AuthenticationTokenIdentifier'),
            ULInt64('TimeStamp'),
            ULInt32('RequestHandle'),
            ULInt32('ReturnDiagnostics'),
            PascalString('AuditEntryId', length_field=ULInt32('length'), encoding='utf8'),
            ULInt32('TimeOutHint'),
# AdditionalHeader
            ULInt8('AHEncodingByte'),
            ULInt8('AHIdentifier'),
            ULInt8('AHEncoding'),
    #        SLInt32('AHLength'),

            ULInt32('ProtocolVersion'),
            ULInt32('RequestType'),
            ULInt32('SecurityMode'),
            ULInt32('ClientNonce'),
            ULInt32('RequestedLifetime'),
        )


x = Container(
            MessageType       = 'OPN' ,
            IsFinal           = 'F'   ,
            MessageSize       =  1191   ,
            SecureChannelId   =  0   ,
            SecurityPolicyUri = 'http://opcfoundation.org/UA/securitypolicy#Basic128Rsa15',

            SenderCertificateLength = len(dercert),
            SenderCertificate = dercert,
            ReceiverCertificateThumbprintLength = len(ThumbPrint),
            ReceiverCertificateThumbprint = ThumbPrint,
            SequenceNumber    =  0   ,
            RequestId         =  0   ,
            EncodingByte      =  1   ,
            NameSpace         =  0   ,
            Identifier        =  446   ,
            AuthenticationTokenEncodingByte = 0,
            AuthenticationTokenIdentifier   = 0,
            TimeStamp = 1000000, # needs work

            RequestHandle     = 1,
            ReturnDiagnostics = 0,
            AuditEntryId      = u'This is an audit entry' ,
            TimeOutHint       = 0 ,
#AdditionalHeader
            AHEncodingByte    = 0 ,
            AHIdentifier      = 0 ,
            AHEncoding        = 0 ,

            ProtocolVersion   =  1   ,
            RequestType       =  0   , # 0 = ISSUE NEW
            SecurityMode      =  1   , # 1 = NONE
            ClientNonce       =   0   , #bytestring !!
            RequestedLifetime = 20,
# add padding and signature
        )

packed_data = c.build(x)


# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('localhost', 4840)

sock.connect(server_address)

try:
    
    # Send data
    print &gt;&gt;sys.stderr, 'sending "%s"' % packed_data
    sock.sendall(packed_data)

finally:
    print &gt;&gt;sys.stderr, 'closing socket'
    sock.close()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Jan Costermans</dc:creator><pubDate>Fri, 08 Jun 2012 22:31:01 -0000</pubDate><guid>https://sourceforge.net67bdc54ea0c0cc6e54c03cefabf135ba595ad09f</guid></item></channel></rss>