Bug 1244960 - FIDO u2f NSSToken (Part 2): Use Attestation Certificates. r=keeler
authorJ.C. Jones <jjones@mozilla.com>
Mon, 28 Mar 2016 18:55:52 -0700
changeset 331367 f7c7877b38a2adaf8c1bb948ee4fe22555da122c
parent 331366 df215bb5bb8c5ad777086d47cad0b26308f1d222
child 331368 d7edcf25d8396f3af13337cb717b706e84b7712c
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler
bugs1244960
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1244960 - FIDO u2f NSSToken (Part 2): Use Attestation Certificates. r=keeler - Add an ephemeral self-signed Attestation Cert to NSSToken - A new one is generated at each call to Register; this is allowed by the protocol, and avoids fingerprinting if the NSSToken is in use. - This now passes at https://u2fdemo.appspot.com/ MozReview-Commit-ID: Aq61MuX9oSD
dom/u2f/tests/mochitest.ini
dom/u2f/tests/pkijs/LICENSE
dom/u2f/tests/pkijs/README
dom/u2f/tests/pkijs/asn1.js
dom/u2f/tests/pkijs/common.js
dom/u2f/tests/pkijs/x509_schema.js
dom/u2f/tests/pkijs/x509_simpl.js
dom/u2f/tests/test_frame.html
dom/u2f/tests/test_frame_register_sign.html
--- a/dom/u2f/tests/mochitest.ini
+++ b/dom/u2f/tests/mochitest.ini
@@ -10,12 +10,16 @@ support-files =
   test_frame_appid_facet_subdomain.html
   facet/facetList.txt
   facet/facetList-good
   facet/facetList-good^headers^
   facet/facetList-no_overlap
   facet/facetList-no_overlap^headers^
   facet/facetList-invalid_format
   facet/facetList-invalid_format^headers^
+  pkijs/common.js
+  pkijs/asn1.js
+  pkijs/x509_schema.js
+  pkijs/x509_simpl.js
 
 [test_util_methods.html]
 [test_no_token.html]
 [test_frame.html]
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, GMO GlobalSign
+Copyright (c) 2015, Peculiar Ventures
+All rights reserved.
+
+Author 2014-2015, Yury Strozhevsky
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or
+  other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/README
@@ -0,0 +1,1 @@
+PKIjs and ASN1js are from https://pkijs.org/ and https://asn1js.org/.
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/asn1.js
@@ -0,0 +1,5466 @@
+/*
+ * Copyright (c) 2014, GMO GlobalSign
+ * Copyright (c) 2015, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software without 
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE. 
+ *
+ */
+(
+function(in_window)
+{
+    //**************************************************************************************
+    // #region Declaration of global variables 
+    //**************************************************************************************
+    // #region "org" namespace 
+    if(typeof in_window.org === "undefined")
+        in_window.org = {};
+    else
+    {
+        if(typeof in_window.org !== "object")
+            throw new Error("Name org already exists and it's not an object");
+    }
+    // #endregion 
+
+    // #region "org.pkijs" namespace 
+    if(typeof in_window.org.pkijs === "undefined")
+        in_window.org.pkijs = {};
+    else
+    {
+        if(typeof in_window.org.pkijs !== "object")
+            throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs));
+    }
+    // #endregion 
+
+    // #region "org.pkijs.asn1" namespace 
+    if(typeof in_window.org.pkijs.asn1 === "undefined")
+        in_window.org.pkijs.asn1 = {};
+    else
+    {
+        if(typeof in_window.org.pkijs.asn1 !== "object")
+            throw new Error("Name org.pkijs.asn1 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.asn1));
+    }
+    // #endregion 
+
+    // #region "local" namespace 
+    var local = {};
+    // #endregion   
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Aux-functions 
+    //**************************************************************************************
+    function util_frombase(input_buffer, input_base)
+    {
+        /// <summary>Convert number from 2^base to 2^10</summary>
+        /// <param name="input_buffer" type="Uint8Array">Array of bytes representing the number to convert</param>
+        /// <param name="input_base" type="Number">The base of initial number</param>
+
+        var result = 0; 
+
+        for(var i = (input_buffer.length - 1); i >= 0; i-- )
+            result += input_buffer[(input_buffer.length - 1) - i] * Math.pow(2, input_base * i);
+
+        return result;
+    }
+    //**************************************************************************************
+    function util_tobase(value, base, reserved)
+    {
+        /// <summary>Convert number from 2^10 to 2^base</summary>
+        /// <param name="value" type="Number">The number to convert</param>
+        /// <param name="base" type="Number">The base for 2^base</param>
+        /// <param name="reserved" type="Number">Pre-defined number of bytes in output array (-1 = limited by function itself)</param>
+
+        reserved = reserved || (-1);
+
+        var result = 0;
+        var biggest = Math.pow(2, base);
+
+        for(var i = 1; i < 8; i++)
+        {
+            if(value < biggest)
+            {
+                var ret_buf;
+
+                if( reserved < 0 )
+                {
+                    ret_buf = new ArrayBuffer(i);
+                    result = i;
+                }
+                else
+                {
+                    if(reserved < i)
+                        return (new ArrayBuffer(0));
+
+                    ret_buf = new ArrayBuffer(reserved);
+
+                    result = reserved;
+                }
+
+                var ret_view = new Uint8Array(ret_buf);
+
+                for(var j = ( i - 1 ); j >= 0; j-- )
+                {
+                    var basis = Math.pow(2, j * base);
+
+                    ret_view[ result - j - 1 ] = Math.floor( value / basis );
+                    value -= ( ret_view[ result - j - 1 ] ) * basis;
+                }
+
+                return ret_buf;
+            }
+
+            biggest *= Math.pow(2, base);
+        }
+    }
+    //**************************************************************************************
+    function util_encode_tc(value)
+    {
+        /// <summary>Encode integer value to "two complement" format</summary>
+        /// <param name="value" type="Number">Value to encode</param>
+
+        var mod_value = (value < 0) ? (value * (-1)) : value;
+        var big_int = 128;
+
+        for(var i = 1; i < 8; i++) 
+        {
+            if( mod_value <= big_int )
+            {
+                if( value < 0 )
+                {
+                    var small_int = big_int - mod_value;
+
+                    var ret_buf = util_tobase( small_int, 8, i );
+                    var ret_view = new Uint8Array(ret_buf);
+
+                    ret_view[ 0 ] |= 0x80;
+
+                    return ret_buf;
+                }
+                else
+                {
+                    var ret_buf = util_tobase( mod_value, 8, i );
+                    var ret_view = new Uint8Array(ret_buf);
+
+                    if( ret_view[ 0 ] & 0x80 )
+                    {
+                        var temp_buf = util_copybuf(ret_buf);
+                        var temp_view = new Uint8Array(temp_buf);
+
+                        ret_buf = new ArrayBuffer( ret_buf.byteLength + 1 );
+                        ret_view = new Uint8Array(ret_buf);
+
+                        for(var k = 0; k < temp_buf.byteLength; k++)
+                            ret_view[k + 1] = temp_view[k];
+
+                        ret_view[0] = 0x00;
+                    }
+
+                    return ret_buf;
+                }
+            }
+
+            big_int *= Math.pow(2, 8);
+        }
+
+        return (new ArrayBuffer(0));
+    }
+    //**************************************************************************************
+    function util_decode_tc()
+    {
+        /// <summary>Decoding of "two complement" values</summary>
+        /// <remarks>The function must be called in scope of instance of "hex_block" class ("value_hex" and "warnings" properties must be present)</remarks>
+
+        var buf = new Uint8Array(this.value_hex);
+
+        if(this.value_hex.byteLength >= 2)
+        {
+            var condition_1 = (buf[0] == 0xFF) && (buf[1] & 0x80);
+            var condition_2 = (buf[0] == 0x00) && ((buf[1] & 0x80) == 0x00);
+
+            if(condition_1 || condition_2)
+                this.warnings.push("Needlessly long format");
+        }
+
+        // #region Create big part of the integer
+        var big_int_buffer = new ArrayBuffer(this.value_hex.byteLength);
+        var big_int_view = new Uint8Array(big_int_buffer);
+        for(var i = 0; i < this.value_hex.byteLength; i++)
+            big_int_view[i] = 0;
+
+        big_int_view[0] = (buf[0] & 0x80); // mask only the biggest bit
+
+        var big_int = util_frombase(big_int_view, 8);
+        // #endregion   
+
+        // #region Create small part of the integer 
+        var small_int_buffer = new ArrayBuffer(this.value_hex.byteLength);
+        var small_int_view = new Uint8Array(small_int_buffer);
+        for(var j = 0; j < this.value_hex.byteLength; j++)
+            small_int_view[j] = buf[j];
+
+        small_int_view[0] &= 0x7F; // mask biggest bit
+
+        var small_int = util_frombase(small_int_view, 8);
+        // #endregion 
+
+        return (small_int - big_int);
+    }
+    //**************************************************************************************
+    function util_copybuf(input_buffer)
+    {
+        /// <summary>Creating a copy of input ArrayBuffer</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ArrayBuffer for coping</param>
+
+        if(check_buffer_params(input_buffer, 0, input_buffer.byteLength) === false)
+            return (new ArrayBuffer(0));
+
+        var input_view = new Uint8Array(input_buffer);
+
+        var ret_buf = new ArrayBuffer(input_buffer.byteLength);
+        var ret_view = new Uint8Array(ret_buf);
+
+        for(var i = 0; i < input_buffer.byteLength; i++)
+            ret_view[i] = input_view[i];
+
+        return ret_buf;
+    }
+    //**************************************************************************************
+    function util_copybuf_offset(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Creating a copy of input ArrayBuffer</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ArrayBuffer for coping</param>
+
+        if(check_buffer_params(input_buffer, input_offset, input_length) === false)
+            return (new ArrayBuffer(0));
+
+        var input_view = new Uint8Array(input_buffer, input_offset, input_length);
+
+        var ret_buf = new ArrayBuffer(input_length);
+        var ret_view = new Uint8Array(ret_buf);
+
+        for(var i = 0; i < input_length; i++)
+            ret_view[i] = input_view[i];
+
+        return ret_buf;
+    }
+    //**************************************************************************************
+    function util_concatbuf(input_buf1, input_buf2)
+    {
+        /// <summary>Concatenate two ArrayBuffers</summary>
+        /// <param name="input_buf1" type="ArrayBuffer">First ArrayBuffer (first part of concatenated array)</param>
+        /// <param name="input_buf2" type="ArrayBuffer">Second ArrayBuffer (second part of concatenated array)</param>
+
+        var input_view1 = new Uint8Array(input_buf1);
+        var input_view2 = new Uint8Array(input_buf2);
+
+        var ret_buf = new ArrayBuffer(input_buf1.byteLength + input_buf2.byteLength);
+        var ret_view = new Uint8Array(ret_buf);
+
+        for(var i = 0; i < input_buf1.byteLength; i++)
+            ret_view[i] = input_view1[i];
+
+        for(var j = 0; j < input_buf2.byteLength; j++)
+            ret_view[input_buf1.byteLength + j] = input_view2[j];
+
+        return ret_buf;
+    }
+    //**************************************************************************************
+    function check_buffer_params(input_buffer, input_offset, input_length)
+    {
+        if((input_buffer instanceof ArrayBuffer) === false)
+        {
+            this.error = "Wrong parameter: input_buffer must be \"ArrayBuffer\"";
+            return false;
+        }
+
+        if(input_buffer.byteLength === 0)
+        {
+            this.error = "Wrong parameter: input_buffer has zero length";
+            return false;
+        }
+
+        if(input_offset < 0)
+        {
+            this.error = "Wrong parameter: input_offset less than zero";
+            return false;
+        }
+
+        if(input_length < 0)
+        {
+            this.error = "Wrong parameter: input_length less than zero";
+            return false;
+        }
+
+        if((input_buffer.byteLength - input_offset - input_length) < 0)
+        {
+            this.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
+            return false;
+        }
+
+        return true;
+    }
+    //**************************************************************************************
+    function to_hex_codes(input_buffer, input_offset, input_lenght)
+    {
+        if(check_buffer_params(input_buffer, input_offset, input_lenght) === false)
+            return "";
+
+        var result = "";
+
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_lenght);
+        
+        for(var i = 0; i < int_buffer.length; i++)
+        {
+            var str = int_buffer[i].toString(16).toUpperCase();
+            result = result + ((str.length === 1) ? " 0" : " ") + str;
+        }
+
+        return result;
+    }
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of base block class 
+    //**************************************************************************************
+    local.base_block =
+    function()
+    {
+        /// <summary>General class of all ASN.1 blocks</summary>
+
+        if(arguments[0] instanceof Object)
+        {
+            this.block_length = in_window.org.pkijs.getValue(arguments[0], "block_length", 0);
+            this.error = in_window.org.pkijs.getValue(arguments[0], "error", new String());
+            this.warnings = in_window.org.pkijs.getValue(arguments[0], "warnings", new Array());
+            if("value_before_decode" in arguments[0])
+                this.value_before_decode = util_copybuf(arguments[0].value_before_decode);
+            else
+                this.value_before_decode = new ArrayBuffer(0);
+        }
+        else
+        {
+            this.block_length = 0;
+            this.error = new String();
+            this.warnings = new Array();
+            /// <field>Copy of the value of incoming ArrayBuffer done before decoding</field>
+            this.value_before_decode = new ArrayBuffer(0);
+        }
+    };
+    //**************************************************************************************
+    local.base_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "base_block";
+    };
+    //**************************************************************************************
+    local.base_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        return {
+            block_name: local.base_block.prototype.block_name.call(this),
+            block_length: this.block_length,
+            error: this.error,
+            warnings: this.warnings,
+            value_before_decode: in_window.org.pkijs.bufferToHexCodes(this.value_before_decode, 0, this.value_before_decode.byteLength)
+        };
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of hex block class 
+    //**************************************************************************************
+    local.hex_block =
+    function()
+    {
+        /// <summary>Descendant of "base_block" with internal ArrayBuffer. Need to have it in case it is not possible to store ASN.1 value in native formats</summary>
+
+        local.base_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+                this.value_hex = new ArrayBuffer(0);
+        }
+        else
+        {
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(0);
+        }
+    };
+    //**************************************************************************************
+    local.hex_block.prototype = new local.base_block();
+    local.hex_block.constructor = local.hex_block;
+    //**************************************************************************************
+    local.hex_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "hex_block";
+    };
+    //**************************************************************************************
+    local.hex_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.warnings.push("Zero buffer length");
+            return input_offset;
+        }
+        // #endregion 
+
+        // #region Copy input buffer to internal buffer 
+        this.value_hex = new ArrayBuffer(input_length);
+        var view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < int_buffer.length; i++)
+            view[i] = int_buffer[i];
+        // #endregion 
+
+        this.block_length = input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    local.hex_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_hex_only !== true)
+        {
+            this.error = "Flag \"is_hex_only\" is not set, abort";
+            return (new ArrayBuffer(0));
+        }
+
+        var ret_buf = new ArrayBuffer(this.value_hex.byteLength);
+
+        if(size_only === true)
+            return ret_buf;
+
+        var ret_view = new Uint8Array(ret_buf);
+        var cur_view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < cur_view.length; i++)
+            ret_view[i] = cur_view[i];
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    local.hex_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.base_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.hex_block.prototype.block_name.call(this);
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of identification block class 
+    //**************************************************************************************
+    local.identification_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 "identification block"</summary>
+
+        local.hex_block.call(this, arguments[0]);
+
+        this.tag_class = (-1);
+        this.tag_number = (-1);
+        this.is_constructed = false;
+
+        if(arguments[0] instanceof Object)
+        {
+            if("id_block" in arguments[0])
+            {
+                // #region Properties from hex_block class 
+                this.is_hex_only = in_window.org.pkijs.getValue(arguments[0].id_block, "is_hex_only", false);
+                this.value_hex = in_window.org.pkijs.getValue(arguments[0].id_block, "value_hex", new ArrayBuffer(0));
+                // #endregion   
+
+                this.tag_class = in_window.org.pkijs.getValue(arguments[0].id_block, "tag_class", (-1));
+                this.tag_number = in_window.org.pkijs.getValue(arguments[0].id_block, "tag_number", (-1));
+                this.is_constructed = in_window.org.pkijs.getValue(arguments[0].id_block, "is_constructed", false);
+            }
+        }
+    };
+    //**************************************************************************************
+    local.identification_block.prototype = new local.hex_block();
+    local.identification_block.constructor = local.identification_block;
+    //**************************************************************************************
+    local.identification_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "identification_block";
+    };
+    //**************************************************************************************
+    local.identification_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var first_octet = 0;
+
+        switch(this.tag_class)
+        {
+            case 1:
+                first_octet |= 0x00; // UNIVERSAL
+                break;
+            case 2:
+                first_octet |= 0x40; // APPLICATION
+                break;
+            case 3:
+                first_octet |= 0x80; // CONTEXT-SPECIFIC
+                break;
+            case 4:
+                first_octet |= 0xC0; // PRIVATE
+                break;
+            default:
+                this.error = "Unknown tag class";
+                return (new ArrayBuffer(0));
+        }
+
+        if(this.is_constructed)
+            first_octet |= 0x20;
+
+        if((this.tag_number < 31) && (!this.is_hex_only))
+        {
+            var ret_buf = new ArrayBuffer(1);
+            var ret_view = new Uint8Array(ret_buf);
+
+            if(!size_only)
+            {
+                var number = this.tag_number;
+                number &= 0x1F;
+                first_octet |= number;
+
+                ret_view[0] = first_octet;
+            }
+
+            return ret_buf;
+        }
+        else
+        {
+            if(this.is_hex_only === false)
+            {
+                var encoded_buf = util_tobase(this.tag_number, 7);
+                var encoded_view = new Uint8Array(encoded_buf);
+                var size = encoded_buf.byteLength;
+
+                var ret_buf = new ArrayBuffer(size + 1);
+                var ret_view = new Uint8Array(ret_buf);
+
+                ret_view[0] = (first_octet | 0x1F);
+
+                if(!size_only)
+                {
+                    for(var i = 0; i < (size - 1) ; i++)
+                        ret_view[i + 1] = encoded_view[i] | 0x80;
+
+                    ret_view[size] = encoded_view[size - 1];
+                }
+
+                return ret_buf;
+            }
+            else
+            {
+                var ret_buf = new ArrayBuffer(this.value_hex.byteLength + 1);
+                var ret_view = new Uint8Array(ret_buf);
+
+                ret_view[0] = (first_octet | 0x1F);
+
+                if(size_only === false)
+                {
+                    var cur_view = new Uint8Array(this.value_hex);
+
+                    for(var i = 0; i < (cur_view.length - 1); i++)
+                        ret_view[i + 1] = cur_view[i] | 0x80;
+
+                    ret_view[this.value_hex.byteLength] = cur_view[cur_view.length - 1];
+                }
+
+                return ret_buf;
+            }
+        }
+    };
+    //**************************************************************************************
+    local.identification_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.error = "Zero buffer length";
+            return (-1);
+        }
+        // #endregion 
+
+        // #region Find tag class 
+        var tag_class_mask = int_buffer[0] & 0xC0;
+
+        switch(tag_class_mask)
+        {
+            case 0x00:
+                this.tag_class = (1); // UNIVERSAL
+                break;
+            case 0x40:
+                this.tag_class = (2); // APPLICATION
+                break;
+            case 0x80:
+                this.tag_class = (3); // CONTEXT-SPECIFIC
+                break;
+            case 0xC0:
+                this.tag_class = (4); // PRIVATE
+                break;
+            default:
+                this.error = "Unknown tag class";
+                return ( -1 );
+        }
+        // #endregion 
+
+        // #region Find it's constructed or not 
+        this.is_constructed = (int_buffer[0] & 0x20) == 0x20;
+        // #endregion 
+
+        // #region Find tag number 
+        this.is_hex_only = false;
+
+        var tag_number_mask = int_buffer[0] & 0x1F;
+
+        // #region Simple case (tag number < 31)
+        if(tag_number_mask != 0x1F) 
+        {
+            this.tag_number = (tag_number_mask);
+            this.block_length = 1;
+        }
+            // #endregion 
+        // #region Tag number bigger or equal to 31 
+        else
+        {
+            var count = 1;
+
+            this.value_hex = new ArrayBuffer(255);
+            var tag_number_buffer_max_length = 255;
+            var int_tag_number_buffer = new Uint8Array(this.value_hex);
+
+            while(int_buffer[count] & 0x80)
+            {
+                int_tag_number_buffer[count - 1] = int_buffer[count] & 0x7F;
+                count++;
+
+                if(count >= int_buffer.length)
+                {
+                    this.error = "End of input reached before message was fully decoded";
+                    return (-1);
+                }
+
+                // #region In case if tag number length is greater than 255 bytes (rare but possible case)
+                if(count == tag_number_buffer_max_length)
+                {
+                    tag_number_buffer_max_length += 255;
+
+                    var temp_buffer = new ArrayBuffer(tag_number_buffer_max_length);
+                    var temp_buffer_view = new Uint8Array(temp_buffer);
+
+                    for(var i = 0; i < int_tag_number_buffer.length; i++)
+                        temp_buffer_view[i] = int_tag_number_buffer[i];
+
+                    this.value_hex = new ArrayBuffer(tag_number_buffer_max_length);
+                    int_tag_number_buffer = new Uint8Array(this.value_hex);
+                }
+                // #endregion 
+            }
+
+            this.block_length = (count + 1);
+            int_tag_number_buffer[count - 1] = int_buffer[count] & 0x7F; // Write last byte to buffer
+
+            // #region Cut buffer 
+            var temp_buffer = new ArrayBuffer(count);
+            var temp_buffer_view = new Uint8Array(temp_buffer);
+            for(var i = 0; i < count; i++)
+                temp_buffer_view[i] = int_tag_number_buffer[i];
+
+            this.value_hex = new ArrayBuffer(count);
+            int_tag_number_buffer = new Uint8Array(this.value_hex);
+            int_tag_number_buffer.set(temp_buffer_view);
+            // #endregion 
+
+            // #region Try to convert long tag number to short form 
+            if(this.block_length <= 9)
+                this.tag_number = util_frombase(int_tag_number_buffer, 7);
+            else
+            {
+                this.is_hex_only = true;
+                this.warnings.push("Tag too long, represented as hex-coded");
+            }
+            // #endregion 
+        }
+        // #endregion 
+        // #endregion 
+
+        // #region Check if constructed encoding was using for primitive type 
+        if(((this.tag_class == 1)) &&
+            (this.is_constructed))
+        {
+            switch(this.tag_number)
+            {
+                case 1:  // BOOLEAN
+                case 2:  // REAL
+                case 5:  // NULL
+                case 6:  // OBJECT IDENTIFIER
+                case 9:  // REAL
+                case 14: // TIME
+                case 23:
+                case 24:
+                case 31:
+                case 32:
+                case 33:
+                case 34:
+                    this.error = "Constructed encoding used for primitive type";
+                    return (-1);
+                default:
+                    ;
+            }
+        }
+        // #endregion 
+
+        return ( input_offset + this.block_length ); // Return current offset in input buffer
+    };
+    //**************************************************************************************
+    local.identification_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.identification_block.prototype.block_name.call(this);
+        _object.tag_class = this.tag_class;
+        _object.tag_number = this.tag_number;
+        _object.is_constructed = this.is_constructed;
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of length block class 
+    //**************************************************************************************
+    local.length_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 "length block"</summary>
+
+        local.base_block.call(this, arguments[0]);
+
+        this.is_indefinite_form = false;
+        this.long_form_used = false;
+        this.length = (0);
+
+        if(arguments[0] instanceof Object)
+        {
+            if("len_block" in arguments[0])
+            {
+                this.is_indefinite_form = in_window.org.pkijs.getValue(arguments[0].len_block, "is_indefinite_form", false);
+                this.long_form_used = in_window.org.pkijs.getValue(arguments[0].len_block, "long_form_used", false);
+                this.length = in_window.org.pkijs.getValue(arguments[0].len_block, "length", 0);
+            }
+        }
+    };
+    //**************************************************************************************
+    local.length_block.prototype = new local.base_block();
+    local.length_block.constructor = local.length_block;
+    //**************************************************************************************
+    local.length_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "length_block";
+    };
+    //**************************************************************************************
+    local.length_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.error = "Zero buffer length";
+            return (-1);
+        }
+
+        if(int_buffer[0] == 0xFF)
+        {
+            this.error = "Length block 0xFF is reserved by standard";
+            return (-1);
+        }
+        // #endregion 
+
+        // #region Check for length form type 
+        this.is_indefinite_form = int_buffer[0] == 0x80;
+        // #endregion 
+
+        // #region Stop working in case of indefinite length form 
+        if(this.is_indefinite_form == true)
+        {
+            this.block_length = 1;
+            return (input_offset + this.block_length);
+        }
+        // #endregion 
+
+        // #region Check is long form of length encoding using 
+        this.long_form_used = !!(int_buffer[0] & 0x80);
+        // #endregion 
+
+        // #region Stop working in case of short form of length value 
+        if(this.long_form_used == false)
+        {
+            this.length = (int_buffer[0]);
+            this.block_length = 1;
+            return (input_offset + this.block_length);
+        }
+        // #endregion 
+
+        // #region Calculate length value in case of long form 
+        var count = int_buffer[0] & 0x7F;
+
+        if(count > 8) // Too big length value
+        {
+            this.error = "Too big integer";
+            return (-1);
+        }
+
+        if((count + 1) > int_buffer.length)
+        {
+            this.error = "End of input reached before message was fully decoded";
+            return (-1);
+        }
+
+        var length_buffer_view = new Uint8Array(count);
+
+        for(var i = 0; i < count; i++)
+            length_buffer_view[i] = int_buffer[i + 1];
+
+        if(length_buffer_view[count - 1] == 0x00)
+            this.warnings.push("Needlessly long encoded length");
+
+        this.length = util_frombase(length_buffer_view, 8);
+
+        if(this.long_form_used && (this.length <= 127))
+            this.warnings.push("Unneccesary usage of long length form");
+
+        this.block_length = count + 1;
+        // #endregion 
+
+        return (input_offset + this.block_length); // Return current offset in input buffer
+    };
+    //**************************************************************************************
+    local.length_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.length > 127)
+            this.long_form_used = true;
+
+        if(this.is_indefinite_form)
+        {
+            var ret_buf = new ArrayBuffer(1);
+
+            if(size_only === false)
+            {
+                var ret_view = new Uint8Array(ret_buf);
+                ret_view[0] = 0x80;
+            }
+
+            return ret_buf;
+        }
+
+        if(this.long_form_used === true)
+        {
+            var encoded_buf = util_tobase(this.length, 8);
+
+            if(encoded_buf.byteLength > 127)
+            {
+                this.error = "Too big length";
+                return (new ArrayBuffer(0));
+            }
+
+            var ret_buf = new ArrayBuffer(encoded_buf.byteLength + 1);
+
+            if(size_only === true)
+                return ret_buf;
+
+            var encoded_view = new Uint8Array(encoded_buf);
+            var ret_view = new Uint8Array(ret_buf);
+
+            ret_view[0] = encoded_buf.byteLength | 0x80;
+
+            for(var i = 0; i < encoded_buf.byteLength; i++)
+                ret_view[i + 1] = encoded_view[i];
+
+            return ret_buf;
+        }
+        else
+        {
+            var ret_buf = new ArrayBuffer(1);
+
+            if(size_only === false)
+            {
+                var ret_view = new Uint8Array(ret_buf);
+
+                ret_view[0] = this.length;
+            }
+
+            return ret_buf;
+        }
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.length_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.base_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.length_block.prototype.block_name.call(this);
+        _object.is_indefinite_form = this.is_indefinite_form;
+        _object.long_form_used = this.long_form_used;
+        _object.length = this.length;
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of value block class 
+    //**************************************************************************************
+    local.value_block =
+    function()
+    {
+        /// <summary>Generic class of ASN.1 "value block"</summary>
+        local.base_block.call(this, arguments[0]);
+    };
+    //**************************************************************************************
+    local.value_block.prototype = new local.base_block();
+    local.value_block.constructor = local.value_block;
+    //**************************************************************************************
+    local.value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "value_block";
+    };
+    //**************************************************************************************
+    local.value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.base_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.value_block.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of basic ASN.1 block class 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 block (identification block + length block + value block)</summary>
+
+        local.base_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.name = in_window.org.pkijs.getValue(arguments[0], "name", "");
+            this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false);
+
+            if("primitive_schema" in arguments[0])
+                this.primitive_schema = arguments[0].primitive_schema;
+        }
+
+        this.id_block = new local.identification_block(arguments[0]);
+        this.len_block = new local.length_block(arguments[0]);
+        this.value_block = new local.value_block(arguments[0]);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype = new local.base_block();
+    in_window.org.pkijs.asn1.ASN1_block.constructor = in_window.org.pkijs.asn1.ASN1_block;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "ASN1_block";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var ret_buf;
+
+        var id_block_buf = this.id_block.toBER(size_only);
+        var value_block_size_buf = this.value_block.toBER(true);
+
+        this.len_block.length = value_block_size_buf.byteLength;
+        var len_block_buf = this.len_block.toBER(size_only);
+
+        ret_buf = util_concatbuf(id_block_buf, len_block_buf);
+
+        var value_block_buf;
+
+        if(size_only === false)
+            value_block_buf = this.value_block.toBER(size_only);
+        else
+            value_block_buf = new ArrayBuffer(this.len_block.length);
+
+        ret_buf = util_concatbuf(ret_buf, value_block_buf);
+
+        if(this.len_block.is_indefinite_form === true)
+        {
+            var indef_buf = new ArrayBuffer(2);
+
+            if(size_only === false)
+            {
+                var indef_view = new Uint8Array(indef_buf);
+
+                indef_view[0] = 0x00;
+                indef_view[1] = 0x00;
+            }
+
+            ret_buf = util_concatbuf(ret_buf, indef_buf);
+        }
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.base_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.ASN1_block.prototype.block_name.call(this);
+        _object.id_block = this.id_block.toJSON();
+        _object.len_block = this.len_block.toJSON();
+        _object.value_block = this.value_block.toJSON();
+
+        if("name" in this)
+            _object.name = this.name;
+        if("optional" in this)
+            _object.optional = this.optional;
+        if("primitive_schema" in this)
+            _object.primitive_schema = this.primitive_schema.toJSON();
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of basic block for all PRIMITIVE types 
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 value block for primitive values (non-constructive encoding)</summary>
+
+        local.value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            // #region Variables from "hex_block" class 
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+                this.value_hex = new ArrayBuffer(0);
+
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", true);
+            // #endregion 
+        }
+        else
+        {
+            // #region Variables from "hex_block" class 
+            this.value_hex = new ArrayBuffer(0);
+            this.is_hex_only = true;
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype = new local.value_block();
+    local.ASN1_PRIMITIVE_value_block.constructor = local.ASN1_PRIMITIVE_value_block;
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.warnings.push("Zero buffer length");
+            return input_offset;
+        }
+        // #endregion 
+
+        // #region Copy input buffer into internal buffer 
+        this.value_hex = new ArrayBuffer(int_buffer.length);
+        var value_hex_view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < int_buffer.length; i++)
+            value_hex_view[i] = int_buffer[i];
+        // #endregion 
+
+        this.block_length = input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        return util_copybuf(this.value_hex);
+    };
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "ASN1_PRIMITIVE_value_block";
+    };
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.ASN1_PRIMITIVE_value_block.prototype.block_name.call(this);
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+        _object.is_hex_only = this.is_hex_only;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE =
+    function()
+    {
+        /// <summary>Base class of ASN.1 block for primitive values (non-constructive encoding)</summary>
+
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.id_block.is_constructed = false;
+        this.value_block = new local.ASN1_PRIMITIVE_value_block(arguments[0]);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE.constructor = in_window.org.pkijs.asn1.ASN1_PRIMITIVE;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "PRIMITIVE";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of basic block for all CONSTRUCTED types 
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 value block for constructive values (constructive encoding)</summary>
+
+        local.value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.value = in_window.org.pkijs.getValue(arguments[0], "value", new Array());
+            this.is_indefinite_form = in_window.org.pkijs.getValue(arguments[0], "is_indefinite_form", false);
+        }
+        else
+        {
+            this.value = new Array();
+            this.is_indefinite_form = false;
+        }
+    };
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype = new local.value_block();
+    local.ASN1_CONSTRUCTED_value_block.constructor = local.ASN1_CONSTRUCTED_value_block;
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Store initial offset and length 
+        var initial_offset = input_offset;
+        var initial_length = input_length;
+        // #endregion 
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.warnings.push("Zero buffer length");
+            return input_offset;
+        }
+        // #endregion 
+
+        // #region Aux function 
+        function check_len(_indefinite_length, _length)
+        {
+            if(_indefinite_length == true)
+                return 1;
+
+            return _length;
+        }
+        // #endregion 
+
+        var current_offset = input_offset;
+
+        while(check_len(this.is_indefinite_form, input_length) > 0)
+        {
+            var return_object = fromBER_raw(input_buffer, current_offset, input_length);
+            if(return_object.offset == (-1))
+            {
+                this.error = return_object.result.error;
+                this.warnings.concat(return_object.result.warnings);
+                return (-1);
+            }
+
+            current_offset = return_object.offset;
+
+            this.block_length += return_object.result.block_length;
+            input_length -= return_object.result.block_length;
+
+            this.value.push(return_object.result);
+
+            if((this.is_indefinite_form == true) && (return_object.result.block_name() == in_window.org.pkijs.asn1.EOC.prototype.block_name()))
+                break;
+        }
+
+        if(this.is_indefinite_form == true)
+        {
+            if(this.value[this.value.length - 1].block_name() == in_window.org.pkijs.asn1.EOC.prototype.block_name())
+                this.value.pop();
+            else
+                this.warnings.push("No EOC block encoded");
+        }
+
+        // #region Copy "input_buffer" to "value_before_decode" 
+        this.value_before_decode = util_copybuf_offset(input_buffer, initial_offset, initial_length);
+        // #endregion 
+
+        return current_offset;
+    };
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var ret_buf = new ArrayBuffer(0);
+
+        for(var i = 0; i < this.value.length; i++)
+        {
+            var value_buf = this.value[i].toBER(size_only);
+            ret_buf = util_concatbuf(ret_buf, value_buf);
+        }
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "ASN1_CONSTRUCTED_value_block";
+    };
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.ASN1_CONSTRUCTED_value_block.prototype.block_name.call(this);
+        _object.is_indefinite_form = this.is_indefinite_form;
+        _object.value = new Array();
+        for(var i = 0; i < this.value.length; i++)
+            _object.value.push(this.value[i].toJSON());
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED =
+    function()
+    {
+        /// <summary>Base class of ASN.1 block for constructive values (constructive encoding)</summary>
+
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.id_block.is_constructed = true;
+        this.value_block = new local.ASN1_CONSTRUCTED_value_block(arguments[0]);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.constructor = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "CONSTRUCTED";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        this.value_block.is_indefinite_form = this.len_block.is_indefinite_form;
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 EOC type class
+    //**************************************************************************************
+    local.EOC_value_block =
+    function()
+    {
+        local.value_block.call(this, arguments[0]);
+    };
+    //**************************************************************************************
+    local.EOC_value_block.prototype = new local.value_block();
+    local.EOC_value_block.constructor = local.EOC_value_block;
+    //**************************************************************************************
+    local.EOC_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region There is no "value block" for EOC type and we need to return the same offset 
+        return input_offset;
+        // #endregion 
+    };
+    //**************************************************************************************
+    local.EOC_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.EOC_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "EOC_value_block";
+    };
+    //**************************************************************************************
+    local.EOC_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.EOC_value_block.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.EOC =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.EOC_value_block();
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 0; // EOC
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.EOC.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.EOC.constructor = local.EOC_value_block;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.EOC.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "END_OF_CONTENT";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.EOC.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.EOC.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 BOOLEAN type class
+    //**************************************************************************************
+    local.BOOLEAN_value_block =
+    function()
+    {
+        local.value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.value = in_window.org.pkijs.getValue(arguments[0], "value", false);
+
+            // #region Variables from hex_block class 
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+            {
+                this.value_hex = new ArrayBuffer(1);
+                if(this.value === true)
+                {
+                    var view = new Uint8Array(this.value_hex);
+                    view[0] = 0xFF;
+                }
+            }
+            // #endregion 
+        }
+        else
+        {
+            this.value = false;
+
+            // #region Variables from hex_block class 
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(1);
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype = new local.value_block();
+    local.BOOLEAN_value_block.constructor = local.BOOLEAN_value_block;
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        if(input_length > 1)
+            this.warnings.push("BOOLEAN value encoded in more then 1 octet");
+
+        this.value = int_buffer[0] != 0x00;
+
+        this.is_hex_only = true;
+
+        // #region Copy input buffer to internal array 
+        this.value_hex = new ArrayBuffer(int_buffer.length);
+        var view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < int_buffer.length; i++)
+            view[i] = int_buffer[i];
+        // #endregion 
+
+        this.block_length = input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        return this.value_hex;
+    };
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BOOLEAN_value_block";
+    };
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.BOOLEAN_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BOOLEAN =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.BOOLEAN_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 1; // BOOLEAN
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BOOLEAN.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.BOOLEAN.constructor = local.BOOLEAN_value_block;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BOOLEAN.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BOOLEAN";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BOOLEAN.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.BOOLEAN.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 SEQUENCE and SET type classes
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SEQUENCE =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 16; // SEQUENCE
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SEQUENCE.prototype = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED();
+    in_window.org.pkijs.asn1.SEQUENCE.constructor = in_window.org.pkijs.asn1.SEQUENCE;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SEQUENCE.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "SEQUENCE";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SEQUENCE.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.SEQUENCE.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SET =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 17; // SET
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SET.prototype = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED();
+    in_window.org.pkijs.asn1.SET.constructor = in_window.org.pkijs.asn1.SET;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SET.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "SET";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SET.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.SET.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 NULL type class 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 5; // NULL
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.NULL.constructor = in_window.org.pkijs.asn1.NULL;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "NULL";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        if(this.len_block.length > 0)
+            this.warnings.push("Non-zero length of value block for NULL type");
+
+        if(this.id_block.error.length === 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length === 0)
+            this.block_length += this.len_block.block_length;
+
+        this.block_length += input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var ret_buf = new ArrayBuffer(2);
+
+        if(size_only === true)
+            return ret_buf;
+
+        var ret_view = new Uint8Array(ret_buf);
+        ret_view[0] = 0x05;
+        ret_view[1] = 0x00;
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.NULL.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 OCTETSTRING type class 
+    //**************************************************************************************
+    local.OCTETSTRING_value_block =
+    function()
+    {
+        /// <param name="input_value_hex" type="ArrayBuffer"></param>
+        /// <param name="input_value" type="Array"></param>
+        /// <param name="input_constructed" type="Boolean"></param>
+        /// <remarks>Value for the OCTETSTRING may be as hex, as well as a constructed value.</remarks>
+        /// <remarks>Constructed values consists of other OCTETSTRINGs</remarks>
+
+        local.ASN1_CONSTRUCTED_value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.is_constructed = in_window.org.pkijs.getValue(arguments[0], "is_constructed", false);
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+                this.value_hex = new ArrayBuffer(0);
+            // #endregion 
+        }
+        else
+        {
+            this.is_constructed = false;
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(0);
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype = new local.ASN1_CONSTRUCTED_value_block();
+    local.OCTETSTRING_value_block.constructor = local.OCTETSTRING_value_block;
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = 0;
+
+        if(this.is_constructed == true)
+        {
+            this.is_hex_only = false;
+
+            result_offset = local.ASN1_CONSTRUCTED_value_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+            if(result_offset == (-1))
+                return result_offset;
+
+            for(var i = 0; i < this.value.length; i++)
+            {
+                var current_block_name = this.value[i].block_name();
+
+                if(current_block_name == in_window.org.pkijs.asn1.EOC.prototype.block_name())
+                {
+                    if(this.is_indefinite_form == true)
+                        break;
+                    else
+                    {
+                        this.error = "EOC is unexpected, OCTET STRING may consists of OCTET STRINGs only";
+                        return (-1);
+                    }
+                }
+
+                if(current_block_name != in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name())
+                {
+                    this.error = "OCTET STRING may consists of OCTET STRINGs only";
+                    return (-1);
+                }
+            }
+        }
+        else
+        {
+            this.is_hex_only = true;
+
+            result_offset = local.hex_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+            this.block_length = input_length;
+        }
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_constructed === true)
+            return local.ASN1_CONSTRUCTED_value_block.prototype.toBER.call(this, size_only);
+        else
+        {
+            var ret_buf = new ArrayBuffer(this.value_hex.byteLength);
+
+            if(size_only === true)
+                return ret_buf;
+
+            if(this.value_hex.byteLength == 0)
+                return ret_buf;
+
+            ret_buf = util_copybuf(this.value_hex);
+
+            return ret_buf;
+        }
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "OCTETSTRING_value_block";
+    };
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.ASN1_CONSTRUCTED_value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.OCTETSTRING_value_block.prototype.block_name.call(this);
+        _object.is_constructed = this.is_constructed;
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.OCTETSTRING_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 4; // OCTETSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.OCTETSTRING.constructor = in_window.org.pkijs.asn1.OCTETSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        this.value_block.is_constructed = this.id_block.is_constructed;
+        this.value_block.is_indefinite_form = this.len_block.is_indefinite_form;
+
+        // #region Ability to encode empty OCTET STRING 
+        if(input_length == 0)
+        {
+            if(this.id_block.error.length == 0)
+                this.block_length += this.id_block.block_length;
+
+            if(this.len_block.error.length == 0)
+                this.block_length += this.len_block.block_length;
+
+            return input_offset;
+        }
+        // #endregion 
+
+        return in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name =
+    function()
+    {
+        return "OCTETSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype.isEqual =
+    function(octetString)
+    {
+        /// <summaryChecking that two OCTETSTRINGs are equal></summary>
+        /// <param name="octetString" type="in_window.org.pkijs.asn1.OCTETSTRING">The OCTETSTRING to compare with</param>
+
+        // #region Check input type 
+        if((octetString instanceof in_window.org.pkijs.asn1.OCTETSTRING) == false)
+            return false;
+        // #endregion 
+
+        // #region Compare two JSON strings 
+        if(JSON.stringify(this) != JSON.stringify(octetString))
+            return false;
+        // #endregion 
+
+        return true;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 BITSTRING type class
+    //**************************************************************************************
+    local.BITSTRING_value_block =
+    function()
+    {
+        local.ASN1_CONSTRUCTED_value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.unused_bits = in_window.org.pkijs.getValue(arguments[0], "unused_bits", 0);
+            this.is_constructed = in_window.org.pkijs.getValue(arguments[0], "is_constructed", false);
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+                this.value_hex = new ArrayBuffer(0);
+
+            this.block_length = this.value_hex.byteLength;
+            // #endregion 
+        }
+        else
+        {
+            this.unused_bits = 0;
+            this.is_constructed = false;
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(0);
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype = new local.ASN1_CONSTRUCTED_value_block();
+    local.BITSTRING_value_block.constructor = local.BITSTRING_value_block;
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Ability to decode zero-length BITSTRING value 
+        if(input_length == 0)
+            return input_offset;
+        // #endregion 
+
+        var result_offset = (-1);
+
+        // #region If the BISTRING supposed to be a constructed value 
+        if(this.is_constructed == true)
+        {
+            result_offset = local.ASN1_CONSTRUCTED_value_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+            if(result_offset == (-1))
+                return result_offset;
+
+            for(var i = 0; i < this.value.length; i++)
+            {
+                var current_block_name = this.value[i].block_name();
+
+                if(current_block_name == in_window.org.pkijs.asn1.EOC.prototype.block_name())
+                {
+                    if(this.is_indefinite_form == true)
+                        break;
+                    else
+                    {
+                        this.error = "EOC is unexpected, BIT STRING may consists of BIT STRINGs only";
+                        return (-1);
+                    }
+                }
+
+                if(current_block_name != in_window.org.pkijs.asn1.BITSTRING.prototype.block_name())
+                {
+                    this.error = "BIT STRING may consists of BIT STRINGs only";
+                    return (-1);
+                }
+
+                if((this.unused_bits > 0) && (this.value[i].unused_bits > 0))
+                {
+                    this.error = "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only";
+                    return (-1);
+                }
+                else
+                {
+                    this.unused_bits = this.value[i].unused_bits;
+                    if(this.unused_bits > 7)
+                    {
+                        this.error = "Unused bits for BITSTRING must be in range 0-7";
+                        return (-1);
+                    }
+                }
+            }
+
+            return result_offset;
+        }
+            // #endregion 
+        // #region If the BITSTRING supposed to be a primitive value
+        else
+        {
+            // #region Basic check for parameters 
+            if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+                return (-1);
+            // #endregion 
+
+            var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+
+            this.unused_bits = int_buffer[0];
+            if(this.unused_bits > 7)
+            {
+                this.error = "Unused bits for BITSTRING must be in range 0-7";
+                return (-1);
+            }
+
+            // #region Copy input buffer to internal buffer 
+            this.value_hex = new ArrayBuffer(int_buffer.length - 1);
+            var view = new Uint8Array(this.value_hex);
+            for(var i = 0; i < (input_length - 1) ; i++)
+                view[i] = int_buffer[i + 1];
+            // #endregion 
+
+            this.block_length = int_buffer.length;
+
+            return (input_offset + input_length);
+        }
+        // #endregion 
+    };
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_constructed === true)
+            return local.ASN1_CONSTRUCTED_value_block.prototype.toBER.call(this, size_only);
+        else
+        {
+            if(size_only === true)
+                return (new ArrayBuffer(this.value_hex.byteLength + 1));
+
+            if(this.value_hex.byteLength == 0)
+                return (new ArrayBuffer(0));
+
+            var cur_view = new Uint8Array(this.value_hex);
+
+            var ret_buf = new ArrayBuffer(this.value_hex.byteLength + 1);
+            var ret_view = new Uint8Array(ret_buf);
+
+            ret_view[0] = this.unused_bits;
+
+            for(var i = 0; i < this.value_hex.byteLength; i++)
+                ret_view[i + 1] = cur_view[i];
+
+            return ret_buf;
+        }
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BITSTRING_value_block";
+    };
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.ASN1_CONSTRUCTED_value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.BITSTRING_value_block.prototype.block_name.call(this);
+        _object.unused_bits = this.unused_bits;
+        _object.is_constructed = this.is_constructed;
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.BITSTRING_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 3; // BITSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.BITSTRING.constructor = in_window.org.pkijs.asn1.BITSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BITSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Ability to encode empty BITSTRING 
+        if(input_length == 0)
+            return input_offset;
+        // #endregion 
+
+        this.value_block.is_constructed = this.id_block.is_constructed;
+        this.value_block.is_indefinite_form = this.len_block.is_indefinite_form;
+
+        return in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.BITSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 INTEGER type class 
+    //**************************************************************************************
+    local.INTEGER_value_block =
+    function()
+    {
+        local.value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.value_dec = in_window.org.pkijs.getValue(arguments[0], "value", 0);
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+            if("value_hex" in arguments[0])
+            {
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+
+                if(this.value_hex.byteLength >= 4) // Dummy's protection
+                    this.is_hex_only = true;
+                else
+                    this.value_dec = util_decode_tc.call(this);
+            }
+            else
+                this.value_hex = util_encode_tc(this.value_dec);
+            // #endregion 
+        }
+        else
+        {
+            this.value_dec = 0;
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(0);
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype = new local.value_block();
+    local.INTEGER_value_block.constructor = local.INTEGER_value_block;
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = local.hex_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+        if(result_offset == (-1))
+            return result_offset;
+
+        if(this.value_hex.byteLength > 4) // In JavaScript we can effectively work with 32-bit integers only
+        {
+            this.warnings.push("Too big INTEGER for decoding, hex only");
+            this.is_hex_only = true;
+        }
+        else
+            this.value_dec = util_decode_tc.call(this);
+
+        this.block_length = input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_hex_only === false)
+        {
+            var encoded_buf = util_encode_tc(this.value_dec);
+            if(encoded_buf.byteLength == 0)
+            {
+                this.error = "Error during encoding INTEGER value";
+                return (new ArrayBuffer(0));
+            }
+
+            return util_copybuf(encoded_buf);
+        }
+        else
+            return util_copybuf(this.value_hex);
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "INTEGER_value_block";
+    };
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.INTEGER_value_block.prototype.block_name.call(this);
+        _object.value_dec = this.value_dec;
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.INTEGER_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 2; // INTEGER
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.INTEGER.constructor = in_window.org.pkijs.asn1.INTEGER;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "INTEGER";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER.prototype.isEqual =
+    function()
+    {
+        /// <summary>Compare two INTEGER object, or INTEGER and ArrayBuffer objects</summary>
+        /// <returns type="Boolean"></returns>
+
+        if(arguments[0] instanceof in_window.org.pkijs.asn1.INTEGER)
+        {
+            if(this.value_block.is_hex_only && arguments[0].value_block.is_hex_only) // Compare two ArrayBuffers
+                return in_window.org.pkijs.isEqual_buffer(this.value_block.value_hex, arguments[0].value_block.value_hex);
+            else
+            {
+                if(this.value_block.is_hex_only === arguments[0].value_block.is_hex_only)
+                    return (this.value_block.value_dec == arguments[0].value_block.value_dec);
+                else
+                    return false;
+            }
+        }
+        else
+        {
+            if(arguments[0] instanceof ArrayBuffer)
+                return in_window.org.pkijs.isEqual_buffer(this.value_block.value_hex, arguments[0]);
+            else
+                return false;
+        }
+
+        return false;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.INTEGER.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 ENUMERATED type class 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ENUMERATED =
+    function()
+    {
+        in_window.org.pkijs.asn1.INTEGER.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 10; // ENUMERATED
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ENUMERATED.prototype = new in_window.org.pkijs.asn1.INTEGER();
+    in_window.org.pkijs.asn1.ENUMERATED.constructor = in_window.org.pkijs.asn1.ENUMERATED;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ENUMERATED.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "ENUMERATED";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ENUMERATED.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.INTEGER.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.ENUMERATED.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 OBJECT IDENTIFIER type class 
+    //**************************************************************************************
+    local.SID_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.value_dec = in_window.org.pkijs.getValue(arguments[0], "value_dec", -1);
+            this.is_first_sid = in_window.org.pkijs.getValue(arguments[0], "is_first_sid", false);
+        }
+        else
+        {
+            this.value_dec = (-1);
+            this.is_first_sid = false;
+        }
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype = new local.hex_block();
+    local.SID_value_block.constructor = local.SID_value_block;
+    //**************************************************************************************
+    local.SID_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "sid_block";
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        if(input_length == 0)
+            return input_offset;
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+
+        this.value_hex = new ArrayBuffer(input_length);
+        var view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < input_length; i++)
+        {
+            view[i] = int_buffer[i] & 0x7F;
+
+            this.block_length++;
+
+            if((int_buffer[i] & 0x80) == 0x00)
+                break;
+        }
+
+        // #region Ajust size of value_hex buffer 
+        var temp_value_hex = new ArrayBuffer(this.block_length);
+        var temp_view = new Uint8Array(temp_value_hex);
+
+        for(var i = 0; i < this.block_length; i++)
+            temp_view[i] = view[i];
+
+        this.value_hex = util_copybuf(temp_value_hex);
+        view = new Uint8Array(this.value_hex);
+        // #endregion   
+
+        if((int_buffer[this.block_length - 1] & 0x80) != 0x00)
+        {
+            this.error = "End of input reached before message was fully decoded";
+            return (-1);
+        }
+
+        if(view[0] == 0x00)
+            this.warnings.push("Needlessly long format of SID encoding");
+
+        if(this.block_length <= 8)
+            this.value_dec = util_frombase(view, 7);
+        else
+        {
+            this.is_hex_only = true;
+            this.warnings.push("Too big SID for decoding, hex only");
+        }
+
+        return (input_offset + this.block_length);
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_hex_only)
+        {
+            if(size_only === true)
+                return (new ArrayBuffer(this.value_hex.byteLength));
+
+            var cur_view = new Uint8Array(this.value_hex);
+
+            var ret_buf = new ArrayBuffer(this.block_length);
+            var ret_view = new Uint8Array(ret_buf);
+
+            for(var i = 0; i < (this.block_length - 1) ; i++)
+                ret_view[i] = cur_view[i] | 0x80;
+
+            ret_view[this.block_length - 1] = cur_view[this.block_length - 1];
+
+            return ret_buf;
+        }
+        else
+        {
+            var encoded_buf = util_tobase(this.value_dec, 7);
+            if(encoded_buf.byteLength === 0)
+            {
+                this.error = "Error during encoding SID value";
+                return (new ArrayBuffer(0));
+            }
+
+            var ret_buf = new ArrayBuffer(encoded_buf.byteLength);
+
+            if(size_only === false)
+            {
+                var encoded_view = new Uint8Array(encoded_buf);
+                var ret_view = new Uint8Array(ret_buf);
+
+                for(var i = 0; i < (encoded_buf.byteLength - 1) ; i++)
+                    ret_view[i] = encoded_view[i] | 0x80;
+
+                ret_view[encoded_buf.byteLength - 1] = encoded_view[encoded_buf.byteLength - 1];
+            }
+
+            return ret_buf;
+        }
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype.toString =
+    function()
+    {
+        var result = "";
+
+        if(this.is_hex_only === true)
+            result = to_hex_codes(this.value_hex);
+        else
+        {
+            if(this.is_first_sid)
+            {
+                var sid_value = this.value_dec;
+
+                if(this.value_dec <= 39)
+                    result = "0.";
+                else
+                {
+                    if(this.value_dec <= 79)
+                    {
+                        result = "1.";
+                        sid_value -= 40;
+                    }
+                    else
+                    {
+                        result = "2.";
+                        sid_value -= 80;
+                    }
+                }
+
+                result = result + sid_value.toString();
+            }
+            else
+                result = this.value_dec.toString();
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.SID_value_block.prototype.block_name.call(this);
+        _object.value_dec = this.value_dec;
+        _object.is_first_sid = this.is_first_sid;
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.OID_value_block =
+    function()
+    {
+        local.value_block.call(this, arguments[0]);
+
+        this.value = new Array();
+
+        if(arguments[0] instanceof Object)
+            this.fromString(in_window.org.pkijs.getValue(arguments[0], "value", ""));
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype = new local.value_block();
+    local.OID_value_block.constructor = local.OID_value_block;
+    //**************************************************************************************
+    local.OID_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = input_offset;
+
+        while(input_length > 0)
+        {
+            var sid_block = new local.SID_value_block();
+            result_offset = sid_block.fromBER(input_buffer, result_offset, input_length);
+            if(result_offset == (-1))
+            {
+                this.block_length = 0;
+                this.error = sid_block.error;
+                return result_offset;
+            }
+
+            if(this.value.length == 0)
+                sid_block.is_first_sid = true;
+
+            this.block_length += sid_block.block_length;
+            input_length -= sid_block.block_length;
+
+            this.value.push(sid_block);
+        }
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var ret_buf = new ArrayBuffer(0);
+
+        for(var i = 0; i < this.value.length; i++)
+        {
+            var value_buf = this.value[i].toBER(size_only);
+            if(value_buf.byteLength === 0)
+            {
+                this.error = this.value[i].error;
+                return (new ArrayBuffer(0));
+            }
+
+            ret_buf = util_concatbuf(ret_buf, value_buf);
+        }
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.fromString =
+    function(str)
+    {
+        this.value = new Array(); // Clear existing SID values
+
+        var pos1 = 0;
+        var pos2 = 0;
+
+        var sid = "";
+
+        var flag = false;
+
+        do
+        {
+            pos2 = str.indexOf('.', pos1);
+            if(pos2 === (-1))
+                sid = str.substr(pos1);
+            else
+                sid = str.substr(pos1, pos2 - pos1);
+
+            pos1 = pos2 + 1;
+
+            if(flag)
+            {
+                var sid_block = this.value[0];
+
+                var plus = 0;
+
+                switch(sid_block.value_dec)
+                {
+                    case 0:
+                        break;
+                    case 1:
+                        plus = 40;
+                        break;
+                    case 2:
+                        plus = 80;
+                        break;
+                    default:
+                        this.value = new Array(); // clear SID array
+                        return false; // ???
+                }
+
+                var parsedSID = parseInt(sid, 10);
+                if(isNaN(parsedSID))
+                    return true;
+
+                sid_block.value_dec = parsedSID + plus;
+
+                flag = false;
+            }
+            else
+            {
+                var sid_block = new local.SID_value_block();
+                sid_block.value_dec = parseInt(sid, 10);
+                if(isNaN(sid_block.value_dec))
+                    return true;
+
+                if(this.value.length === 0)
+                {
+                    sid_block.is_first_sid = true;
+                    flag = true;
+                }
+
+                this.value.push(sid_block);
+            }
+
+        } while(pos2 !== (-1));
+
+        return true;
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.toString =
+    function()
+    {
+        var result = "";
+        var is_hex_only = false;
+
+        for(var i = 0; i < this.value.length; i++)
+        {
+            is_hex_only = this.value[i].is_hex_only;
+
+            var sid_str = this.value[i].toString();
+
+            if(i !== 0)
+                result = result + ".";
+
+            if(is_hex_only)
+            {
+                sid_str = "{" + sid_str + "}";
+
+                if(this.value[i].is_first_sid)
+                    result = "2.{" + sid_str + " - 80}";
+                else
+                    result = result + sid_str;
+            }
+            else
+                result = result + sid_str;
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "OID_value_block";
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.OID_value_block.prototype.block_name.call(this);
+        _object.value = local.OID_value_block.prototype.toString.call(this);
+        _object.sid_array = new Array();
+        for(var i = 0; i < this.value.length; i++)
+            _object.sid_array.push(this.value[i].toJSON());
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OID =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.OID_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 6; // OBJECT IDENTIFIER
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OID.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.OID.constructor = in_window.org.pkijs.asn1.OID;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OID.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "OID";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OID.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.OID.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion   
+    //**************************************************************************************
+    // #region Declaration of all string's classes 
+    //**************************************************************************************
+    local.UTF8STRING_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        this.is_hex_only = true;
+        this.value = ""; // String representation of decoded ArrayBuffer
+    };
+    //**************************************************************************************
+    local.UTF8STRING_value_block.prototype = new local.hex_block();
+    local.UTF8STRING_value_block.constructor = local.UTF8STRING_value_block;
+    //**************************************************************************************
+    local.UTF8STRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UTF8STRING_value_block";
+    };
+    //**************************************************************************************
+    local.UTF8STRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.UTF8STRING_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.UTF8STRING_value_block();
+
+        if(arguments[0] instanceof Object)
+        {
+            if("value" in arguments[0])
+                in_window.org.pkijs.asn1.UTF8STRING.prototype.fromString.call(this,arguments[0].value);
+        }
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 12; // UTF8STRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.UTF8STRING.constructor = in_window.org.pkijs.asn1.UTF8STRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UTF8STRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param>
+        this.value_block.value = String.fromCharCode.apply(null, new Uint8Array(input_buffer));
+
+        try
+        {
+            this.value_block.value = decodeURIComponent(escape(this.value_block.value));
+        }
+        catch(ex)
+        {
+            this.warnings.push("Error during \"decodeURIComponent\": " + ex + ", using raw string");
+        }
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.fromString =
+    function(input_string)
+    {
+        /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param>
+
+        var str = unescape(encodeURIComponent(input_string));
+        var str_len = str.length;
+
+        this.value_block.value_hex = new ArrayBuffer(str_len);
+        var view = new Uint8Array(this.value_block.value_hex);
+
+        for(var i = 0; i < str_len; i++)
+            view[i] = str.charCodeAt(i);
+
+        this.value_block.value = input_string;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.UTF8STRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.BMPSTRING_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        this.is_hex_only = true;
+        this.value = "";
+    };
+    //**************************************************************************************
+    local.BMPSTRING_value_block.prototype = new local.hex_block();
+    local.BMPSTRING_value_block.constructor = local.BMPSTRING_value_block;
+    //**************************************************************************************
+    local.BMPSTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BMPSTRING_value_block";
+    };
+    //**************************************************************************************
+    local.BMPSTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.BMPSTRING_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.BMPSTRING_value_block();
+
+        if(arguments[0] instanceof Object)
+        {
+            if("value" in arguments[0])
+                in_window.org.pkijs.asn1.BMPSTRING.prototype.fromString.call(this, arguments[0].value);
+        }
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 30; // BMPSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.BMPSTRING.constructor = in_window.org.pkijs.asn1.BMPSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BMPSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param>
+
+        var copy_buffer = in_window.org.pkijs.copyBuffer(input_buffer);
+
+        var value_view = new Uint8Array(copy_buffer);
+
+        for(var i = 0; i < value_view.length; i = i + 2)
+        {
+            var temp = value_view[i];
+
+            value_view[i] = value_view[i + 1];
+            value_view[i + 1] = temp;
+        }
+
+        this.value_block.value = String.fromCharCode.apply(null, new Uint16Array(copy_buffer));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.fromString =
+    function(input_string)
+    {
+        /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param>
+
+        var str_length = input_string.length;
+
+        this.value_block.value_hex = new ArrayBuffer(str_length * 2);
+        var value_hex_view = new Uint8Array(this.value_block.value_hex);
+
+        for(var i = 0; i < str_length; i++)
+        {
+            var code_buf = util_tobase(input_string.charCodeAt(i), 8);
+            var code_view = new Uint8Array(code_buf);
+            if(code_view.length > 2)
+                continue;
+
+            var dif = 2 - code_view.length;
+
+            for(var j = (code_view.length - 1) ; j >= 0; j--)
+                value_hex_view[i * 2 + j + dif] = code_view[j];
+        }
+
+        this.value_block.value = input_string;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.BMPSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.UNIVERSALSTRING_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        this.is_hex_only = true;
+        this.value = "";
+    };
+    //**************************************************************************************
+    local.UNIVERSALSTRING_value_block.prototype = new local.hex_block();
+    local.UNIVERSALSTRING_value_block.constructor = local.UNIVERSALSTRING_value_block;
+    //**************************************************************************************
+    local.UNIVERSALSTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UNIVERSALSTRING_value_block";
+    };
+    //**************************************************************************************
+    local.UNIVERSALSTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.UNIVERSALSTRING_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.UNIVERSALSTRING_value_block();
+
+        if(arguments[0] instanceof Object)
+        {
+            if("value" in arguments[0])
+                in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromString.call(this, arguments[0].value);
+        }
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 28; // UNIVERSALSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.constructor = in_window.org.pkijs.asn1.UNIVERSALSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UNIVERSALSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param>
+
+        var copy_buffer = in_window.org.pkijs.copyBuffer(input_buffer);
+
+        var value_view = new Uint8Array(copy_buffer);
+
+        for(var i = 0; i < value_view.length; i = i + 4)
+        {
+            value_view[i] = value_view[i + 3];
+            value_view[i + 1] = value_view[i + 2];
+            value_view[i + 2] = 0x00;
+            value_view[i + 3] = 0x00;
+        }
+
+        this.value_block.value = String.fromCharCode.apply(null, new Uint32Array(copy_buffer));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromString =
+    function(input_string)
+    {
+        /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param>
+
+        var str_length = input_string.length;
+
+        this.value_block.value_hex = new ArrayBuffer(str_length * 4);
+        var value_hex_view = new Uint8Array(this.value_block.value_hex);
+
+        for(var i = 0; i < str_length; i++)
+        {
+            var code_buf = util_tobase(input_string.charCodeAt(i), 8);
+            var code_view = new Uint8Array(code_buf);
+            if(code_view.length > 4)
+                continue;
+
+            var dif = 4 - code_view.length;
+
+            for(var j = (code_view.length - 1) ; j >= 0; j--)
+                value_hex_view[i*4 + j + dif] = code_view[j];
+        }
+
+        this.value_block.value = input_string;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        /// <field type="String">Native string representation</field>
+        this.value = "";
+        this.is_hex_only = true;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_value_block.prototype = new local.hex_block();
+    local.SIMPLESTRING_value_block.constructor = local.SIMPLESTRING_value_block;
+    //**************************************************************************************
+    local.SIMPLESTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "SIMPLESTRING_value_block";
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.SIMPLESTRING_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.SIMPLESTRING_value_block();
+
+        if(arguments[0] instanceof Object)
+        {
+            if("value" in arguments[0])
+                local.SIMPLESTRING_block.prototype.fromString.call(this, arguments[0].value);
+        }
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    local.SIMPLESTRING_block.constructor = local.SIMPLESTRING_block;
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "SIMPLESTRING";
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        local.SIMPLESTRING_block.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param>
+
+        this.value_block.value = String.fromCharCode.apply(null, new Uint8Array(input_buffer));
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.fromString =
+    function(input_string)
+    {
+        /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param>
+        var str_len = input_string.length;
+
+        this.value_block.value_hex = new ArrayBuffer(str_len);
+        var view = new Uint8Array(this.value_block.value_hex);
+
+        for(var i = 0; i < str_len; i++)
+            view[i] = input_string.charCodeAt(i);
+
+        this.value_block.value = input_string;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.SIMPLESTRING_block.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NUMERICSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 18; // NUMERICSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NUMERICSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.NUMERICSTRING.constructor = in_window.org.pkijs.asn1.NUMERICSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NUMERICSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "NUMERICSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NUMERICSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.NUMERICSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.PRINTABLESTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 19; // PRINTABLESTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.PRINTABLESTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.PRINTABLESTRING.constructor = in_window.org.pkijs.asn1.PRINTABLESTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "PRINTABLESTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TELETEXSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 20; // TELETEXSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TELETEXSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.TELETEXSTRING.constructor = in_window.org.pkijs.asn1.TELETEXSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TELETEXSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "TELETEXSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TELETEXSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.TELETEXSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 21; // VIDEOTEXSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING.constructor = in_window.org.pkijs.asn1.VIDEOTEXSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "VIDEOTEXSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.IA5STRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 22; // IA5STRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.IA5STRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.IA5STRING.constructor = in_window.org.pkijs.asn1.IA5STRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.IA5STRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "IA5STRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.IA5STRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.IA5STRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GRAPHICSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 25; // GRAPHICSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GRAPHICSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.GRAPHICSTRING.constructor = in_window.org.pkijs.asn1.GRAPHICSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "GRAPHICSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VISIBLESTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 26; // VISIBLESTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VISIBLESTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.VISIBLESTRING.constructor = in_window.org.pkijs.asn1.VISIBLESTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VISIBLESTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "VISIBLESTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 27; // GENERALSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.GENERALSTRING.constructor = in_window.org.pkijs.asn1.GENERALSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "GENERALSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.GENERALSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHARACTERSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 29; // CHARACTERSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHARACTERSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.CHARACTERSTRING.constructor = in_window.org.pkijs.asn1.CHARACTERSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "CHARACTERSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of all date and time classes 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME =
+    function()
+    {
+        in_window.org.pkijs.asn1.VISIBLESTRING.call(this, arguments[0]);
+
+        this.year = 0;
+        this.month = 0;
+        this.day = 0;
+        this.hour = 0;
+        this.minute = 0;
+        this.second = 0;
+
+        // #region Create UTCTIME from ASN.1 UTC string value 
+        if((arguments[0] instanceof Object) && ("value" in arguments[0]))
+        {
+            in_window.org.pkijs.asn1.UTCTIME.prototype.fromString.call(this, arguments[0].value);
+
+            this.value_block.value_hex = new ArrayBuffer(arguments[0].value.length);
+            var view = new Uint8Array(this.value_block.value_hex);
+
+            for(var i = 0; i < arguments[0].value.length; i++)
+                view[i] = arguments[0].value.charCodeAt(i);
+        }
+        // #endregion 
+        // #region Create UTCTIME from JavaScript Date type 
+        if((arguments[0] instanceof Object) && ("value_date" in arguments[0]))
+        {
+            in_window.org.pkijs.asn1.UTCTIME.prototype.fromDate.call(this, arguments[0].value_date);
+            this.value_block.value_hex = in_window.org.pkijs.asn1.UTCTIME.prototype.toBuffer.call(this);
+        }
+        // #endregion 
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 23; // UTCTIME
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype = new in_window.org.pkijs.asn1.VISIBLESTRING();
+    in_window.org.pkijs.asn1.UTCTIME.constructor = in_window.org.pkijs.asn1.UTCTIME;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.UTCTIME.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        in_window.org.pkijs.asn1.UTCTIME.prototype.fromString.call(this, String.fromCharCode.apply(null, new Uint8Array(input_buffer)));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.toBuffer =
+    function()
+    {
+        var str = in_window.org.pkijs.asn1.UTCTIME.prototype.toString.call(this);
+
+        var buffer = new ArrayBuffer(str.length);
+        var view = new Uint8Array(buffer);
+
+        for(var i = 0; i < str.length; i++)
+            view[i] = str.charCodeAt(i);
+
+        return buffer;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.fromDate =
+    function(input_date)
+    {
+        /// <summary>Create "UTCTime" ASN.1 type from JavaScript "Date" type</summary>
+
+        this.year = input_date.getUTCFullYear();
+        this.month = input_date.getUTCMonth() + 1;
+        this.day = input_date.getUTCDate();
+        this.hour = input_date.getUTCHours();
+        this.minute = input_date.getUTCMinutes();
+        this.second = input_date.getUTCSeconds();
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.toDate =
+    function()
+    {
+        return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second)));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.fromString =
+    function(input_string)
+    {
+        /// <summary>Create "UTCTime" ASN.1 type from JavaScript "String" type</summary>
+
+        // #region Parse input string 
+        var parser = /(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z/ig;
+        var parser_array = parser.exec(input_string);
+        if(parser_array === null)
+        {
+            this.error = "Wrong input string for convertion";
+            return;
+        }
+        // #endregion 
+
+        // #region Store parsed values 
+        var year = parseInt(parser_array[1], 10);
+        if(year >= 50)
+            this.year = 1900 + year;
+        else
+            this.year = 2000 + year;
+
+        this.month = parseInt(parser_array[2], 10);
+        this.day = parseInt(parser_array[3], 10);
+        this.hour = parseInt(parser_array[4], 10);
+        this.minute = parseInt(parser_array[5], 10);
+        this.second = parseInt(parser_array[6], 10);
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.toString =
+    function()
+    {
+        var output_array = new Array(7);
+
+        output_array[0] = in_window.org.pkijs.padNumber(((this.year < 2000) ? (this.year - 1900) : (this.year - 2000)), 2);
+        output_array[1] = in_window.org.pkijs.padNumber(this.month, 2);
+        output_array[2] = in_window.org.pkijs.padNumber(this.day, 2);
+        output_array[3] = in_window.org.pkijs.padNumber(this.hour, 2);
+        output_array[4] = in_window.org.pkijs.padNumber(this.minute, 2);
+        output_array[5] = in_window.org.pkijs.padNumber(this.second, 2);
+        output_array[6] = "Z";
+
+        return output_array.join('');
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UTCTIME";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.UTCTIME.prototype.block_name.call(this);
+        _object.year = this.year;
+        _object.month = this.month;
+        _object.day = this.day;
+        _object.hour = this.hour;
+        _object.minute = this.minute;
+        _object.second = this.second;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME =
+    function()
+    {
+        in_window.org.pkijs.asn1.VISIBLESTRING.call(this, arguments[0]);
+
+        this.year = 0;
+        this.month = 0;
+        this.day = 0;
+        this.hour = 0;
+        this.minute = 0;
+        this.second = 0;
+        this.millisecond = 0;
+
+        // #region Create GeneralizedTime from ASN.1 string value 
+        if((arguments[0] instanceof Object) && ("value" in arguments[0]))
+        {
+            in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString.call(this, arguments[0].value);
+
+            this.value_block.value_hex = new ArrayBuffer(arguments[0].value.length);
+            var view = new Uint8Array(this.value_block.value_hex);
+
+            for(var i = 0; i < arguments[0].value.length; i++)
+                view[i] = arguments[0].value.charCodeAt(i);
+        }
+        // #endregion 
+        // #region Create GeneralizedTime from JavaScript Date type 
+        if((arguments[0] instanceof Object) && ("value_date" in arguments[0]))
+        {
+            in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromDate.call(this, arguments[0].value_date);
+            this.value_block.value_hex = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toBuffer.call(this);
+        }
+        // #endregion 
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 24; // GENERALIZEDTIME
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype = new in_window.org.pkijs.asn1.VISIBLESTRING();
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.constructor = in_window.org.pkijs.asn1.GENERALIZEDTIME;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString.call(this, String.fromCharCode.apply(null, new Uint8Array(input_buffer)));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toBuffer =
+    function()
+    {
+        var str = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toString.call(this);
+
+        var buffer = new ArrayBuffer(str.length);
+        var view = new Uint8Array(buffer);
+
+        for(var i = 0; i < str.length; i++)
+            view[i] = str.charCodeAt(i);
+
+        return buffer;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromDate =
+    function(input_date)
+    {
+        /// <summary>Create "GeneralizedTime" ASN.1 type from JavaScript "Date" type</summary>
+
+        this.year = input_date.getUTCFullYear();
+        this.month = input_date.getUTCMonth();
+        this.day = input_date.getUTCDate();
+        this.hour = input_date.getUTCHours();
+        this.minute = input_date.getUTCMinutes();
+        this.second = input_date.getUTCSeconds();
+        this.millisecond = input_date.getUTCMilliseconds();
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toDate =
+    function()
+    {
+        return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond)));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString =
+    function(input_string)
+    {
+        /// <summary>Create "GeneralizedTime" ASN.1 type from JavaScript "String" type</summary>
+
+        // #region Initial variables 
+        var isUTC = false;
+
+        var timeString = "";
+        var dateTimeString = "";
+        var fractionPart = 0;
+
+        var parser;
+
+        var hourDifference = 0;
+        var minuteDifference = 0;
+        // #endregion 
+
+        // #region Convert as UTC time 
+        if(input_string[input_string.length - 1] == "Z")
+        {
+            timeString = input_string.substr(0, input_string.length - 1);
+
+            isUTC = true;
+        }
+        // #endregion 
+        // #region Convert as local time 
+        else
+        {
+            var number = new Number(input_string[input_string.length - 1]);
+
+            if(isNaN(number.valueOf()))
+                throw new Error("Wrong input string for convertion");
+
+            timeString = input_string;
+        }
+        // #endregion 
+
+        // #region Check that we do not have a "+" and "-" symbols inside UTC time 
+        if(isUTC)
+        {
+            if(timeString.indexOf("+") != (-1))
+                throw new Error("Wrong input string for convertion");
+
+            if(timeString.indexOf("-") != (-1))
+                throw new Error("Wrong input string for convertion");
+        }
+        // #endregion 
+        // #region Get "UTC time difference" in case of local time
+        else
+        {
+            var multiplier = 1;
+            var differencePosition = timeString.indexOf("+");
+            var differenceString = "";
+
+            if(differencePosition == (-1))
+            {
+                differencePosition = timeString.indexOf("-");
+                multiplier = (-1);
+            }
+
+            if(differencePosition != (-1))
+            {
+                differenceString = timeString.substr(differencePosition + 1);
+                timeString = timeString.substr(0, differencePosition);
+
+                if((differenceString.length != 2) && (differenceString.length != 4))
+                    throw new Error("Wrong input string for convertion");
+
+                var number = new Number(differenceString.substr(0, 2));
+
+                if(isNaN(number.valueOf()))
+                    throw new Error("Wrong input string for convertion");
+
+                hourDifference = multiplier * number;
+
+                if(differenceString.length == 4)
+                {
+                    number = new Number(differenceString.substr(2, 2));
+
+                    if(isNaN(number.valueOf()))
+                        throw new Error("Wrong input string for convertion");
+
+                    minuteDifference = multiplier * number;
+                }
+            }
+        }
+        // #endregion 
+
+        // #region Get position of fraction point 
+        var fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol
+        if(fractionPointPosition == (-1))
+            fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol
+        // #endregion 
+
+        // #region Get fraction part 
+        if(fractionPointPosition != (-1))
+        {
+            var fractionPartCheck = new Number("0" + timeString.substr(fractionPointPosition));
+
+            if(isNaN(fractionPartCheck.valueOf()))
+                throw new Error("Wrong input string for convertion");
+
+            fractionPart = fractionPartCheck.valueOf();
+
+            dateTimeString = timeString.substr(0, fractionPointPosition);
+        }
+        else
+            dateTimeString = timeString;
+        // #endregion 
+
+        // #region Parse internal date 
+        switch(true)
+        {
+            case (dateTimeString.length == 8): // "YYYYMMDD"
+                parser = /(\d{4})(\d{2})(\d{2})/ig;
+                if(fractionPointPosition !== (-1))
+                    throw new Error("Wrong input string for convertion"); // Here we should not have a "fraction point"
+                break;
+            case (dateTimeString.length == 10): // "YYYYMMDDHH"
+                parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig;
+
+                if(fractionPointPosition !== (-1))
+                {
+                    var fractionResult = 60 * fractionPart;
+                    this.minute = Math.floor(fractionResult);
+
+                    fractionResult = 60 * (fractionResult - this.minute);
+                    this.second = Math.floor(fractionResult);
+
+                    fractionResult = 1000 * (fractionResult - this.second);
+                    this.millisecond = Math.floor(fractionResult);
+                }
+                break;
+            case (dateTimeString.length == 12): // "YYYYMMDDHHMM"
+                parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+                if(fractionPointPosition !== (-1))
+                {
+                    var fractionResult = 60 * fractionPart;
+                    this.second = Math.floor(fractionResult);
+
+                    fractionResult = 1000 * (fractionResult - this.second);
+                    this.millisecond = Math.floor(fractionResult);
+                }
+                break;
+            case (dateTimeString.length == 14): // "YYYYMMDDHHMMSS"
+                parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+                if(fractionPointPosition !== (-1))
+                {
+                    var fractionResult = 1000 * fractionPart;
+                    this.millisecond = Math.floor(fractionResult);
+                }
+                break;
+            default:
+                throw new Error("Wrong input string for convertion");
+        }
+        // #endregion 
+
+        // #region Put parsed values at right places 
+        var parser_array = parser.exec(dateTimeString);
+        if(parser_array == null)
+            throw new Error("Wrong input string for convertion");
+
+        for(var j = 1; j < parser_array.length; j++)
+        {
+            switch(j)
+            {
+                case 1:
+                    this.year = parseInt(parser_array[j], 10);
+                    break;
+                case 2:
+                    this.month = parseInt(parser_array[j], 10) - 1; // In JavaScript we have month range as "0 - 11"
+                    break;
+                case 3:
+                    this.day = parseInt(parser_array[j], 10);
+                    break;
+                case 4:
+                    this.hour = parseInt(parser_array[j], 10) + hourDifference;
+                    break;
+                case 5:
+                    this.minute = parseInt(parser_array[j], 10) + minuteDifference;
+                    break;
+                case 6:
+                    this.second = parseInt(parser_array[j], 10);
+                    break;
+                default:
+                    throw new Error("Wrong input string for convertion");
+            }
+        }
+        // #endregion 
+
+        // #region Get final date 
+        if(isUTC == false)
+        {
+            var tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
+
+            this.year = tempDate.getUTCFullYear();
+            this.month = tempDate.getUTCMonth();
+            this.day = tempDate.getUTCDay();
+            this.hour = tempDate.getUTCHours();
+            this.minute = tempDate.getUTCMinutes();
+            this.second = tempDate.getUTCSeconds();
+            this.millisecond = tempDate.getUTCMilliseconds();
+        }
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toString =
+    function()
+    {
+        var output_array = new Array();
+
+        output_array.push(in_window.org.pkijs.padNumber(this.year, 4));
+        output_array.push(in_window.org.pkijs.padNumber(this.month, 2));
+        output_array.push(in_window.org.pkijs.padNumber(this.day, 2));
+        output_array.push(in_window.org.pkijs.padNumber(this.hour, 2));
+        output_array.push(in_window.org.pkijs.padNumber(this.minute, 2));
+        output_array.push(in_window.org.pkijs.padNumber(this.second, 2));
+        if(this.millisecond != 0)
+        {
+            output_array.push(".");
+            output_array.push(in_window.org.pkijs.padNumber(this.millisecond, 3));
+        }
+        output_array.push("Z");
+
+        return output_array.join('');
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "GENERALIZEDTIME";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.block_name.call(this);
+        _object.year = this.year;
+        _object.month = this.month;
+        _object.day = this.day;
+        _object.hour = this.hour;
+        _object.minute = this.minute;
+        _object.second = this.second;
+        _object.millisecond = this.millisecond;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATE =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 31; // DATE
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATE.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.DATE.constructor = in_window.org.pkijs.asn1.DATE;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATE.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "DATE";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATE.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.DATE.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIMEOFDAY =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 32; // TIMEOFDAY
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIMEOFDAY.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.TIMEOFDAY.constructor = in_window.org.pkijs.asn1.TIMEOFDAY;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIMEOFDAY.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "TIMEOFDAY";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIMEOFDAY.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.TIMEOFDAY.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATETIME =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 33; // DATETIME
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATETIME.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.DATETIME.constructor = in_window.org.pkijs.asn1.DATETIME;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATETIME.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "DATETIME";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATETIME.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.DATETIME.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DURATION =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 34; // DURATION
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DURATION.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.DURATION.constructor = in_window.org.pkijs.asn1.DURATION;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DURATION.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "DURATION";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DURATION.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.DURATION.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIME =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 14; // TIME
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIME.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.TIME.constructor = in_window.org.pkijs.asn1.TIME;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIME.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "TIME";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIME.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.TIME.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of special ASN.1 schema type CHOICE 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHOICE =
+    function()
+    {
+        if(arguments[0] instanceof Object)
+        {
+            this.value = in_window.org.pkijs.getValue(arguments[0], "value", new Array()); // Array of ASN.1 types for make a choice from
+            this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false);
+        }
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of special ASN.1 schema type ANY 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ANY =
+    function()
+    {
+        if(arguments[0] instanceof Object)
+        {
+            this.name = in_window.org.pkijs.getValue(arguments[0], "name", "");
+            this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false);
+        }
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of special ASN.1 schema type REPEATED 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.REPEATED =
+    function()
+    {
+        if(arguments[0] instanceof Object)
+        {
+            this.name = in_window.org.pkijs.getValue(arguments[0], "name", "");
+            this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false);
+            this.value = in_window.org.pkijs.getValue(arguments[0], "value", new in_window.org.pkijs.asn1.ANY());
+            this.local = in_window.org.pkijs.getValue(arguments[0], "local", false); // Could local or global array to store elements
+        }
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Major ASN.1 BER decoding function
+    //**************************************************************************************
+    function fromBER_raw(input_buffer, input_offset, input_length)
+    {
+        var incoming_offset = input_offset; // Need to store initial offset since "input_offset" is changing in the function
+
+        // #region Local function changing a type for ASN.1 classes 
+        function local_change_type(input_object, new_type)
+        {
+            if(input_object instanceof new_type)
+                return input_object;
+
+            var new_object = new new_type();
+            new_object.id_block = input_object.id_block;
+            new_object.len_block = input_object.len_block;
+            new_object.warnings = input_object.warnings;
+            new_object.value_before_decode = util_copybuf(input_object.value_before_decode);
+
+            return new_object;
+        }
+        // #endregion 
+
+        // #region Create a basic ASN.1 type since we need to return errors and warnings from the function 
+        var return_object = new in_window.org.pkijs.asn1.ASN1_block();
+        // #endregion 
+
+        // #region Basic check for parameters 
+        if(check_buffer_params(input_buffer, input_offset, input_length) === false)
+        {
+            return_object.error = "Wrong input parameters";
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.error = "Zero buffer length";
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+        // #endregion 
+
+        // #region Decode indentifcation block of ASN.1 BER structure 
+        var result_offset = return_object.id_block.fromBER(input_buffer, input_offset, input_length);
+        return_object.warnings.concat(return_object.id_block.warnings);
+        if(result_offset == (-1))
+        {
+            return_object.error = return_object.id_block.error;
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+
+        input_offset = result_offset;
+        input_length -= return_object.id_block.block_length;
+        // #endregion 
+
+        // #region Decode length block of ASN.1 BER structure 
+        result_offset = return_object.len_block.fromBER(input_buffer, input_offset, input_length);
+        return_object.warnings.concat(return_object.len_block.warnings);
+        if(result_offset == (-1))
+        {
+            return_object.error = return_object.len_block.error;
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+
+        input_offset = result_offset;
+        input_length -= return_object.len_block.block_length;
+        // #endregion 
+
+        // #region Check for usign indefinite length form in encoding for primitive types 
+        if((return_object.id_block.is_constructed == false) &&
+           (return_object.len_block.is_indefinite_form == true))
+        {
+            return_object.error = new String("Indefinite length form used for primitive encoding form");
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+        // #endregion 
+
+        // #region Switch ASN.1 block type 
+        var new_asn1_type = in_window.org.pkijs.asn1.ASN1_block;
+
+        switch(return_object.id_block.tag_class)
+        {
+            // #region UNIVERSAL 
+            case 1: 
+                // #region Check for reserved tag numbers 
+                if((return_object.id_block.tag_number >= 37) &&
+                   (return_object.id_block.is_hex_only == false))
+                {
+                    return_object.error = "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard";
+                    return {
+                        offset: (-1),
+                        result: return_object
+                    };
+                }
+                // #endregion 
+
+                switch(return_object.id_block.tag_number)
+                {
+                    // #region EOC type 
+                    case 0:
+                        // #region Check for EOC type 
+                        if((return_object.id_block.is_constructed == true) &&
+                           (return_object.len_block.length > 0))
+                        {
+                            return_object.error = "Type [UNIVERSAL 0] is reserved";
+                            return {
+                                offset: (-1),
+                                result: return_object
+                            };
+                        }
+                        // #endregion 
+
+                        new_asn1_type = in_window.org.pkijs.asn1.EOC;
+
+                        break;
+                        // #endregion 
+                    // #region BOOLEAN type 
+                    case 1:
+                        new_asn1_type = in_window.org.pkijs.asn1.BOOLEAN;
+                        break;
+                    // #endregion 
+                    // #region INTEGER type 
+                    case 2:
+                        new_asn1_type = in_window.org.pkijs.asn1.INTEGER;
+                        break;
+                    // #endregion 
+                    // #region BITSTRING type 
+                    case 3:
+                        new_asn1_type = in_window.org.pkijs.asn1.BITSTRING;
+                        break;
+                    // #endregion 
+                    // #region OCTETSTRING type 
+                    case 4:
+                        new_asn1_type = in_window.org.pkijs.asn1.OCTETSTRING;
+                        break;
+                    // #endregion 
+                    // #region NULL type 
+                    case 5:
+                        new_asn1_type = in_window.org.pkijs.asn1.NULL;
+                        break;
+                    // #endregion 
+                    // #region OBJECT IDENTIFIER type 
+                    case 6:
+                        new_asn1_type = in_window.org.pkijs.asn1.OID;
+                        break;
+                    // #endregion 
+                    // #region ENUMERATED type 
+                    case 10:
+                        new_asn1_type = in_window.org.pkijs.asn1.ENUMERATED;
+                        break;
+                    // #endregion 
+                    // #region UTF8STRING type 
+                    case 12:
+                        new_asn1_type = in_window.org.pkijs.asn1.UTF8STRING;
+                        break;
+                    // #endregion 
+                    // #region TIME type 
+                    case 14:
+                        new_asn1_type = in_window.org.pkijs.asn1.TIME;
+                        break;
+                    // #endregion 
+                    // #region ASN.1 reserved type 
+                    case 15:
+                        return_object.error = "[UNIVERSAL 15] is reserved by ASN.1 standard";
+                        return {
+                            offset: (-1),
+                            result: return_object
+                        };
+                        break;
+                    // #endregion 
+                    // #region SEQUENCE type 
+                    case 16:
+                        new_asn1_type = in_window.org.pkijs.asn1.SEQUENCE;
+                        break;
+                    // #endregion 
+                    // #region SET type 
+                    case 17:
+                        new_asn1_type = in_window.org.pkijs.asn1.SET;
+                        break;
+                    // #endregion 
+                    // #region NUMERICSTRING type 
+                    case 18:
+                        new_asn1_type = in_window.org.pkijs.asn1.NUMERICSTRING;
+                        break;
+                    // #endregion 
+                    // #region PRINTABLESTRING type 
+                    case 19:
+                        new_asn1_type = in_window.org.pkijs.asn1.PRINTABLESTRING;
+                        break;
+                    // #endregion 
+                    // #region TELETEXSTRING type 
+                    case 20:
+                        new_asn1_type = in_window.org.pkijs.asn1.TELETEXSTRING;
+                        break;
+                    // #endregion 
+                    // #region VIDEOTEXSTRING type 
+                    case 21:
+                        new_asn1_type = in_window.org.pkijs.asn1.VIDEOTEXSTRING;
+                        break;
+                    // #endregion 
+                    // #region IA5STRING type 
+                    case 22:
+                        new_asn1_type = in_window.org.pkijs.asn1.IA5STRING;
+                        break;
+                    // #endregion 
+                    // #region UTCTIME type 
+                    case 23:
+                        new_asn1_type = in_window.org.pkijs.asn1.UTCTIME;
+                        break;
+                    // #endregion 
+                    // #region GENERALIZEDTIME type 
+                    case 24:
+                        new_asn1_type = in_window.org.pkijs.asn1.GENERALIZEDTIME;
+                        break;
+                    // #endregion 
+                    // #region GRAPHICSTRING type 
+                    case 25:
+                        new_asn1_type = in_window.org.pkijs.asn1.GRAPHICSTRING;
+                        break;
+                    // #endregion 
+                    // #region VISIBLESTRING type 
+                    case 26:
+                        new_asn1_type = in_window.org.pkijs.asn1.VISIBLESTRING;
+                        break;
+                    // #endregion 
+                    // #region GENERALSTRING type 
+                    case 27:
+                        new_asn1_type = in_window.org.pkijs.asn1.GENERALSTRING;
+                        break;
+                    // #endregion 
+                    // #region UNIVERSALSTRING type 
+                    case 28:
+                        new_asn1_type = in_window.org.pkijs.asn1.UNIVERSALSTRING;
+                        break;
+                    // #endregion 
+                    // #region CHARACTERSTRING type 
+                    case 29:
+                        new_asn1_type = in_window.org.pkijs.asn1.CHARACTERSTRING;
+                        break;
+                    // #endregion 
+                    // #region BMPSTRING type 
+                    case 30:
+                        new_asn1_type = in_window.org.pkijs.asn1.BMPSTRING;
+                        break;
+                    // #endregion 
+                    // #region DATE type 
+                    case 31:
+                        new_asn1_type = in_window.org.pkijs.asn1.DATE;
+                        break;
+                    // #endregion 
+                    // #region TIMEOFDAY type 
+                    case 32:
+                        new_asn1_type = in_window.org.pkijs.asn1.TIMEOFDAY;
+                        break;
+                    // #endregion 
+                    // #region DATE-TIME type 
+                    case 33:
+                        new_asn1_type = in_window.org.pkijs.asn1.DATETIME;
+                        break;
+                    // #endregion 
+                    // #region DURATION type 
+                    case 34:
+                        new_asn1_type = in_window.org.pkijs.asn1.DURATION;
+                        break;
+                    // #endregion 
+                    // #region default 
+                    default:
+                        {
+                            var new_object;
+
+                            if(return_object.id_block.is_constructed == true)
+                                new_object = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED();
+                            else
+                                new_object = new in_window.org.pkijs.asn1.ASN1_PRIMITIVE();
+
+                            new_object.id_block = return_object.id_block;
+                            new_object.len_block = return_object.len_block;
+                            new_object.warnings = return_object.warnings;
+
+                            return_object = new_object;
+
+                            result_offset = return_object.fromBER(input_buffer, input_offset, input_length);
+                        }
+                    // #endregion 
+                }
+                break;
+            // #endregion 
+            // #region All other tag classes 
+            case 2: // APPLICATION
+            case 3: // CONTEXT-SPECIFIC
+            case 4: // PRIVATE
+            default:
+                {
+                    if(return_object.id_block.is_constructed == true)
+                        new_asn1_type = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED;
+                    else
+                        new_asn1_type = in_window.org.pkijs.asn1.ASN1_PRIMITIVE;
+                }
+            // #endregion 
+        }
+        // #endregion 
+
+        // #region Change type and perform BER decoding 
+        return_object = local_change_type(return_object, new_asn1_type);
+        result_offset = return_object.fromBER(input_buffer, input_offset, (return_object.len_block.is_indefinite_form == true) ? input_length : return_object.len_block.length);
+        // #endregion 
+
+        // #region Coping incoming buffer for entire ASN.1 block 
+        return_object.value_before_decode = util_copybuf_offset(input_buffer, incoming_offset, return_object.block_length);
+        // #endregion 
+
+        return {
+            offset: result_offset,
+            result: return_object
+        };
+    }
+    //**************************************************************************************
+    in_window.org.pkijs.fromBER = 
+    function(input_buffer)
+    {
+        /// <summary>Major function for decoding ASN.1 BER array into internal library structuries</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array of bytes</param>
+
+        if(input_buffer.byteLength == 0)
+        {
+            var result = new in_window.org.pkijs.asn1.ASN1_block();
+            result.error = "Input buffer has zero length";
+
+            return {
+                offset: (-1),
+                result: result
+            };
+        }
+
+        return fromBER_raw(input_buffer, 0, input_buffer.byteLength);
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Major scheme verification function 
+    //**************************************************************************************
+    in_window.org.pkijs.compareSchema =
+    function(root, input_asn1_data, input_asn1_schema)
+    {
+        // #region Special case for CHOICE schema element type 
+        if(input_asn1_schema instanceof in_window.org.pkijs.asn1.CHOICE)
+        {
+            var choice_result = false;
+
+            for(var j = 0; j < input_asn1_schema.value.length; j++)
+            {
+                var result = in_window.org.pkijs.compareSchema(root, input_asn1_data, input_asn1_schema.value[j]);
+                if(result.verified === true)
+                    return {
+                        verified: true,
+                        result: root
+                    };
+            }
+
+            if(choice_result === false)
+            {
+                var _result = {
+                    verified: false,
+                    result: {
+                        error: "Wrong values for CHOICE type"
+                    }
+                };
+
+                if(input_asn1_schema.hasOwnProperty('name'))
+                    _result.name = input_asn1_schema.name;
+
+                return _result;
+            }
+        }
+        // #endregion 
+
+        // #region Special case for ANY schema element type 
+        if(input_asn1_schema instanceof in_window.org.pkijs.asn1.ANY)
+        {
+            // #region Add named component of ASN.1 schema 
+            if(input_asn1_schema.hasOwnProperty('name'))
+                root[input_asn1_schema.name] = input_asn1_data;
+            // #endregion 
+
+            return {
+                verified: true,
+                result: root
+            };
+        }
+        // #endregion 
+
+        // #region Initial check 
+        if((root instanceof Object) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong root object" }
+            };
+
+        if((input_asn1_data instanceof Object) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 data" }
+            };
+
+        if((input_asn1_schema instanceof Object) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(('id_block' in input_asn1_schema) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+        // #endregion 
+
+        // #region Comparing id_block properties in ASN.1 data and ASN.1 schema 
+        // #region Encode and decode ASN.1 schema id_block 
+        /// <remarks>This encoding/decoding is neccessary because could be an errors in schema definition</remarks>
+        if(('fromBER' in input_asn1_schema.id_block) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(('toBER' in input_asn1_schema.id_block) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        var encoded_id = input_asn1_schema.id_block.toBER(false);
+        if(encoded_id.byteLength === 0)
+            return {
+                verified: false,
+                result: { error: "Error encoding id_block for ASN.1 schema" }
+            };
+
+        var decoded_offset = input_asn1_schema.id_block.fromBER(encoded_id, 0, encoded_id.byteLength);
+        if(decoded_offset === (-1))
+            return {
+                verified: false,
+                result: { error: "Error decoding id_block for ASN.1 schema" }
+            };
+        // #endregion 
+
+        // #region tag_class 
+        if(input_asn1_schema.id_block.hasOwnProperty('tag_class') === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(input_asn1_schema.id_block.tag_class !== input_asn1_data.id_block.tag_class)
+            return {
+                verified: false,
+                result: root
+            };
+        // #endregion 
+        // #region tag_number 
+        if(input_asn1_schema.id_block.hasOwnProperty('tag_number') === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(input_asn1_schema.id_block.tag_number !== input_asn1_data.id_block.tag_number)
+            return {
+                verified: false,
+                result: root
+            };
+        // #endregion 
+        // #region is_constructed 
+        if(input_asn1_schema.id_block.hasOwnProperty('is_constructed') === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(input_asn1_schema.id_block.is_constructed !== input_asn1_data.id_block.is_constructed)
+            return {
+                verified: false,
+                result: root
+            };
+        // #endregion 
+        // #region is_hex_only 
+        if(('is_hex_only' in input_asn1_schema.id_block) === false) // Since 'is_hex_only' is an inhirited property
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(input_asn1_schema.id_block.is_hex_only !== input_asn1_data.id_block.is_hex_only)
+            return {
+                verified: false,
+                result: root
+            };
+        // #endregion 
+        // #region value_hex 
+        if(input_asn1_schema.id_block.is_hex_only === true)
+        {
+            if(('value_hex' in input_asn1_schema.id_block) === false) // Since 'value_hex' is an inhirited property
+                return {
+                    verified: false,
+                    result: { error: "Wrong ASN.1 schema" }
+                };
+
+            var schema_view = new Uint8Array(input_asn1_schema.id_block.value_hex);
+            var asn1_view = new Uint8Array(input_asn1_data.id_block.value_hex);
+
+            if(schema_view.length !== asn1_view.length)
+                return {
+                    verified: false,
+                    result: root
+                };
+
+            for(var i = 0; i < schema_view.length; i++)
+            {
+                if(schema_view[i] !== asn1_view[1])
+                    return {
+                        verified: false,
+                        result: root
+                    };
+            }
+        }
+        // #endregion 
+        // #endregion 
+
+        // #region Add named component of ASN.1 schema 
+        if(input_asn1_schema.hasOwnProperty('name'))
+        {
+            input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+            if(input_asn1_schema.name !== "")
+                root[input_asn1_schema.name] = input_asn1_data;
+        }
+        // #endregion 
+
+        // #region Getting next ASN.1 block for comparition 
+        if(input_asn1_schema.id_block.is_constructed === true)
+        {
+            var admission = 0;
+            var result = { verified: false };
+
+            var max_length = input_asn1_schema.value_block.value.length;
+
+            if(max_length > 0)
+            {
+                if(input_asn1_schema.value_block.value[0] instanceof in_window.org.pkijs.asn1.REPEATED)
+                    max_length = input_asn1_data.value_block.value.length;
+            }
+
+            // #region Special case when constructive value has no elements 
+            if(max_length === 0)
+                return {
+                    verified: true,
+                    result: root
+                };
+            // #endregion 
+
+            // #region Special case when "input_asn1_data" has no values and "input_asn1_schema" has all optional values
+            if((input_asn1_data.value_block.value.length === 0) && 
+               (input_asn1_schema.value_block.value.length !== 0))
+            {
+                var _optional = true;
+
+                for(var i = 0; i < input_asn1_schema.value_block.value.length; i++)
+                    _optional = _optional && (input_asn1_schema.value_block.value[i].optional || false);
+
+                if(_optional === true)
+                {
+                    return {
+                        verified: true,
+                        result: root
+                    };
+                }
+                else
+                {
+                    // #region Delete early added name of block 
+                    if(input_asn1_schema.hasOwnProperty('name'))
+                    {
+                        input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                        if(input_asn1_schema.name !== "")
+                            delete root[input_asn1_schema.name];
+                    }
+                    // #endregion 
+
+                    root.error = "Inconsistent object length";
+
+                    return {
+                        verified: false,
+                        result: root
+                    };
+                }
+            }
+            // #endregion 
+
+            for(var i = 0; i < max_length; i++)
+            {
+                // #region Special case when there is an "optional" element of ASN.1 schema at the end 
+                if((i - admission) >= input_asn1_data.value_block.value.length)
+                {
+                    if(input_asn1_schema.value_block.value[i].optional === false)
+                    {
+                        var _result = {
+                            verified: false,
+                            result: root
+                        };
+
+                        root.error = "Inconsistent length between ASN.1 data and schema";
+
+                        // #region Delete early added name of block 
+                        if(input_asn1_schema.hasOwnProperty('name'))
+                        {
+                            input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                            if(input_asn1_schema.name !== "")
+                            {
+                                delete root[input_asn1_schema.name];
+                                _result.name = input_asn1_schema.name;
+                            }
+                        }
+                        // #endregion 
+
+                        return _result;
+                    }
+                }
+                    // #endregion 
+                else
+                {
+                    // #region Special case for REPEATED type of ASN.1 schema element 
+                    if(input_asn1_schema.value_block.value[0] instanceof in_window.org.pkijs.asn1.REPEATED)
+                    {
+                        result = in_window.org.pkijs.compareSchema(root, input_asn1_data.value_block.value[i], input_asn1_schema.value_block.value[0].value);
+                        if(result.verified === false)
+                        {
+                            if(input_asn1_schema.value_block.value[0].optional === true)
+                                admission++;
+                            else
+                            {
+                                // #region Delete early added name of block 
+                                if(input_asn1_schema.hasOwnProperty('name'))
+                                {
+                                    input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                                    if(input_asn1_schema.name !== "")
+                                        delete root[input_asn1_schema.name];
+                                }
+                                // #endregion 
+
+                                return result;
+                            }
+                        }
+
+                        if(("name" in input_asn1_schema.value_block.value[0]) && (input_asn1_schema.value_block.value[0].name.length > 0))
+                        {
+                            var array_root = {};
+
+                            if(("local" in input_asn1_schema.value_block.value[0]) && (input_asn1_schema.value_block.value[0].local === true))
+                                array_root = input_asn1_data;
+                            else
+                                array_root = root;
+
+                            if(typeof array_root[input_asn1_schema.value_block.value[0].name] === "undefined")
+                                array_root[input_asn1_schema.value_block.value[0].name] = new Array();
+
+                            array_root[input_asn1_schema.value_block.value[0].name].push(input_asn1_data.value_block.value[i]);
+                        }
+                    }
+                        // #endregion 
+                    else
+                    {
+                        result = in_window.org.pkijs.compareSchema(root, input_asn1_data.value_block.value[i - admission], input_asn1_schema.value_block.value[i]);
+                        if(result.verified === false)
+                        {
+                            if(input_asn1_schema.value_block.value[i].optional === true)
+                                admission++;
+                            else
+                            {
+                                // #region Delete early added name of block 
+                                if(input_asn1_schema.hasOwnProperty('name'))
+                                {
+                                    input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                                    if(input_asn1_schema.name !== "")
+                                        delete root[input_asn1_schema.name];
+                                }
+                                // #endregion 
+
+                                return result;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if(result.verified === false) // The situation may take place if last element is "optional" and verification failed
+            {
+                var _result = {
+                    verified: false,
+                    result: root
+                };
+
+                // #region Delete early added name of block 
+                if(input_asn1_schema.hasOwnProperty('name'))
+                {
+                    input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                    if(input_asn1_schema.name !== "")
+                    {
+                        delete root[input_asn1_schema.name];
+                        _result.name = input_asn1_schema.name;
+                    }
+                }
+                // #endregion 
+
+                return _result;
+            }
+
+            return {
+                verified: true,
+                result: root
+            };
+        }
+        // #endregion 
+        // #region Ability to parse internal value for primitive-encoded value (value of OCTETSTRING, for example)
+        else
+        {
+            if( ("primitive_schema" in input_asn1_schema) &&
+                ("value_hex" in input_asn1_data.value_block) )
+            {
+                // #region Decoding of raw ASN.1 data 
+                var asn1 = in_window.org.pkijs.fromBER(input_asn1_data.value_block.value_hex);
+                if(asn1.offset === (-1))
+                {
+                    var _result = {
+                        verified: false,
+                        result: asn1.result
+                    };
+
+                    // #region Delete early added name of block 
+                    if(input_asn1_schema.hasOwnProperty('name'))
+                    {
+                        input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                        if(input_asn1_schema.name !== "")
+                        {
+                            delete root[input_asn1_schema.name];
+                            _result.name = input_asn1_schema.name;
+                        }
+                    }
+                    // #endregion 
+
+                    return _result;
+                }
+                // #endregion 
+
+                return in_window.org.pkijs.compareSchema(root, asn1.result, input_asn1_schema.primitive_schema);
+            }
+            else
+                return {
+                    verified: true,
+                    result: root
+                };
+        }
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.verifySchema =
+    function(input_buffer, input_schema)
+    {
+        // #region Initial check 
+        if((input_schema instanceof Object) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema type" }
+            };
+        // #endregion 
+
+        // #region Decoding of raw ASN.1 data 
+        var asn1 = in_window.org.pkijs.fromBER(input_buffer);
+        if(asn1.offset === (-1))
+            return {
+                verified: false,
+                result: asn1.result
+            };
+        // #endregion 
+
+        // #region Compare ASN.1 struct with input schema 
+        return in_window.org.pkijs.compareSchema(asn1.result, asn1.result, input_schema);
+        // #endregion 
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Major function converting JSON to ASN.1 objects 
+    //**************************************************************************************
+    in_window.org.pkijs.fromJSON = 
+    function(json)
+    {
+        /// <summary>Converting from JSON to ASN.1 objects</summary>
+        /// <param name="json" type="String|Object">JSON string or object to convert to ASN.1 objects</param>
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+}
+)(typeof exports !== "undefined" ? exports : window);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/common.js
@@ -0,0 +1,1542 @@
+/*
+ * Copyright (c) 2014, GMO GlobalSign
+ * Copyright (c) 2015, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software without 
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE. 
+ *
+ */
+(
+function(in_window)
+{
+    //**************************************************************************************
+    // #region Declaration of global variables 
+    //**************************************************************************************
+    // #region "org" namespace 
+    if(typeof in_window.org === "undefined")
+        in_window.org = {};
+    else
+    {
+        if(typeof in_window.org !== "object")
+            throw new Error("Name org already exists and it's not an object");
+    }
+    // #endregion 
+
+    // #region "org.pkijs" namespace 
+    if(typeof in_window.org.pkijs === "undefined")
+        in_window.org.pkijs = {};
+    else
+    {
+        if(typeof in_window.org.pkijs !== "object")
+            throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs));
+    }
+    // #endregion 
+
+    // #region "local" namespace 
+    var local = {};
+    // #endregion   
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Settings for "crypto engine" 
+    //**************************************************************************************
+    local.engine = {
+        name: "none",
+        crypto: null,
+        subtle: null
+    };
+
+    if(typeof window != "undefined")
+    {
+        if("crypto" in window)
+        {
+            var engineName = "webcrypto";
+            var cryptoObject = window.crypto;
+            var subtleObject = null;
+
+            // Apple Safari support
+            if("webkitSubtle" in window.crypto)
+                subtleObject = window.crypto.webkitSubtle;
+
+            if("subtle" in window.crypto)
+                subtleObject = window.crypto.subtle;
+
+            local.engine = {
+                name: engineName,
+                crypto: cryptoObject,
+                subtle: subtleObject
+            };
+        }
+    }
+    //**************************************************************************************
+    in_window.org.pkijs.setEngine =
+    function(name, crypto, subtle)
+    {
+        /// <summary>Setting the global "crypto engine" parameters</summary>
+        /// <param name="name" type="String">Auxiliary name for "crypto engine"</param>
+        /// <param name="crypto" type="Object">Object handling all root cryptographic requests (in fact currently it must handle only "getRandomValues")</param>
+        /// <param name="subtle" type="Object">Object handling all main cryptographic requests</param>
+
+        local.engine = {
+            name: name,
+            crypto: crypto,
+            subtle: subtle
+        };
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getEngine =
+    function()
+    {
+        return local.engine;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of common functions 
+    //**************************************************************************************
+    in_window.org.pkijs.emptyObject =
+    function()
+    {
+        this.toJSON = function()
+        {
+            return {};
+        };
+        this.toSchema = function()
+        {
+            return {};
+        };
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getNames =
+    function(arg)
+    {
+        /// <summary>Get correct "names" array for all "schema" objects</summary>
+
+        var names = {};
+
+        if(arg instanceof Object)
+            names = (arg.names || {});
+
+        return names;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.inheriteObjectFields =
+    function(from)
+    {
+        for(var i in from.prototype)
+        {
+            if(typeof from.prototype[i] === "function")
+                continue;
+
+            this[i] = from.prototype[i];
+        }
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getUTCDate =
+    function(date)
+    {
+        /// <summary>Making UTC date from local date</summary>
+        /// <param name="date" type="Date">Date to convert from</param>
+
+        var current_date = date;
+        return new Date(current_date.getTime() + (current_date.getTimezoneOffset() * 60000));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.padNumber =
+    function(input_number, full_length)
+    {
+        var str = input_number.toString(10);
+        var dif = full_length - str.length;
+
+        var padding = new Array(dif);
+        for(var i = 0; i < dif; i++)
+            padding[i] = '0';
+
+        var padding_string = padding.join('');
+
+        return padding_string.concat(str);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getValue =
+    function(args, item, default_value)
+    {
+        if(item in args)
+            return args[item];
+        else
+            return default_value;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.isEqual_view =
+    function(input_view1, input_view2)
+    {
+        /// <summary>Compare two Uint8Arrays</summary>
+        /// <param name="input_view1" type="Uint8Array">First Uint8Array for comparision</param>
+        /// <param name="input_view2" type="Uint8Array">Second Uint8Array for comparision</param>
+
+        if(input_view1.length !== input_view2.length)
+            return false;
+
+        for(var i = 0; i < input_view1.length; i++)
+        {
+            if(input_view1[i] != input_view2[i])
+                return false;
+        }
+
+        return true;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.isEqual_buffer =
+    function(input_buffer1, input_buffer2)
+    {
+        /// <summary>Compare two array buffers</summary>
+        /// <param name="input_buffer1" type="ArrayBuffer">First ArrayBuffer for comparision</param>
+        /// <param name="input_buffer2" type="ArrayBuffer">Second ArrayBuffer for comparision</param>
+
+        if(input_buffer1.byteLength != input_buffer2.byteLength)
+            return false;
+
+        var view1 = new Uint8Array(input_buffer1);
+        var view2 = new Uint8Array(input_buffer2);
+
+        return in_window.org.pkijs.isEqual_view(view1, view2);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.concat_buffers =
+    function(input_buf1, input_buf2)
+    {
+        /// <summary>Concatenate two ArrayBuffers</summary>
+        /// <param name="input_buf1" type="ArrayBuffer">First ArrayBuffer (first part of concatenated array)</param>
+        /// <param name="input_buf2" type="ArrayBuffer">Second ArrayBuffer (second part of concatenated array)</param>
+
+        var input_view1 = new Uint8Array(input_buf1);
+        var input_view2 = new Uint8Array(input_buf2);
+
+        var ret_buf = new ArrayBuffer(input_buf1.byteLength + input_buf2.byteLength);
+        var ret_view = new Uint8Array(ret_buf);
+
+        for(var i = 0; i < input_buf1.byteLength; i++)
+            ret_view[i] = input_view1[i];
+
+        for(var j = 0; j < input_buf2.byteLength; j++)
+            ret_view[input_buf1.byteLength + j] = input_view2[j];
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.copyBuffer =
+    function(input_buffer)
+    {
+        var result = new ArrayBuffer(input_buffer.byteLength);
+
+        var resultView = new Uint8Array(result);
+        var inputView = new Uint8Array(input_buffer);
+
+        for(var i = 0; i < inputView.length; i++)
+            resultView[i] = inputView[i];
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getCrypto =
+    function()
+    {
+        var crypto_temp;
+
+        if(local.engine.subtle !== null)
+            crypto_temp = local.engine.subtle;
+
+        return crypto_temp;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.stringPrep =
+    function(input_string)
+    {
+        /// <summary>String preparation function. In a future here will be realization of algorithm from RFC4518.</summary>
+        /// <param name="input_string" type="String">JavaScript string. As soon as for each ASN.1 string type we have a specific transformation function here we will work with pure JavaScript string</param>
+        /// <returns type="String">Formated string</returns>
+
+        var result = input_string.replace(/^\s+|\s+$/g, ""); // Trim input string
+        result = result.replace(/\s+/g, " "); // Change all sequence of SPACE down to SPACE char
+        result = result.toLowerCase();
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.bufferToHexCodes =
+    function(input_buffer, input_offset, input_lenght)
+    {
+        var result = "";
+
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_lenght);
+
+        for(var i = 0; i < int_buffer.length; i++)
+        {
+            var str = int_buffer[i].toString(16).toUpperCase();
+            result = result + ((str.length === 1) ? "0" : "") + str;
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.bufferFromHexCodes =
+    function(hexString)
+    {
+        /// <summary>Create an ArrayBuffer from string having hexdecimal codes</summary>
+        /// <param name="hexString" type="String">String to create ArrayBuffer from</param>
+
+        // #region Initial variables 
+        var stringLength = hexString.length;
+
+        var resultBuffer = new ArrayBuffer(stringLength >> 1);
+        var resultView = new Uint8Array(resultBuffer);
+
+        var hex_map = {};
+
+        hex_map['0'] = 0x00;
+        hex_map['1'] = 0x01;
+        hex_map['2'] = 0x02;
+        hex_map['3'] = 0x03;
+        hex_map['4'] = 0x04;
+        hex_map['5'] = 0x05;
+        hex_map['6'] = 0x06;
+        hex_map['7'] = 0x07;
+        hex_map['8'] = 0x08;
+        hex_map['9'] = 0x09;
+        hex_map['A'] = 0x0A;
+        hex_map['a'] = 0x0A;
+        hex_map['B'] = 0x0B;
+        hex_map['b'] = 0x0B;
+        hex_map['C'] = 0x0C;
+        hex_map['c'] = 0x0C;
+        hex_map['D'] = 0x0D;
+        hex_map['d'] = 0x0D;
+        hex_map['E'] = 0x0E;
+        hex_map['e'] = 0x0E;
+        hex_map['F'] = 0x0F;
+        hex_map['f'] = 0x0F;
+
+        var j = 0;
+        var temp = 0x00;
+        // #endregion 
+
+        // #region Convert char-by-char 
+        for(var i = 0; i < stringLength; i++)
+        {
+            if(!(i % 2))
+                temp = hex_map[hexString.charAt(i)] << 4;
+            else
+            {
+                temp |= hex_map[hexString.charAt(i)];
+
+                resultView[j] = temp;
+                j++;
+            }
+        }
+        // #endregion 
+
+        return resultBuffer;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getRandomValues =
+    function(view)
+    {
+        /// <param name="view" type="Uint8Array">New array which gives a length for random value</param>
+
+        if(local.engine.crypto !== null)
+            return local.engine.crypto.getRandomValues(view);
+        else
+            throw new Error("No support for Web Cryptography API");
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getAlgorithmParameters =
+    function(algorithmName, operation)
+    {
+        /// <param name="algorithmName" type="String">Algorithm name to get common parameters for</param>
+        /// <param name="operation" type="String">Kind of operation: "sign", "encrypt", "generatekey", "importkey", "exportkey", "verify"</param>
+
+        var result = {
+            algorithm: {},
+            usages: []
+        };
+
+        switch(algorithmName.toUpperCase())
+        {
+            case "RSASSA-PKCS1-V1_5":
+                switch(operation.toLowerCase())
+                {
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "RSASSA-PKCS1-v1_5",
+                                modulusLength: 2048,
+                                publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "verify":
+                    case "sign":
+                    case "importkey":
+                        result = {
+                            algorithm: {
+                                name: "RSASSA-PKCS1-v1_5",
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only
+                        };
+                        break;
+                    case "exportkey":
+                    default:
+                        return {
+                            algorithm: {
+                                name: "RSASSA-PKCS1-v1_5"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "RSA-PSS":
+                switch(operation.toLowerCase())
+                {
+                    case "sign":
+                    case "verify":
+                        result = {
+                            algorithm: {
+                                name: "RSA-PSS",
+                                hash: {
+                                    name: "SHA-1"
+                                },
+                                saltLength: 20
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "RSA-PSS",
+                                modulusLength: 2048,
+                                publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+                                hash: {
+                                    name: "SHA-1"
+                                }
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "importkey":
+                        result = {
+                            algorithm: {
+                                name: "RSA-PSS",
+                                hash: {
+                                    name: "SHA-1"
+                                }
+                            },
+                            usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only
+                        };
+                        break;
+                    case "exportkey":
+                    default:
+                        return {
+                            algorithm: {
+                                name: "RSA-PSS"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "RSA-OAEP":
+                switch(operation.toLowerCase())
+                {
+                    case "encrypt":
+                    case "decrypt":
+                        result = {
+                            algorithm: {
+                                name: "RSA-OAEP"
+                            },
+                            usages: ["encrypt", "decrypt"]
+                        };
+                        break;
+                        break;
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "RSA-OAEP",
+                                modulusLength: 2048,
+                                publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    case "importkey":
+                        result = {
+                            algorithm: {
+                                name: "RSA-OAEP",
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["encrypt"] // encrypt for "spki" and decrypt for "pkcs8"
+                        };
+                        break;
+                    case "exportkey":
+                    default:
+                        return {
+                            algorithm: {
+                                name: "RSA-OAEP"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "ECDSA":
+                switch(operation.toLowerCase())
+                {
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "ECDSA",
+                                namedCurve: "P-256"
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "importkey":
+                        result = {
+                            algorithm: {
+                                name: "ECDSA",
+                                namedCurve: "P-256"
+                            },
+                            usages: ["verify"] // "sign" for "pkcs8"
+                        };
+                        break;
+                    case "verify":
+                    case "sign":
+                        result = {
+                            algorithm: {
+                                name: "ECDSA",
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["sign"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "ECDSA"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "ECDH":
+                switch(operation.toLowerCase())
+                {
+                    case "exportkey":
+                    case "importkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "ECDH",
+                                namedCurve: "P-256"
+                            },
+                            usages: ["deriveKey", "deriveBits"]
+                        };
+                        break;
+                    case "derivekey":
+                    case "derivebits":
+                        result = {
+                            algorithm: {
+                                name: "ECDH",
+                                namedCurve: "P-256",
+                                public: [] // Must be a "publicKey"
+                            },
+                            usages: ["encrypt", "decrypt"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "ECDH"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "AES-CTR":
+                switch(operation.toLowerCase())
+                {
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "AES-CTR",
+                                length: 256
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    case "decrypt":
+                    case "encrypt":
+                        result = {
+                            algorithm: {
+                                name: "AES-CTR",
+                                counter: new Uint8Array(16),
+                                length: 10
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "AES-CTR"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "AES-CBC":
+                switch(operation.toLowerCase())
+                {
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "AES-CBC",
+                                length: 256
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    case "decrypt":
+                    case "encrypt":
+                        result = {
+                            algorithm: {
+                                name: "AES-CBC",
+                                iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "AES-CBC"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "AES-GCM":
+                switch(operation.toLowerCase())
+                {
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "AES-GCM",
+                                length: 256
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    case "decrypt":
+                    case "encrypt":
+                        result = {
+                            algorithm: {
+                                name: "AES-GCM",
+                                iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "AES-GCM"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "AES-KW":
+                switch(operation.toLowerCase())
+                {
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                    case "wrapkey":
+                    case "unwrapkey":
+                        result = {
+                            algorithm: {
+                                name: "AES-KW",
+                                length: 256
+                            },
+                            usages: ["wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "AES-KW"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "HMAC":
+                switch(operation.toLowerCase())
+                {
+                    case "sign":
+                    case "verify":
+                        result = {
+                            algorithm: {
+                                name: "HMAC"
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "HMAC",
+                                length: 32,
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "HMAC"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "HKDF":
+                switch(operation.toLowerCase())
+                {
+                    case "derivekey":
+                        result = {
+                            algorithm: {
+                                name: "HKDF",
+                                hash: "SHA-256",
+                                salt: new Uint8Array(),
+                                info: new Uint8Array()
+                            },
+                            usages: ["encrypt", "decrypt"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "HKDF"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "PBKDF2":
+                switch(operation.toLowerCase())
+                {
+                    case "derivekey":
+                        result = {
+                            algorithm: {
+                                name: "PBKDF2",
+                                hash: { name: "SHA-256" },
+                                salt: new Uint8Array(),
+                                iterations: 1000
+                            },
+                            usages: ["encrypt", "decrypt"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "PBKDF2"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getOIDByAlgorithm =
+    function(algorithm)
+    {
+        /// <summary>Get OID for each specific WebCrypto algorithm</summary>
+        /// <param name="algorithm" type="Object">WebCrypto algorithm</param>
+
+        var result = "";
+
+        switch(algorithm.name.toUpperCase())
+        {
+            case "RSASSA-PKCS1-V1_5":
+                switch(algorithm.hash.name.toUpperCase())
+                {
+                    case "SHA-1":
+                        result = "1.2.840.113549.1.1.5";
+                        break;
+                    case "SHA-256":
+                        result = "1.2.840.113549.1.1.11";
+                        break;
+                    case "SHA-384":
+                        result = "1.2.840.113549.1.1.12";
+                        break;
+                    case "SHA-512":
+                        result = "1.2.840.113549.1.1.13";
+                        break;
+                    default:
+                }
+                break;
+            case "RSA-PSS":
+                result = "1.2.840.113549.1.1.10";
+                break;
+            case "RSA-OAEP":
+                result = "1.2.840.113549.1.1.7";
+                break;
+            case "ECDSA":
+                switch(algorithm.hash.name.toUpperCase())
+                {
+                    case "SHA-1":
+                        result = "1.2.840.10045.4.1";
+                        break;
+                    case "SHA-256":
+                        result = "1.2.840.10045.4.3.2";
+                        break;
+                    case "SHA-384":
+                        result = "1.2.840.10045.4.3.3";
+                        break;
+                    case "SHA-512":
+                        result = "1.2.840.10045.4.3.4";
+                        break;
+                    default:
+                }
+                break;
+            case "ECDH":
+                switch(algorithm.kdf.toUpperCase()) // Non-standard addition - hash algorithm of KDF function
+                {
+                    case "SHA-1":
+                        result = "1.3.133.16.840.63.0.2"; // dhSinglePass-stdDH-sha1kdf-scheme
+                        break;
+                    case "SHA-256":
+                        result = "1.3.132.1.11.1"; // dhSinglePass-stdDH-sha256kdf-scheme 
+                        break;
+                    case "SHA-384":
+                        result = "1.3.132.1.11.2"; // dhSinglePass-stdDH-sha384kdf-scheme
+                        break;
+                    case "SHA-512":
+                        result = "1.3.132.1.11.3"; // dhSinglePass-stdDH-sha512kdf-scheme
+                        break;
+                    default:
+                }
+                break;
+            case "AES-CTR":
+                break;
+            case "AES-CBC":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.2";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.22";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.42";
+                        break;
+                    default:
+                }
+                break;
+            case "AES-CMAC":
+                break;
+            case "AES-GCM":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.6";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.26";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.46";
+                        break;
+                    default:
+                }
+                break;
+            case "AES-CFB":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.4";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.24";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.44";
+                        break;
+                    default:
+                }
+                break;
+            case "AES-KW":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.5";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.25";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.45";
+                        break;
+                    default:
+                }
+                break;
+            case "HMAC":
+                switch(algorithm.hash.name.toUpperCase())
+                {
+                    case "SHA-1":
+                        result = "1.2.840.113549.2.7";
+                        break;
+                    case "SHA-256":
+                        result = "1.2.840.113549.2.9";
+                        break;
+                    case "SHA-384":
+                        result = "1.2.840.113549.2.10";
+                        break;
+                    case "SHA-512":
+                        result = "1.2.840.113549.2.11";
+                        break;
+                    default:
+                }
+                break;
+            case "DH":
+                result = "1.2.840.113549.1.9.16.3.5";
+                break;
+            case "SHA-1":
+                result = "1.3.14.3.2.26";
+                break;
+            case "SHA-256":
+                result = "2.16.840.1.101.3.4.2.1";
+                break;
+            case "SHA-384":
+                result = "2.16.840.1.101.3.4.2.2";
+                break;
+            case "SHA-512":
+                result = "2.16.840.1.101.3.4.2.3";
+                break;
+            case "CONCAT":
+                break;
+            case "HKDF":
+                break;
+            case "PBKDF2":
+                result = "1.2.840.113549.1.5.12";
+                break;
+            // #region Special case - OIDs for ECC curves 
+            case "P-256":
+                result = "1.2.840.10045.3.1.7";
+                break;
+            case "P-384":
+                result = "1.3.132.0.34";
+                break;
+            case "P-521":
+                result = "1.3.132.0.35";
+                break;
+            // #endregion 
+
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getAlgorithmByOID =
+    function(oid)
+    {
+        /// <summary>Get WebCrypto algorithm by wel-known OID</summary>
+        /// <param name="oid" type="String">Wel-known OID to search for</param>
+
+        var result = {};
+
+        switch(oid)
+        {
+            case "1.2.840.113549.1.1.5":
+                result = {
+                    name: "RSASSA-PKCS1-v1_5",
+                    hash: {
+                        name: "SHA-1"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.1.11":
+                result = {
+                    name: "RSASSA-PKCS1-v1_5",
+                    hash: {
+                        name: "SHA-256"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.1.12":
+                result = {
+                    name: "RSASSA-PKCS1-v1_5",
+                    hash: {
+                        name: "SHA-384"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.1.13":
+                result = {
+                    name: "RSASSA-PKCS1-v1_5",
+                    hash: {
+                        name: "SHA-512"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.1.10":
+                result = {
+                    name: "RSA-PSS"
+                };
+                break;
+            case "1.2.840.113549.1.1.7":
+                result = {
+                    name: "RSA-OAEP"
+                };
+                break;
+            case "1.2.840.10045.4.1":
+                result = {
+                    name: "ECDSA",
+                    hash: {
+                        name: "SHA-1"
+                    }
+                };
+                break;
+            case "1.2.840.10045.4.3.2":
+                result = {
+                    name: "ECDSA",
+                    hash: {
+                        name: "SHA-256"
+                    }
+                };
+                break;
+            case "1.2.840.10045.4.3.3":
+                result = {
+                    name: "ECDSA",
+                    hash: {
+                        name: "SHA-384"
+                    }
+                };
+                break;
+            case "1.2.840.10045.4.3.4":
+                result = {
+                    name: "ECDSA",
+                    hash: {
+                        name: "SHA-512"
+                    }
+                };
+                break;
+            case "1.3.133.16.840.63.0.2":
+                result = {
+                    name: "ECDH",
+                    kdf: "SHA-1"
+                };
+                break;
+            case "1.3.132.1.11.1":
+                result = {
+                    name: "ECDH",
+                    kdf: "SHA-256"
+                };
+                break;
+            case "1.3.132.1.11.2":
+                result = {
+                    name: "ECDH",
+                    kdf: "SHA-384"
+                };
+                break;
+            case "1.3.132.1.11.3":
+                result = {
+                    name: "ECDH",
+                    kdf: "SHA-512"
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.2":
+                result = {
+                    name: "AES-CBC",
+                    length: 128
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.22":
+                result = {
+                    name: "AES-CBC",
+                    length: 192
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.42":
+                result = {
+                    name: "AES-CBC",
+                    length: 256
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.6":
+                result = {
+                    name: "AES-GCM",
+                    length: 128
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.26":
+                result = {
+                    name: "AES-GCM",
+                    length: 192
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.46":
+                result = {
+                    name: "AES-GCM",
+                    length: 256
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.4":
+                result = {
+                    name: "AES-CFB",
+                    length: 128
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.24":
+                result = {
+                    name: "AES-CFB",
+                    length: 192
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.44":
+                result = {
+                    name: "AES-CFB",
+                    length: 256
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.5":
+                result = {
+                    name: "AES-KW",
+                    length: 128
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.25":
+                result = {
+                    name: "AES-KW",
+                    length: 192
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.45":
+                result = {
+                    name: "AES-KW",
+                    length: 256
+                };
+                break;
+            case "1.2.840.113549.2.7":
+                result = {
+                    name: "HMAC",
+                    hash: {
+                        name: "SHA-1"
+                    }
+                };
+                break;
+            case "1.2.840.113549.2.9":
+                result = {
+                    name: "HMAC",
+                    hash: {
+                        name: "SHA-256"
+                    }
+                };
+                break;
+            case "1.2.840.113549.2.10":
+                result = {
+                    name: "HMAC",
+                    hash: {
+                        name: "SHA-384"
+                    }
+                };
+                break;
+            case "1.2.840.113549.2.11":
+                result = {
+                    name: "HMAC",
+                    hash: {
+                        name: "SHA-512"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.9.16.3.5":
+                result = {
+                    name: "DH"
+                };
+                break;
+            case "1.3.14.3.2.26":
+                result = {
+                    name: "SHA-1"
+                };
+                break;
+            case "2.16.840.1.101.3.4.2.1":
+                result = {
+                    name: "SHA-256"
+                };
+                break;
+            case "2.16.840.1.101.3.4.2.2":
+                result = {
+                    name: "SHA-384"
+                };
+                break;
+            case "2.16.840.1.101.3.4.2.3":
+                result = {
+                    name: "SHA-512"
+                };
+                break;
+            case "1.2.840.113549.1.5.12":
+                result = {
+                    name: "PBKDF2"
+                };
+                break;
+            // #region Special case - OIDs for ECC curves 
+            case "1.2.840.10045.3.1.7":
+                result = {
+                    name: "P-256"
+                };
+                break;
+            case "1.3.132.0.34":
+                result = {
+                    name: "P-384"
+                };
+                break;
+            case "1.3.132.0.35":
+                result = {
+                    name: "P-521"
+                };
+                break;
+            // #endregion 
+
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getHashAlgorithm =
+    function(signatureAlgorithm)
+    {
+        /// <summary>Getting hash algorithm by signature algorithm</summary>
+        /// <param name="signatureAlgorithm" type="in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER">Signature algorithm</param>
+
+        var result = "";
+
+        switch(signatureAlgorithm.algorithm_id)
+        {
+            case "1.2.840.10045.4.1": // ecdsa-with-SHA1
+            case "1.2.840.113549.1.1.5":
+                result = "SHA-1";
+                break;
+            case "1.2.840.10045.4.3.2": // ecdsa-with-SHA256
+            case "1.2.840.113549.1.1.11":
+                result = "SHA-256";
+                break;
+            case "1.2.840.10045.4.3.3": // ecdsa-with-SHA384
+            case "1.2.840.113549.1.1.12":
+                result = "SHA-384";
+                break;
+            case "1.2.840.10045.4.3.4": // ecdsa-with-SHA512
+            case "1.2.840.113549.1.1.13":
+                result = "SHA-512";
+                break;
+            case "1.2.840.113549.1.1.10": // RSA-PSS
+                {
+                    var params;
+
+                    try
+                    {
+                        params = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: signatureAlgorithm.algorithm_params });
+                        if("hashAlgorithm" in params)
+                        {
+                            var algorithm = in_window.org.pkijs.getAlgorithmByOID(params.hashAlgorithm.algorithm_id);
+                            if(("name" in algorithm) === false)
+                                return "";
+
+                            result = algorithm.name;
+                        }
+                        else
+                            result = "SHA-1";
+                    }
+                    catch(ex)
+                    {
+                    }
+                }
+                break;
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.createCMSECDSASignature =
+    function(signatureBuffer)
+    {
+        /// <summary>Create CMS ECDSA signature from WebCrypto ECDSA signature</summary>
+        /// <param name="signatureBuffer" type="ArrayBuffer">WebCrypto result of "sign" function</param>
+
+        // #region Initial check for correct length 
+        if((signatureBuffer.byteLength % 2) != 0)
+            return new ArrayBuffer(0);
+        // #endregion 
+
+        // #region Initial variables 
+        var i = 0;
+        var length = signatureBuffer.byteLength / 2; // There are two equal parts inside incoming ArrayBuffer
+
+        var signatureView = new Uint8Array(signatureBuffer);
+
+        var r_buffer = new ArrayBuffer(length);
+        var r_view = new Uint8Array(r_buffer);
+        var r_corrected_buffer;
+        var r_corrected_view;
+
+        var s_buffer = new ArrayBuffer(length);
+        var s_view = new Uint8Array(s_buffer);
+        var s_corrected_buffer;
+        var s_corrected_view;
+        // #endregion   
+
+        // #region Get "r" part of ECDSA signature 
+        for(; i < length; i++)
+            r_view[i] = signatureView[i];
+
+        if(r_view[0] & 0x80)
+        {
+            r_corrected_buffer = new ArrayBuffer(length + 1);
+            r_corrected_view = new Uint8Array(r_corrected_buffer);
+
+            r_corrected_view[0] = 0x00;
+
+            for(var j = 0; j < length; j++)
+                r_corrected_view[j + 1] = r_view[j];
+        }
+        else
+        {
+            r_corrected_buffer = r_buffer;
+            r_corrected_view = r_view;
+        }
+        // #endregion 
+
+        // #region Get "s" part of ECDSA signature 
+        for(; i < signatureBuffer.byteLength; i++)
+            s_view[i - length] = signatureView[i];
+
+
+        if(s_view[0] & 0x80)
+        {
+            s_corrected_buffer = new ArrayBuffer(length + 1);
+            s_corrected_view = new Uint8Array(s_corrected_buffer);
+
+            s_corrected_view[0] = 0x00;
+
+            for(var j = 0; j < length; j++)
+                s_corrected_view[j + 1] = s_view[j];
+        }
+        else
+        {
+            s_corrected_buffer = s_buffer;
+            s_corrected_view = s_view;
+        }
+        // #endregion 
+
+        // #region Create ASN.1 structure of CMS ECDSA signature 
+        var r_integer = new in_window.org.pkijs.asn1.INTEGER();
+        r_integer.value_block.is_hex_only = true;
+        r_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(r_corrected_buffer);
+
+        var s_integer = new in_window.org.pkijs.asn1.INTEGER();
+        s_integer.value_block.is_hex_only = true;
+        s_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(s_corrected_buffer);
+
+        var asn1 = new in_window.org.pkijs.asn1.SEQUENCE({
+            value: [
+                r_integer,
+                s_integer
+            ]
+        });
+        // #endregion   
+
+        return asn1.toBER(false);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.createECDSASignatureFromCMS =
+    function(cmsSignature)
+    {
+        /// <summary>Create a single ArrayBuffer from CMS ECDSA signature</summary>
+        /// <param name="cmsSignature" type="in_window.org.pkijs.asn1.SEQUENCE">ASN.1 SEQUENCE contains CMS ECDSA signature</param>
+
+        // #region Initial variables 
+        var length = 0;
+
+        var r_start = 0;
+        var s_start = 0;
+
+        var r_length = cmsSignature.value_block.value[0].value_block.value_hex.byteLength;
+        var s_length = cmsSignature.value_block.value[1].value_block.value_hex.byteLength;
+        // #endregion 
+
+        // #region Get length of final "ArrayBuffer" 
+        var r_view = new Uint8Array(cmsSignature.value_block.value[0].value_block.value_hex);
+        if((r_view[0] === 0x00) && (r_view[1] & 0x80))
+        {
+            length = r_length - 1;
+            r_start = 1;
+        }
+        else
+            length = r_length;
+
+        var s_view = new Uint8Array(cmsSignature.value_block.value[1].value_block.value_hex);
+        if((s_view[0] === 0x00) && (s_view[1] & 0x80))
+        {
+            length += s_length - 1;
+            s_start = 1;
+        }
+        else
+            length += s_length;
+        // #endregion 
+
+        // #region Copy values from CMS ECDSA signature 
+        var result = new ArrayBuffer(length);
+        var result_view = new Uint8Array(result);
+
+        for(var i = r_start; i < r_length; i++)
+            result_view[i - r_start] = r_view[i];
+
+        for(var i = s_start; i < s_length; i++)
+            result_view[i - s_start + r_length - r_start] = s_view[i];
+        // #endregion 
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getEncryptionAlgorithm =
+    function(algorithm)
+    {
+        /// <summary>Get encryption algorithm OID by WebCrypto algorithm's object</summary>
+        /// <param name="algorithm" type="WebCryptoAlgorithm">WebCrypto algorithm object</param>
+
+        var result = "";
+
+        switch(algorithm.name.toUpperCase())
+        {
+            case "AES-CBC":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.2";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.22";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.42";
+                        break;
+                    default:
+                }
+                break;
+            case "AES-GCM":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.6";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.26";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.46";
+                        break;
+                    default:
+                }
+                break;
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getAlgorithmByEncryptionOID =
+    function(oid)
+    {
+        /// <summary>Get encryption algorithm name by OID</summary>
+        /// <param name="oid" type="String">OID of encryption algorithm</param>
+
+        var result = "";
+
+        switch(oid)
+        {
+            case "2.16.840.1.101.3.4.1.2":
+            case "2.16.840.1.101.3.4.1.22":
+            case "2.16.840.1.101.3.4.1.42":
+                result = "AES-CBC";
+                break;
+            case "2.16.840.1.101.3.4.1.6":
+            case "2.16.840.1.101.3.4.1.26":
+            case "2.16.840.1.101.3.4.1.46":
+                result = "AES-GCM";
+                break;
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+}
+)(typeof exports !== "undefined" ? exports : window);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/x509_schema.js
@@ -0,0 +1,1889 @@
+/*
+ * Copyright (c) 2014, GMO GlobalSign
+ * Copyright (c) 2015, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software without 
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE. 
+ *
+ */
+(
+function(in_window)
+{
+    //**************************************************************************************
+    // #region Declaration of global variables 
+    //**************************************************************************************
+    // #region "org" namespace 
+    if(typeof in_window.org === "undefined")
+        in_window.org = {};
+    else
+    {
+        if(typeof in_window.org !== "object")
+            throw new Error("Name org already exists and it's not an object");
+    }
+    // #endregion 
+
+    // #region "org.pkijs" namespace 
+    if(typeof in_window.org.pkijs === "undefined")
+        in_window.org.pkijs = {};
+    else
+    {
+        if(typeof in_window.org.pkijs !== "object")
+            throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs));
+    }
+    // #endregion 
+
+    // #region "org.pkijs.schema" namespace 
+    if(typeof in_window.org.pkijs.schema === "undefined")
+        in_window.org.pkijs.schema = {};
+    else
+    {
+        if(typeof in_window.org.pkijs.schema !== "object")
+            throw new Error("Name org.pkijs.schema already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema));
+    }
+    // #endregion 
+
+    // #region "org.pkijs.schema.x509" namespace 
+    if(typeof in_window.org.pkijs.schema.x509 === "undefined")
+        in_window.org.pkijs.schema.x509 = {};
+    else
+    {
+        if(typeof in_window.org.pkijs.schema.x509 !== "object")
+            throw new Error("Name org.pkijs.schema.x509 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema.x509));
+    }
+    // #endregion 
+
+    // #region "local" namespace 
+    var local = {};
+    // #endregion   
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "Time" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.TIME =
+    function(input_names, input_optional)
+    {
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+        var optional = (input_optional || false);
+
+        return (new in_window.org.pkijs.asn1.CHOICE({
+            optional: optional,
+            value: [
+                new in_window.org.pkijs.asn1.UTCTIME({ name: (names.utcTimeName || "") }),
+                new in_window.org.pkijs.asn1.GENERALIZEDTIME({ name: (names.generalTimeName || "") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for X.509 v3 certificate (RFC5280)
+    //**************************************************************************************
+    local.tbsCertificate =
+    function()
+    {
+        //TBSCertificate  ::=  SEQUENCE  {
+        //    version         [0]  EXPLICIT Version DEFAULT v1,
+        //    serialNumber         CertificateSerialNumber,
+        //    signature            AlgorithmIdentifier,
+        //    issuer               Name,
+        //    validity             Validity,
+        //    subject              Name,
+        //    subjectPublicKeyInfo SubjectPublicKeyInfo,
+        //    issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+        //                         -- If present, version MUST be v2 or v3
+        //    subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+        //                         -- If present, version MUST be v2 or v3
+        //    extensions      [3]  EXPLICIT Extensions OPTIONAL
+        //    -- If present, version MUST be v3
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || "tbsCertificate"),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                value: [
+                    new in_window.org.pkijs.asn1.INTEGER({ name: (names.tbsCertificate_version || "tbsCertificate.version") }) // EXPLICIT integer value
+                ]
+            }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.tbsCertificate_serialNumber || "tbsCertificate.serialNumber") }),
+                in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signature || {
+                    names: {
+                        block_name: "tbsCertificate.signature"
+                    }
+                }),
+                in_window.org.pkijs.schema.RDN(names.issuer || {
+                    names: {
+                        block_name: "tbsCertificate.issuer"
+                    }
+                }),
+                new in_window.org.pkijs.asn1.SEQUENCE({
+                    name: (names.tbsCertificate_validity || "tbsCertificate.validity"),
+                    value: [
+                        in_window.org.pkijs.schema.TIME(names.not_before || {
+                            names: {
+                                utcTimeName: "tbsCertificate.notBefore",
+                                generalTimeName: "tbsCertificate.notBefore"
+                            }
+                        }),
+                        in_window.org.pkijs.schema.TIME(names.not_after || {
+                            names: {
+                                utcTimeName: "tbsCertificate.notAfter",
+                                generalTimeName: "tbsCertificate.notAfter"
+                            }
+                        })
+                    ]
+                }),
+                in_window.org.pkijs.schema.RDN(names.subject || {
+                    names: {
+                        block_name: "tbsCertificate.subject"
+                    }
+                }),
+                in_window.org.pkijs.schema.PUBLIC_KEY_INFO(names.subjectPublicKeyInfo || {
+                    names: {
+                        block_name: "tbsCertificate.subjectPublicKeyInfo"
+                    }
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.tbsCertificate_issuerUniqueID ||"tbsCertificate.issuerUniqueID"),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    }
+                }), // IMPLICIT bistring value
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.tbsCertificate_subjectUniqueID ||"tbsCertificate.subjectUniqueID"),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 2 // [2]
+                    }
+                }), // IMPLICIT bistring value
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 3 // [3]
+                    },
+                    value: [in_window.org.pkijs.schema.EXTENSIONS(names.extensions || {
+                        names: {
+                            block_name: "tbsCertificate.extensions"
+                        }
+                    })]
+                }) // EXPLICIT SEQUENCE value
+            ]
+        }));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.schema.CERT =
+    function()
+    {
+        //Certificate  ::=  SEQUENCE  {
+        //    tbsCertificate       TBSCertificate,
+        //    signatureAlgorithm   AlgorithmIdentifier,
+        //    signatureValue       BIT STRING  }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                local.tbsCertificate(names.tbsCertificate),
+                in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signatureAlgorithm || {
+                    names: {
+                        block_name: "signatureAlgorithm"
+                    }
+                }),
+                new in_window.org.pkijs.asn1.BITSTRING({ name: (names.signatureValue || "signatureValue") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for X.509 CRL (Certificate Revocation List)(RFC5280)  
+    //**************************************************************************************
+    local.tbsCertList =
+    function()
+    {
+        //TBSCertList  ::=  SEQUENCE  {
+        //    version                 Version OPTIONAL,
+        //                                 -- if present, MUST be v2
+        //    signature               AlgorithmIdentifier,
+        //    issuer                  Name,
+        //    thisUpdate              Time,
+        //    nextUpdate              Time OPTIONAL,
+        //    revokedCertificates     SEQUENCE OF SEQUENCE  {
+        //        userCertificate         CertificateSerialNumber,
+        //        revocationDate          Time,
+        //        crlEntryExtensions      Extensions OPTIONAL
+        //        -- if present, version MUST be v2
+        //    }  OPTIONAL,
+        //    crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
+        //    -- if present, version MUST be v2
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || "tbsCertList"),
+            value: [
+                        new in_window.org.pkijs.asn1.INTEGER({
+                            optional: true,
+                            name: (names.tbsCertList_version || "tbsCertList.version"),
+                            value: 2
+                        }), // EXPLICIT integer value (v2)
+                        in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signature || {
+                            names: {
+                                block_name: "tbsCertList.signature"
+                            }
+                        }),
+                        in_window.org.pkijs.schema.RDN(names.issuer || {
+                            names: {
+                                block_name: "tbsCertList.issuer"
+                            }
+                        }),
+                        in_window.org.pkijs.schema.TIME(names.tbsCertList_thisUpdate || {
+                            names: {
+                                utcTimeName: "tbsCertList.thisUpdate",
+                                generalTimeName: "tbsCertList.thisUpdate"
+                            }
+                        }),
+                        in_window.org.pkijs.schema.TIME(names.tbsCertList_thisUpdate || {
+                            names: {
+                                utcTimeName: "tbsCertList.nextUpdate",
+                                generalTimeName: "tbsCertList.nextUpdate"
+                            }
+                        }, true),
+                        new in_window.org.pkijs.asn1.SEQUENCE({
+                            optional: true,
+                            value: [
+                                new in_window.org.pkijs.asn1.REPEATED({
+                                    name: (names.tbsCertList_revokedCertificates || "tbsCertList.revokedCertificates"),
+                                    value: new in_window.org.pkijs.asn1.SEQUENCE({
+                                        value: [
+                                            new in_window.org.pkijs.asn1.INTEGER(),
+                                            in_window.org.pkijs.schema.TIME(),
+                                            in_window.org.pkijs.schema.EXTENSIONS({}, true)
+                                        ]
+                                    })
+                                })
+                            ]
+                        }),
+                        new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                            optional: true,
+                            id_block: {
+                                tag_class: 3, // CONTEXT-SPECIFIC
+                                tag_number: 0 // [0]
+                            },
+                            value: [in_window.org.pkijs.schema.EXTENSIONS(names.crlExtensions || {
+                                names: {
+                                    block_name: "tbsCertList.extensions"
+                                }
+                            })]
+                        }) // EXPLICIT SEQUENCE value
+                    ]
+        }));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.schema.CRL =
+    function()
+    {
+        //CertificateList  ::=  SEQUENCE  {
+        //    tbsCertList          TBSCertList,
+        //    signatureAlgorithm   AlgorithmIdentifier,
+        //    signatureValue       BIT STRING  }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || "CertificateList"),
+            value: [
+                local.tbsCertList(arguments[0]),
+                in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signatureAlgorithm || {
+                    names: {
+                        block_name: "signatureAlgorithm"
+                    }
+                }),
+                new in_window.org.pkijs.asn1.BITSTRING({ name: (names.signatureValue || "signatureValue") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for PKCS#10 certificate request 
+    //**************************************************************************************
+    local.CertificationRequestInfo =
+    function()
+    {
+        //CertificationRequestInfo ::= SEQUENCE {
+        //    version       INTEGER { v1(0) } (v1,...),
+        //    subject       Name,
+        //    subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+        //    attributes    [0] Attributes{{ CRIAttributes }}
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.CertificationRequestInfo || "CertificationRequestInfo"),
+            value: [
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.CertificationRequestInfo_version || "CertificationRequestInfo.version") }),
+                new in_window.org.pkijs.schema.RDN(names.subject || {
+                    names: {
+                        block_name: "CertificationRequestInfo.subject"
+                    }
+                }),
+                new in_window.org.pkijs.schema.PUBLIC_KEY_INFO({
+                    names: {
+                        block_name: "CertificationRequestInfo.subjectPublicKeyInfo"
+                    }
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            optional: true, // Because OpenSSL makes wrong "attributes" field
+                            name: (names.CertificationRequestInfo_attributes || "CertificationRequestInfo.attributes"),
+                            value: in_window.org.pkijs.schema.ATTRIBUTE(names.attributes || {})
+                        })
+                    ]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.schema.PKCS10 =
+    function()
+    {
+        //CertificationRequest ::= SEQUENCE {
+        //    certificationRequestInfo CertificationRequestInfo,
+        //    signatureAlgorithm       AlgorithmIdentifier{{ SignatureAlgorithms }},
+        //    signature                BIT STRING
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            value: [
+                local.CertificationRequestInfo(names.certificationRequestInfo || {}),
+                new in_window.org.pkijs.asn1.SEQUENCE({
+                    name: (names.signatureAlgorithm || "signatureAlgorithm"),
+                    value: [
+                        new in_window.org.pkijs.asn1.OID(),
+                        new in_window.org.pkijs.asn1.ANY({ optional: true })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.BITSTRING({ name: (names.signatureValue || "signatureValue") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for PKCS#8 private key bag
+    //**************************************************************************************
+    in_window.org.pkijs.schema.PKCS8 =
+    function()
+    {
+        //PrivateKeyInfo ::= SEQUENCE {
+        //    version Version,
+        //    privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+        //    privateKey PrivateKey,
+        //    attributes [0] Attributes OPTIONAL }
+        //
+        //Version ::= INTEGER {v1(0)} (v1,...)
+        //
+        //PrivateKey ::= OCTET STRING
+        //
+        //Attributes ::= SET OF Attribute
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            value: [
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }),
+                in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.privateKeyAlgorithm || ""),
+                new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.privateKey || "") }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            name: (names.attributes || ""),
+                            value: in_window.org.pkijs.schema.ATTRIBUTE()
+                        })
+                    ]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "GeneralName" type 
+    //**************************************************************************************
+    local.BuiltInStandardAttributes =
+    function(optional_flag)
+    {
+        //BuiltInStandardAttributes ::= SEQUENCE {
+        //    country-name                  CountryName OPTIONAL,
+        //    administration-domain-name    AdministrationDomainName OPTIONAL,
+        //    network-address           [0] IMPLICIT NetworkAddress OPTIONAL,
+        //    terminal-identifier       [1] IMPLICIT TerminalIdentifier OPTIONAL,
+        //    private-domain-name       [2] PrivateDomainName OPTIONAL,
+        //    organization-name         [3] IMPLICIT OrganizationName OPTIONAL,
+        //    numeric-user-identifier   [4] IMPLICIT NumericUserIdentifier OPTIONAL,
+        //    personal-name             [5] IMPLICIT PersonalName OPTIONAL,
+        //    organizational-unit-names [6] IMPLICIT OrganizationalUnitNames OPTIONAL }
+
+        if(typeof optional_flag === "undefined")
+            optional_flag = false;
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            optional: optional_flag,
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 2, // APPLICATION-SPECIFIC
+                        tag_number: 1 // [1]
+                    },
+                    name: (names.country_name || ""),
+                    value: [
+                        new in_window.org.pkijs.asn1.CHOICE({
+                            value: [
+                                new in_window.org.pkijs.asn1.NUMERICSTRING(),
+                                new in_window.org.pkijs.asn1.PRINTABLESTRING()
+                            ]
+                        })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 2, // APPLICATION-SPECIFIC
+                        tag_number: 2 // [2]
+                    },
+                    name: (names.administration_domain_name || ""),
+                    value: [
+                        new in_window.org.pkijs.asn1.CHOICE({
+                            value: [
+                                new in_window.org.pkijs.asn1.NUMERICSTRING(),
+                                new in_window.org.pkijs.asn1.PRINTABLESTRING()
+                            ]
+                        })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    name: (names.network_address || ""),
+                    is_hex_only: true
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    },
+                    name: (names.terminal_identifier || ""),
+                    is_hex_only: true
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 2 // [2]
+                    },
+                    name: (names.private_domain_name || ""),
+                    value: [
+                        new in_window.org.pkijs.asn1.CHOICE({
+                            value: [
+                                new in_window.org.pkijs.asn1.NUMERICSTRING(),
+                                new in_window.org.pkijs.asn1.PRINTABLESTRING()
+                            ]
+                        })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 3 // [3]
+                    },
+                    name: (names.organization_name || ""),
+                    is_hex_only: true
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    optional: true,
+                    name: (names.numeric_user_identifier || ""),
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 4 // [4]
+                    },
+                    is_hex_only: true
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    name: (names.personal_name || ""),
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 5 // [5]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                            id_block: {
+                                tag_class: 3, // CONTEXT-SPECIFIC
+                                tag_number: 0 // [0]
+                            },
+                            is_hex_only: true
+                        }),
+                        new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                            optional: true,
+                            id_block: {
+                                tag_class: 3, // CONTEXT-SPECIFIC
+                                tag_number: 1 // [1]
+                            },
+                            is_hex_only: true
+                        }),
+                        new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                            optional: true,
+                            id_block: {
+                                tag_class: 3, // CONTEXT-SPECIFIC
+                                tag_number: 2 // [2]
+                            },
+                            is_hex_only: true
+                        }),
+                        new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                            optional: true,
+                            id_block: {
+                                tag_class: 3, // CONTEXT-SPECIFIC
+                                tag_number: 3 // [3]
+                            },
+                            is_hex_only: true
+                        })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    name: (names.organizational_unit_names || ""),
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 6 // [6]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            value: new in_window.org.pkijs.asn1.PRINTABLESTRING()
+                        })
+                    ]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    local.BuiltInDomainDefinedAttributes =
+    function(optional_flag)
+    {
+        if(typeof optional_flag === "undefined")
+            optional_flag = false;
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            optional: optional_flag,
+            value: [
+                new in_window.org.pkijs.asn1.PRINTABLESTRING(),
+                new in_window.org.pkijs.asn1.PRINTABLESTRING()
+            ]
+        }));
+    };
+    //**************************************************************************************
+    local.ExtensionAttributes =
+    function(optional_flag)
+    {
+        if(typeof optional_flag === "undefined")
+            optional_flag = false;
+
+        return (new in_window.org.pkijs.asn1.SET({
+            optional: optional_flag,
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    is_hex_only: true
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    },
+                    value: [new in_window.org.pkijs.asn1.ANY()]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.schema.GENERAL_NAME =
+    function()
+    {
+        /// <remarks>By passing "names" array as an argument you can name each element of "GENERAL NAME" choice</remarks>
+
+        //GeneralName ::= CHOICE {
+        //    otherName                       [0]     OtherName,
+        //    rfc822Name                      [1]     IA5String,
+        //    dNSName                         [2]     IA5String,
+        //    x400Address                     [3]     ORAddress,
+        //    directoryName                   [4]     Name,
+        //    ediPartyName                    [5]     EDIPartyName,
+        //    uniformResourceIdentifier       [6]     IA5String,
+        //    iPAddress                       [7]     OCTET STRING,
+        //    registeredID                    [8]     OBJECT IDENTIFIER }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.CHOICE({
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    name: (names.block_name || ""),
+                    value: [
+                            new in_window.org.pkijs.asn1.OID(),
+                            new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                                id_block: {
+                                    tag_class: 3, // CONTEXT-SPECIFIC
+                                    tag_number: 0 // [0]
+                                },
+                                value: [new in_window.org.pkijs.asn1.ANY()]
+                            })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.block_name || ""),
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    }
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.block_name || ""),
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 2 // [2]
+                    }
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 3 // [3]
+                    },
+                    name: (names.block_name || ""),
+                    value: [
+                            local.BuiltInStandardAttributes(false),
+                            local.BuiltInDomainDefinedAttributes(true),
+                            local.ExtensionAttributes(true)
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 4 // [4]
+                    },
+                    name: (names.block_name || ""),
+                    value: [in_window.org.pkijs.schema.RDN(names.directoryName || {})]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 5 // [5]
+                    },
+                    name: (names.block_name || ""),
+                    value: [
+                            new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                                optional: true,
+                                id_block: {
+                                    tag_class: 3, // CONTEXT-SPECIFIC
+                                    tag_number: 0 // [0]
+                                },
+                                value: [
+                                    new in_window.org.pkijs.asn1.CHOICE({
+                                        value: [
+                                            new in_window.org.pkijs.asn1.TELETEXSTRING(),
+                                            new in_window.org.pkijs.asn1.PRINTABLESTRING(),
+                                            new in_window.org.pkijs.asn1.UNIVERSALSTRING(),
+                                            new in_window.org.pkijs.asn1.UTF8STRING(),
+                                            new in_window.org.pkijs.asn1.BMPSTRING()
+                                        ]
+                                    })
+                                ]
+                            }),
+                            new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                                id_block: {
+                                    tag_class: 3, // CONTEXT-SPECIFIC
+                                    tag_number: 1 // [1]
+                                },
+                                value: [
+                                    new in_window.org.pkijs.asn1.CHOICE({
+                                        value: [
+                                            new in_window.org.pkijs.asn1.TELETEXSTRING(),
+                                            new in_window.org.pkijs.asn1.PRINTABLESTRING(),
+                                            new in_window.org.pkijs.asn1.UNIVERSALSTRING(),
+                                            new in_window.org.pkijs.asn1.UTF8STRING(),
+                                            new in_window.org.pkijs.asn1.BMPSTRING()
+                                        ]
+                                    })
+                                ]
+                            })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.block_name || ""),
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 6 // [6]
+                    }
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.block_name || ""),
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 7 // [7]
+                    }
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.block_name || ""),
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 8 // [8]
+                    }
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "AlgorithmIdentifier" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER =
+    function()
+    {
+        //AlgorithmIdentifier  ::=  SEQUENCE  {
+        //    algorithm               OBJECT IDENTIFIER,
+        //    parameters              ANY DEFINED BY algorithm OPTIONAL  }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            optional: (names.optional || false),
+            value: [
+                new in_window.org.pkijs.asn1.OID({ name: (names.algorithmIdentifier || "") }),
+                new in_window.org.pkijs.asn1.ANY({ name: (names.algorithmParams || ""), optional: true })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "RSAPublicKey" type (RFC3447)
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.RSAPublicKey =
+    function()
+    {
+        //RSAPublicKey ::= SEQUENCE {
+        //    modulus           INTEGER,  -- n
+        //    publicExponent    INTEGER   -- e
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.modulus || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.publicExponent || "") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "OtherPrimeInfo" type (RFC3447) 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.OtherPrimeInfo =
+    function()
+    {
+        //OtherPrimeInfo ::= SEQUENCE {
+        //    prime             INTEGER,  -- ri
+        //    exponent          INTEGER,  -- di
+        //    coefficient       INTEGER   -- ti
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.prime || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.exponent || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.coefficient || "") })
+    ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "RSAPrivateKey" type (RFC3447)
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.RSAPrivateKey =
+    function()
+    {
+        //RSAPrivateKey ::= SEQUENCE {
+        //    version           Version,
+        //    modulus           INTEGER,  -- n
+        //    publicExponent    INTEGER,  -- e
+        //    privateExponent   INTEGER,  -- d
+        //    prime1            INTEGER,  -- p
+        //    prime2            INTEGER,  -- q
+        //    exponent1         INTEGER,  -- d mod (p-1)
+        //    exponent2         INTEGER,  -- d mod (q-1)
+        //    coefficient       INTEGER,  -- (inverse of q) mod p
+        //    otherPrimeInfos   OtherPrimeInfos OPTIONAL
+        //}
+        //
+        //OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.version || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.modulus || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.publicExponent || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.privateExponent || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.prime1 || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.prime2 || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.exponent1 || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.exponent2 || "") }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.coefficient || "") }),
+                new in_window.org.pkijs.asn1.SEQUENCE({
+                    optional: true,
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            name: (names.otherPrimeInfos || ""),
+                            value: in_window.org.pkijs.schema.x509.OtherPrimeInfo(names.otherPrimeInfo || {})
+                        })
+                    ]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "RSASSA-PSS-params" type (RFC3447)
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.RSASSA_PSS_params =
+    function()
+    {
+        //RSASSA-PSS-params  ::=  SEQUENCE  {
+        //    hashAlgorithm      [0] HashAlgorithm DEFAULT sha1Identifier,
+        //    maskGenAlgorithm   [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
+        //    saltLength         [2] INTEGER DEFAULT 20,
+        //    trailerField       [3] INTEGER DEFAULT 1  }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    optional: true,
+                    value: [in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.hashAlgorithm || {})]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    },
+                    optional: true,
+                    value: [in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.maskGenAlgorithm || {})]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 2 // [2]
+                    },
+                    optional: true,
+                    value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.saltLength || "") })]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 3 // [3]
+                    },
+                    optional: true,
+                    value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.trailerField || "") })]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "SubjectPublicKeyInfo" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.PUBLIC_KEY_INFO =
+    function()
+    {
+        //SubjectPublicKeyInfo  ::=  SEQUENCE  {
+        //    algorithm            AlgorithmIdentifier,
+        //    subjectPublicKey     BIT STRING  }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.algorithm || {}),
+                new in_window.org.pkijs.asn1.BITSTRING({ name: (names.subjectPublicKey || "") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "Attribute" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.ATTRIBUTE =
+    function()
+    {
+        // Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
+        //    type   ATTRIBUTE.&id({IOSet}),
+        //    values SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{@type})
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.OID({ name: (names.type || "") }),
+                new in_window.org.pkijs.asn1.SET({
+                    name: (names.set_name || ""),
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            name: (names.values || ""),
+                            value: new in_window.org.pkijs.asn1.ANY()
+                        })
+                    ]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "AttributeTypeAndValue" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.ATTR_TYPE_AND_VALUE =
+    function()
+    {
+        //AttributeTypeAndValue ::= SEQUENCE {
+        //    type     AttributeType,
+        //    value    AttributeValue }
+        //
+        //AttributeType ::= OBJECT IDENTIFIER
+        //
+        //AttributeValue ::= ANY -- DEFINED BY AttributeType
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.OID({ name: (names.type || "") }),
+                new in_window.org.pkijs.asn1.ANY({ name: (names.value || "") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "RelativeDistinguishedName" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.RDN =
+    function()
+    {
+        //RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+        //
+        //RelativeDistinguishedName ::=
+        //SET SIZE (1..MAX) OF AttributeTypeAndValue
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.repeated_sequence || ""),
+                    value: new in_window.org.pkijs.asn1.SET({
+                        value: [
+                            new in_window.org.pkijs.asn1.REPEATED({
+                                name: (names.repeated_set || ""),
+                                value: in_window.org.pkijs.schema.ATTR_TYPE_AND_VALUE(names.attr_type_and_value || {})
+                            })
+                        ]
+                    })
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "Extension" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.EXTENSION =
+    function()
+    {
+        //Extension  ::=  SEQUENCE  {
+        //    extnID      OBJECT IDENTIFIER,
+        //    critical    BOOLEAN DEFAULT FALSE,
+        //    extnValue   OCTET STRING
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.OID({ name: (names.extnID || "") }),
+                new in_window.org.pkijs.asn1.BOOLEAN({
+                    name: (names.critical || ""),
+                    optional: true
+                }),
+                new in_window.org.pkijs.asn1.OCTETSTRING({ name: (names.extnValue || "") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "Extensions" type (sequence of many Extension)
+    //**************************************************************************************
+    in_window.org.pkijs.schema.EXTENSIONS =
+    function(input_names, input_optional)
+    {
+        //Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+        var optional = input_optional || false;
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            optional: optional,
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.extensions || ""),
+                    value: in_window.org.pkijs.schema.EXTENSION(names.extension || {})
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "AuthorityKeyIdentifier" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.AuthorityKeyIdentifier =
+    function()
+    {
+        // AuthorityKeyIdentifier OID ::= 2.5.29.35
+        // 
+        //AuthorityKeyIdentifier ::= SEQUENCE {
+        //    keyIdentifier             [0] KeyIdentifier           OPTIONAL,
+        //    authorityCertIssuer       [1] GeneralNames            OPTIONAL,
+        //    authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
+        //
+        //KeyIdentifier ::= OCTET STRING
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.keyIdentifier || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    }
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    },
+                    value: [
+                            new in_window.org.pkijs.asn1.REPEATED({
+                                name: (names.authorityCertIssuer || ""),
+                                value: in_window.org.pkijs.schema.GENERAL_NAME()
+                            })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.authorityCertSerialNumber || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 2 // [2]
+                    }
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "PrivateKeyUsagePeriod" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.PrivateKeyUsagePeriod =
+    function()
+    {
+        // PrivateKeyUsagePeriod OID ::= 2.5.29.16
+        //
+        //PrivateKeyUsagePeriod ::= SEQUENCE {
+        //    notBefore       [0]     GeneralizedTime OPTIONAL,
+        //    notAfter        [1]     GeneralizedTime OPTIONAL }
+        //-- either notBefore or notAfter MUST be present
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.notBefore || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    }
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.notAfter || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    }
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "IssuerAltName" and "SubjectAltName" types of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.AltName =
+    function()
+    {
+        // SubjectAltName OID ::= 2.5.29.17
+        // IssuerAltName OID ::= 2.5.29.18
+        //
+        // AltName ::= GeneralNames
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.altNames || ""),
+                    value: in_window.org.pkijs.schema.GENERAL_NAME()
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "SubjectDirectoryAttributes" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.SubjectDirectoryAttributes =
+    function()
+    {
+        // SubjectDirectoryAttributes OID ::= 2.5.29.9
+        //
+        //SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.attributes || ""),
+                    value: in_window.org.pkijs.schema.ATTRIBUTE()
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "GeneralSubtree" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.GeneralSubtree =
+    function()
+    {
+        //GeneralSubtree ::= SEQUENCE {
+        //    base                    GeneralName,
+        //    minimum         [0]     BaseDistance DEFAULT 0,
+        //    maximum         [1]     BaseDistance OPTIONAL }
+        //
+        //BaseDistance ::= INTEGER (0..MAX)
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                in_window.org.pkijs.schema.GENERAL_NAME(names.base || ""),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.minimum || "") })]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    },
+                    value: [new in_window.org.pkijs.asn1.INTEGER({ name: (names.maximum || "") })]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "NameConstraints" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.NameConstraints =
+    function()
+    {
+        // NameConstraints OID ::= 2.5.29.30
+        //
+        //NameConstraints ::= SEQUENCE {
+        //    permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
+        //    excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            name: (names.permittedSubtrees || ""),
+                            value: in_window.org.pkijs.schema.x509.GeneralSubtree()
+                        })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            name: (names.excludedSubtrees || ""),
+                            value: in_window.org.pkijs.schema.x509.GeneralSubtree()
+                        })
+                    ]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "BasicConstraints" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.BasicConstraints =
+    function()
+    {
+        // BasicConstraints OID ::= 2.5.29.19
+        //
+        //BasicConstraints ::= SEQUENCE {
+        //    cA                      BOOLEAN DEFAULT FALSE,
+        //    pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.BOOLEAN({
+                    optional: true,
+                    name: (names.cA || "")
+                }),
+                new in_window.org.pkijs.asn1.INTEGER({
+                    optional: true,
+                    name: (names.pathLenConstraint || "")
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "PolicyQualifierInfo" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.PolicyQualifierInfo =
+    function()
+    {
+        //PolicyQualifierInfo ::= SEQUENCE {
+        //    policyQualifierId  PolicyQualifierId,
+        //    qualifier          ANY DEFINED BY policyQualifierId }
+        //
+        //id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
+        //id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
+        //id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
+        //
+        //PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.OID({ name: (names.policyQualifierId || "") }),
+                new in_window.org.pkijs.asn1.ANY({ name: (names.qualifier || "") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "PolicyInformation" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.PolicyInformation =
+    function()
+    {
+        //PolicyInformation ::= SEQUENCE {
+        //    policyIdentifier   CertPolicyId,
+        //    policyQualifiers   SEQUENCE SIZE (1..MAX) OF
+        //    PolicyQualifierInfo OPTIONAL }
+        //
+        //CertPolicyId ::= OBJECT IDENTIFIER
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.OID({ name: (names.policyIdentifier || "") }),
+                new in_window.org.pkijs.asn1.SEQUENCE({
+                    optional: true,
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            name: (names.policyQualifiers || ""),
+                            value: in_window.org.pkijs.schema.x509.PolicyQualifierInfo()
+                        })
+                    ]
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "CertificatePolicies" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.CertificatePolicies =
+    function()
+    {
+        // CertificatePolicies OID ::= 2.5.29.32
+        //
+        //certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.certificatePolicies || ""),
+                    value: in_window.org.pkijs.schema.x509.PolicyInformation()
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "PolicyMapping" type
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.PolicyMapping =
+    function()
+    {
+        //PolicyMapping ::= SEQUENCE {
+        //    issuerDomainPolicy      CertPolicyId,
+        //    subjectDomainPolicy     CertPolicyId }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.OID({ name: (names.issuerDomainPolicy || "") }),
+                new in_window.org.pkijs.asn1.OID({ name: (names.subjectDomainPolicy || "") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "PolicyMappings" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.PolicyMappings =
+    function()
+    {
+        // PolicyMappings OID ::= 2.5.29.33
+        //
+        //PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF PolicyMapping
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.mappings || ""),
+                    value: in_window.org.pkijs.schema.x509.PolicyMapping()
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "PolicyConstraints" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.PolicyConstraints =
+    function()
+    {
+        // PolicyMappings OID ::= 2.5.29.36
+        //
+        //PolicyConstraints ::= SEQUENCE {
+        //    requireExplicitPolicy           [0] SkipCerts OPTIONAL,
+        //    inhibitPolicyMapping            [1] SkipCerts OPTIONAL }
+        //
+        //SkipCerts ::= INTEGER (0..MAX)
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.requireExplicitPolicy || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    }
+                }), // IMPLICIT integer value
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.inhibitPolicyMapping || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    }
+                }) // IMPLICIT integer value
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "ExtKeyUsage" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.ExtKeyUsage =
+    function()
+    {
+        // ExtKeyUsage OID ::= 2.5.29.37
+        //
+        // ExtKeyUsage ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
+
+        // KeyPurposeId ::= OBJECT IDENTIFIER
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.keyPurposes || ""),
+                    value: new in_window.org.pkijs.asn1.OID()
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "DistributionPoint" type
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.DistributionPoint =
+    function()
+    {
+        //DistributionPoint ::= SEQUENCE {
+        //    distributionPoint       [0]     DistributionPointName OPTIONAL,
+        //    reasons                 [1]     ReasonFlags OPTIONAL,
+        //    cRLIssuer               [2]     GeneralNames OPTIONAL }
+        //
+        //DistributionPointName ::= CHOICE {
+        //    fullName                [0]     GeneralNames,
+        //    nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
+        //
+        //ReasonFlags ::= BIT STRING {
+        //    unused                  (0),
+        //    keyCompromise           (1),
+        //    cACompromise            (2),
+        //    affiliationChanged      (3),
+        //    superseded              (4),
+        //    cessationOfOperation    (5),
+        //    certificateHold         (6),
+        //    privilegeWithdrawn      (7),
+        //    aACompromise            (8) }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.CHOICE({
+                            value: [
+                                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                                    name: (names.distributionPoint || ""),
+                                    optional: true,
+                                    id_block: {
+                                        tag_class: 3, // CONTEXT-SPECIFIC
+                                        tag_number: 0 // [0]
+                                    },
+                                    value: [
+                                        new in_window.org.pkijs.asn1.REPEATED({
+                                            name: (names.distributionPoint_names || ""),
+                                            value: in_window.org.pkijs.schema.GENERAL_NAME()
+                                        })
+                                    ]
+                                }),
+                                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                                    name: (names.distributionPoint || ""),
+                                    optional: true,
+                                    id_block: {
+                                        tag_class: 3, // CONTEXT-SPECIFIC
+                                        tag_number: 1 // [1]
+                                    },
+                                    value: in_window.org.pkijs.schema.RDN().value_block.value
+                                })
+                            ]
+                        })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.reasons || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    }
+                }), // IMPLICIT bitstring value
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    name: (names.cRLIssuer || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 2 // [2]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.REPEATED({
+                            name: (names.cRLIssuer_names || ""),
+                            value: in_window.org.pkijs.schema.GENERAL_NAME()
+                        })
+                    ]
+                }) // IMPLICIT bitstring value
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "CRLDistributionPoints" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.CRLDistributionPoints =
+    function()
+    {
+        // CRLDistributionPoints OID ::= 2.5.29.31
+        //
+        //CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.distributionPoints || ""),
+                    value: in_window.org.pkijs.schema.x509.DistributionPoint()
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "AccessDescription" type
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.AccessDescription =
+    function()
+    {
+        //AccessDescription  ::=  SEQUENCE {
+        //    accessMethod          OBJECT IDENTIFIER,
+        //    accessLocation        GeneralName  }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.OID({ name: (names.accessMethod || "") }),
+                in_window.org.pkijs.schema.GENERAL_NAME(names.accessLocation || "")
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "AuthorityInfoAccess" and "SubjectInfoAccess" types of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.InfoAccess =
+    function()
+    {
+        // AuthorityInfoAccess OID ::= 1.3.6.1.5.5.7.1.1
+        // SubjectInfoAccess OID ::= 1.3.6.1.5.5.7.1.11
+        //
+        //AuthorityInfoAccessSyntax  ::=
+        //SEQUENCE SIZE (1..MAX) OF AccessDescription
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.REPEATED({
+                    name: (names.accessDescriptions || ""),
+                    value: in_window.org.pkijs.schema.x509.AccessDescription()
+                })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "IssuingDistributionPoint" type of extension 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.x509.IssuingDistributionPoint =
+    function()
+    {
+        // IssuingDistributionPoint OID ::= 2.5.29.28
+        //
+        //IssuingDistributionPoint ::= SEQUENCE {
+        //    distributionPoint          [0] DistributionPointName OPTIONAL,
+        //    onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE,
+        //    onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE,
+        //    onlySomeReasons            [3] ReasonFlags OPTIONAL,
+        //    indirectCRL                [4] BOOLEAN DEFAULT FALSE,
+        //    onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+        //
+        //ReasonFlags ::= BIT STRING {
+        //    unused                  (0),
+        //    keyCompromise           (1),
+        //    cACompromise            (2),
+        //    affiliationChanged      (3),
+        //    superseded              (4),
+        //    cessationOfOperation    (5),
+        //    certificateHold         (6),
+        //    privilegeWithdrawn      (7),
+        //    aACompromise            (8) }
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || ""),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                    value: [
+                        new in_window.org.pkijs.asn1.CHOICE({
+                            value: [
+                                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                                    name: (names.distributionPoint || ""),
+                                    id_block: {
+                                        tag_class: 3, // CONTEXT-SPECIFIC
+                                        tag_number: 0 // [0]
+                                    },
+                                    value: [
+                                        new in_window.org.pkijs.asn1.REPEATED({
+                                            name: (names.distributionPoint_names || ""),
+                                            value: in_window.org.pkijs.schema.GENERAL_NAME()
+                                        })
+                                    ]
+                                }),
+                                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                                    name: (names.distributionPoint || ""),
+                                    id_block: {
+                                        tag_class: 3, // CONTEXT-SPECIFIC
+                                        tag_number: 1 // [1]
+                                    },
+                                    value: in_window.org.pkijs.schema.RDN().value_block.value
+                                })
+                            ]
+                        })
+                    ]
+                }),
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.onlyContainsUserCerts || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 1 // [1]
+                    }
+                }), // IMPLICIT boolean value
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.onlyContainsCACerts || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 2 // [2]
+                    }
+                }), // IMPLICIT boolean value
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.onlySomeReasons || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 3 // [3]
+                    }
+                }), // IMPLICIT bitstring value
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.indirectCRL || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 4 // [4]
+                    }
+                }), // IMPLICIT boolean value
+                new in_window.org.pkijs.asn1.ASN1_PRIMITIVE({
+                    name: (names.onlyContainsAttributeCerts || ""),
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 5 // [5]
+                    }
+                }) // IMPLICIT boolean value
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+}
+)(typeof exports !== "undefined" ? exports : window);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/x509_simpl.js
@@ -0,0 +1,7239 @@
+/*
+ * Copyright (c) 2014, GMO GlobalSign
+ * Copyright (c) 2015, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software without 
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE. 
+ *
+ */
+(
+function(in_window)
+{
+    //**************************************************************************************
+    // #region Declaration of global variables 
+    //**************************************************************************************
+    // #region "org" namespace 
+    if(typeof in_window.org === "undefined")
+        in_window.org = {};
+    else
+    {
+        if(typeof in_window.org !== "object")
+            throw new Error("Name org already exists and it's not an object");
+    }
+    // #endregion 
+
+    // #region "org.pkijs" namespace 
+    if(typeof in_window.org.pkijs === "undefined")
+        in_window.org.pkijs = {};
+    else
+    {
+        if(typeof in_window.org.pkijs !== "object")
+            throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs));
+    }
+    // #endregion 
+
+    // #region "org.pkijs.simpl" namespace 
+    if(typeof in_window.org.pkijs.simpl === "undefined")
+        in_window.org.pkijs.simpl = {};
+    else
+    {
+        if(typeof in_window.org.pkijs.simpl !== "object")
+            throw new Error("Name org.pkijs.simpl already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl));
+    }
+    // #endregion 
+
+    // #region "org.pkijs.simpl.x509" namespace 
+    if(typeof in_window.org.pkijs.simpl.x509 === "undefined")
+        in_window.org.pkijs.simpl.x509 = {};
+    else
+    {
+        if(typeof in_window.org.pkijs.simpl.x509 !== "object")
+            throw new Error("Name org.pkijs.simpl.x509 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.simpl.x509));
+    }
+    // #endregion 
+
+    // #region "local" namespace 
+    var local = {};
+    // #endregion   
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Simplified structure for "Time" type
+    //**************************************************************************************
+    in_window.org.pkijs.simpl.TIME =
+    function()
+    {
+        // #region Internal properties of the object 
+        this.type = 0; // 0 - UTCTime; 1 - GeneralizedTime; 2 - empty value
+        this.value = new Date(0, 0, 0);
+        // #endregion 
+
+        // #region If input argument array contains "schema" for this object 
+        if((arguments[0] instanceof Object) && ("schema" in arguments[0]))
+            in_window.org.pkijs.simpl.TIME.prototype.fromSchema.call(this, arguments[0].schema);
+        // #endregion 
+        // #region If input argument array contains "native" values for internal properties 
+        else
+        {
+            if(arguments[0] instanceof Object)
+            {
+                this.type = (arguments[0].type || 0);
+                this.value = (arguments[0].value || (new Date(0, 0, 0)));
+            }
+        }
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.simpl.TIME.prototype.fromSchema =
+    function(schema)
+    {
+        // #region Check the schema is valid 
+        var asn1 = in_window.org.pkijs.compareSchema(schema,
+            schema,
+            in_window.org.pkijs.schema.TIME({
+                names: {
+                    utcTimeName: "utcTimeName",
+                    generalTimeName: "generalTimeName"
+                }
+            })
+            );
+
+        if(asn1.verified === false)
+            throw new Error("Object's schema was not verified against input data for TIME");
+        // #endregion 
+
+        // #region Get internal properties from parsed schema 
+        if("utcTimeName" in asn1.result)
+        {
+            this.type = 0;
+            this.value = asn1.result.utcTimeName.toDate();
+        }
+        if("generalTimeName" in asn1.result)
+        {
+            this.type = 1;
+            this.value = asn1.result.generalTimeName.toDate();
+        }
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.simpl.TIME.prototype.toSchema =
+    function()
+    {
+        // #region Construct and return new ASN.1 schema for this object 
+        var result = {};
+
+        if(this.type === 0)
+            result = new in_window.org.pkijs.asn1.UTCTIME({ value_date: this.value });
+        if(this.type === 1)
+            result = new in_window.org.pkijs.asn1.GENERALIZEDTIME({ value_date: this.value });
+
+        return result;
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.simpl.TIME.prototype.toJSON =
+    function()
+    {
+        return {
+            type: this.type,
+            value: this.value
+        };
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Simplified structure for "GeneralName" type 
+    //**************************************************************************************
+    in_window.org.pkijs.simpl.GENERAL_NAME =
+    function()
+    {
+        // #region Internal properties of the object 
+        this.NameType = 9; // Name type - from a