diff --git a/.github/workflows/jekyll.yml b/.github/workflows/jekyll.yml new file mode 100644 index 0000000..d226cc3 --- /dev/null +++ b/.github/workflows/jekyll.yml @@ -0,0 +1,63 @@ +# Sample workflow for building and deploying a Jekyll site to GitHub Pages +name: Deploy Jekyll with GitHub Pages dependencies preinstalled + +on: + # Runs on pushes targeting the default branch + push: + branches: ["gh-pages"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: "./docs" + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + working-directory: "./docs" + ruby-version: "3.3" + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + cache-version: 0 # Increment this number if you need to re-download cached gems + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Build with Jekyll + # Outputs to the './_site' directory by default + run: bundle exec jekyll build --baseurl "/tech_shield" + env: + JEKYLL_ENV: production + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: "./docs/_site/" + + # Deployment job + deploy: + environment: + name: github-pages + url: "./docs/_site" + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/tttttt.yml b/.github/workflows/tttttt.yml new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/.github/workflows/tttttt.yml @@ -0,0 +1 @@ + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..71f1855 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib"] + path = docs/assets/lib + url = https://github.com/cotes2020/chirpy-static-assets.git diff --git a/docs/.editorconfig b/docs/.editorconfig new file mode 100644 index 0000000..2b740bf --- /dev/null +++ b/docs/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +# Unix-style newlines with a newline ending every file +end_of_line = lf +insert_final_newline = true + +[*.{js,css,scss}] +quote_type = single + +[*.{yml,yaml}] +quote_type = double + +[*.md] +trim_trailing_whitespace = false diff --git a/docs/.gitattributes b/docs/.gitattributes new file mode 100644 index 0000000..262d6bd --- /dev/null +++ b/docs/.gitattributes @@ -0,0 +1,16 @@ +# Set default behavior to automatically normalize line endings. +* text=auto + +# Force bash scripts to always use LF line endings so that if a repo is accessed +# in Unix via a file share from Windows, the scripts will work. +*.sh text eol=lf + +# Force batch scripts to always use CRLF line endings so that if a repo is accessed +# in Windows via a file share from Linux, the scripts will work. +*.{cmd,[cC][mM][dD]} text eol=crlf +*.{bat,[bB][aA][tT]} text eol=crlf + +# Denote all files that are truly binary and should not be modified. +*.png binary +*.jpg binary +*.ico binary diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..f40fbd8 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,5 @@ +_site +.sass-cache +.jekyll-cache +.jekyll-metadata +vendor diff --git a/docs/.gitlab-ci.yml b/docs/.gitlab-ci.yml new file mode 100644 index 0000000..7167efd --- /dev/null +++ b/docs/.gitlab-ci.yml @@ -0,0 +1,26 @@ +image: ruby:2.3 + +variables: + JEKYLL_ENV: production + +test: + stage: test + script: + - sh ./var/build.sh + - bundle exec jekyll build -d test + artifacts: + paths: + - test + except: + - master + +pages: + stage: deploy + script: + - sh ./var/build.sh + - bundle exec jekyll build -d public + artifacts: + paths: + - public + only: + - master diff --git a/docs/.gitmodules b/docs/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 0000000..3ec73b3 --- /dev/null +++ b/docs/404.html @@ -0,0 +1,24 @@ +--- +layout: home +--- + + + +
Page not found :(
+The requested page could not be found.
+
+
+Welcome to Techshield's official GitHub page! We're a team committed to delivering innovative solutions and high-quality products. Here's a bit about each of our team members:
+
+Our Team
+Jannis - Developer
+Jannis specializes in backend development with a sharp eye for detail. He is dedicated to optimizing and improving our systems through his coding expertise.
+
+Markus - Developer
+Markus brings versatility to the team with his proficiency in both frontend and backend technologies. His problem-solving skills and efficient solutions are vital to our projects.
+
+Sebastian - Developer
+Sebastian offers extensive experience in software architecture and design. His focus on clean, maintainable code ensures our projects are built on a solid foundation.
+
+Aghyad - Scrum Master
+As the Scrum Master, Aghyad ensures our projects run smoothly and efficiently. He facilitates communication and collaboration within the team to keep us on track.
+
+Felix - Product Owner
+Felix is responsible for defining the vision and strategy for our products. He works closely with the team to ensure we deliver value to our customers.
+
+Thank you for visiting Techshield's GitHub page. We're excited to share our projects and innovations with you.
diff --git a/docs/_config.yml b/docs/_config.yml
new file mode 100644
index 0000000..6ef7ab3
--- /dev/null
+++ b/docs/_config.yml
@@ -0,0 +1,66 @@
+# Configurations
+title: Documentation
+longtitle: Our Documentation Site
+author: Aghyad
+email: Aghyad
+description: >
+ This is Our Documentation.
+
+version: 1.0
+gitbook_version: 3.2.3
+
+url: 'https://cep-sose2024.github.io/tech_shield'
+baseurl: '/tech_shield'
+rss: RSS
+
+# bootstrap: use the remote theme for the site itself
+remote_theme: sighingnow/jekyll-gitbook
+
+toc:
+ enabled: true
+ h_min: 1
+ h_max: 3
+
+# customize the link favicon in header, will be {{site.baseurl}}/{{site.favicon_path}}
+favicon_path: "https://i.pinimg.com/originals/eb/68/2a/eb682acad8f78afb9b0060455d409c2f.jpg"
+
+# markdown render engine.
+markdown: kramdown
+kramdown:
+ auto_ids: true
+ input: GFM
+ math_engine: mathjax
+ smart_quotes: lsquo,rsquo,ldquo,rdquo
+ toc_levels: 1..6
+ syntax_highlighter: rouge
+ syntax_highlighter_opts:
+ guess_lang: true
+
+syntax_highlighter_style: colorful
+
+markdown_ext: markdown,mkdown,mkdn,mkd,md
+
+# Permalinks
+permalink: /:categories/:year-:month-:day-:title:output_ext
+
+# Disqus comments
+# disqushandler: sighingnow
+
+exclude:
+ - _drafts
+
+collections:
+ pages:
+ output: true
+ permalink: /:collection/:path/
+
+page_width: 800px
+
+destination: ./_site
+incremental: false
+regenerate: true
+
+plugins:
+ - jekyll-feed
+ - jekyll-readme-index
+ - jemoji
diff --git a/docs/_includes/application-insights.html b/docs/_includes/application-insights.html
new file mode 100644
index 0000000..93b1d6b
--- /dev/null
+++ b/docs/_includes/application-insights.html
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/docs/_includes/body.html b/docs/_includes/body.html
new file mode 100644
index 0000000..cd79e9c
--- /dev/null
+++ b/docs/_includes/body.html
@@ -0,0 +1,43 @@
+
+
+Jannis - Developer
+Jannis specializes in backend development with a sharp eye for detail. He is dedicated to optimizing and improving our systems through his coding expertise.
+
+Markus - Developer
+Markus brings versatility to the team with his proficiency in both frontend and backend technologies. His problem-solving skills and efficient solutions are vital to our projects.
+
+Sebastian - Developer
+Sebastian offers extensive experience in software architecture and design. His focus on clean, maintainable code ensures our projects are built on a solid foundation.
+
+Aghyad - Scrum Master
+As the Scrum Master, Aghyad ensures our projects run smoothly and efficiently. He facilitates communication and collaboration within the team to keep us on track.
+
+Felix - Product Owner
+Felix is responsible for defining the vision and strategy for our products. He works closely with the team to ensure we deliver value to our customers.
+
+Thank you for visiting Techshield's GitHub page. We're excited to share our projects and innovations with you.
diff --git a/docs/_pages/categories.md b/docs/_pages/categories.md
new file mode 100644
index 0000000..cdd3222
--- /dev/null
+++ b/docs/_pages/categories.md
@@ -0,0 +1,831 @@
+---
+title: Categories
+author: Aghyad Jabali
+date: 2024-06-14
+category: Jekyll
+layout: post
+---
+
+
+## J&S-Soft Overview
+J&S-Soft GmbH, based in Heidelberg, is an international consulting and software development company specializing in technologies such as SAP HANA, SAP Business Technology Platform (BTP), S/4HANA, as well as SAP UI5 and SAP Fiori. In addition to these services, J&S-Soft GmbH develops its own software solutions, including the open-source framework enmeshed. This framework enables simple, intelligent, and secure GDPR-compliant data transfers, even extending to private users.
+
+Since its founding, the company has established numerous partnerships, leading to continuous revenue growth. Notably, in 2023, J&S-Soft GmbH generated 40% of its revenue from products related to the enmeshed framework. Continued strong revenue growth is expected for 2024. To maintain this success, the further development of the enmeshed framework is of great importance.
+
+
+# CEP SoSe24 Project Overview
+
+## Objectives
+
+With the planned project "CEP SoSe24," J&S-Soft GmbH aims to achieve the following objectives:
+
+1. **Significant Advancement of the Enmeshed Framework**
+ - Enhance and expand the existing capabilities of the enmeshed framework to support more robust and scalable applications.
+
+2. **Secure Generation and Management of Multiple Keys for Various Cryptographic Applications**
+ - Develop and implement mechanisms to securely generate and manage numerous keys essential for different cryptographic procedures.
+
+3. **Increase Compatibility through the Integration of Various Hardware Security Modules**
+ - Improve the compatibility of the enmeshed framework by integrating different hardware security modules (HSMs) to enhance security and performance.
+
+4. **Evaluation of Previous Developments and Incorporation of New Ideas into the Enmeshed Framework**
+ - Assess the current developments and integrate new concepts and innovations to continuously improve the enmeshed framework.
+
+## Project-Specific Conditions
+
+The following chapters describe the conditions specific to the project.
+
+### Organizational Conditions
+
+The development team at J&S-Soft GmbH employs various encryption methods within the enmeshed framework for secure communication and data exchange. In this context, a multitude of keys is generated and managed. A significant challenge is to generate these keys securely and protect them from unauthorized access. To adequately address this risk, the process will be secured using different Hardware Security Modules (HSMs) in the future.
+
+## Project Work Packages
+
+The project is divided into three work packages:
+
+### AP-1: Conceptualization of Secure Key Management Using Hardware Security Modules
+
+Develop a comprehensive concept for secure key management utilizing HSMs to enhance security and efficiency.
+
+### AP-2: Implementation Based on the Developed Concept
+
+Execute the implementation of the secure key management system according to the conceptual framework established in AP-1.
+
+### AP-3: Creation of a Risk Assessment for the Developed Implementation
+
+Conduct a thorough risk assessment of the implemented key management system to identify potential vulnerabilities and ensure robust security measures are in place.
+
+
+
+## Crypto Layer
+
+The Crypto Layer is a comprehensive and flexible cryptographic library designed to provide a unified interface for various cryptographic operations and algorithms. It offers a wide range of functionalities, including encryption, decryption, signing, signature verification, and hashing, while supporting both symmetric and asymmetric cryptography.
+
+## Features
+
+- **Encryption Algorithms**: Supports a variety of encryption algorithms, including:
+
+ - Asymmetric Encryption: RSA, ECC (Elliptic Curve Cryptography) with various curve types (P-256, P-384, P-521, secp256k1, Brainpool curves, Curve25519, Curve448, FRP256v1)
+ - Symmetric Block Ciphers: AES (with multiple modes like GCM, CCM, ECB, CBC, CFB, OFB, CTR), Triple DES (two-key and three-key configurations), DES, RC2, Camellia
+ - Stream Ciphers: RC4, ChaCha20
+
+- **Hashing Algorithms**: Supports a wide range of hashing algorithms, including:
+
+ - SHA-1, SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256)
+ - SHA-3 (SHA3-224, SHA3-256, SHA3-384, SHA3-512)
+ - MD2, MD4, MD5, RIPEMD-160
+
+- **Key Management**: Provides a unified interface for creating, loading, and managing cryptographic keys, supporting various key usages and algorithms.
+
+- **Cross-Platform Support**: Designed to work seamlessly across multiple platforms, including Linux and Windows, with platform-specific implementations for key handling and security module integration.
+
+- **Security Module Integration**: Integrates with Hardware Security Modules (HSMs) and Trusted Platform Modules (TPMs) for secure key storage and cryptographic operations, ensuring enhanced security and compliance with industry standards.
+
+- **Extensibility**: The modular design of the Crypto Layer allows for easy extension and integration of additional cryptographic algorithms and security modules in the future.
+
+## Usage
+
+The Crypto Layer provides a comprehensive set of interfaces and enums for working with cryptographic operations and algorithms. Here's a brief overview of the main components:
+
+### Encryption Algorithms
+
+The `encryption` module defines enums for various encryption algorithms, including:
+
+- `AsymmetricEncryption`: Represents asymmetric encryption algorithms like RSA and ECC.
+- `BlockCiphers`: Represents symmetric block cipher algorithms like AES, Triple DES, DES, RC2, and Camellia.
+- `StreamCiphers`: Represents stream cipher algorithms like RC4 and ChaCha20.
+
+### Hashing Algorithms
+
+The `hashes` module defines the `Hash` enum, which represents various hashing algorithms like SHA-1, SHA-2, SHA-3, MD2, MD4, MD5, and RIPEMD-160.
+
+### Key Management
+
+The `key_handle` module provides the `KeyHandle` trait, which defines a common interface for cryptographic key operations like signing, decryption, encryption, and signature verification. The `GenericKeyHandle` enum represents a platform-agnostic key handle that can be used on both Linux and Windows platforms.
+
+### Security Module Integration
+
+The `module_provider` module defines the `Provider` trait, which encapsulates operations related to cryptographic processing and key management. This trait is designed to be implemented by security modules, ensuring a unified approach to interacting with different types of security modules.
+
+The `factory` module provides the `SecModules` struct, which serves as a namespace for managing and accessing security module instances. It includes methods for retrieving or creating instances of security modules based on their type (HSM or TPM).
+
+### Error Handling
+
+The `error` module defines the `SecurityModuleError` enum, which represents various types of errors that can occur within a security module, including errors originating from HSMs, TPMs, or during cryptographic operations like signing, decryption, encryption, and signature verification.
+
+### Usage Examples
+
+Here are some usage examples based on the Windows TPM handler implementation:
+
+#### Creating a TPM Provider
+
+```rust
+use crypto_layer::factory::{SecModules, SecurityModule};
+use crypto_layer::tpm::core::instance::TpmType;
+
+let key_id = "my_key_id".to_string();
+let tpm_provider = SecModules::get_instances(key_id, SecurityModule::Tpm(TpmType::default()))
+ .expect("Failed to create TPM provider");
+```
+
+#### Initializing the TPM Module
+
+```rust
+use crypto_layer::common::error::SecurityModuleError;
+
+match tpm_provider.lock().unwrap().initialize_module() {
+ Ok(()) => println!("TPM module initialized successfully"),
+ Err(e) => println!("Failed to initialize TPM module: {:?}", e),
+}
+```
+
+#### Creating a Key
+
+```rust
+use crypto_layer::common::crypto::algorithms::{
+ encryption::{AsymmetricEncryption, BlockCiphers},
+ hashes::Hash,
+};
+use crypto_layer::common::KeyUsage;
+
+let key_algorithm = AsymmetricEncryption::Ecc(EccSchemeAlgorithm::EcDsa(EccCurves::P256));
+let sym_algorithm = Some(BlockCiphers::Aes(SymmetricMode::Cbc, KeyBits::Bits256));
+let hash = Some(Hash::Sha2(Sha2Bits::Sha256));
+let key_usages = vec![KeyUsage::SignEncrypt, KeyUsage::Decrypt];
+
+match tpm_provider.lock().unwrap().create_key(
+ "my_key_id",
+ key_algorithm,
+ sym_algorithm,
+ hash,
+ key_usages,
+) {
+ Ok(()) => println!("Key created successfully"),
+ Err(e) => println!("Failed to create key: {:?}", e),
+}
+```
+
+#### Signing Data
+
+```rust
+let data = b"Hello, world!";
+
+match tpm_provider.lock().unwrap().sign_data(data) {
+ Ok(signature) => println!("Signature: {:?}", signature),
+ Err(e) => println!("Failed to sign data: {:?}", e),
+}
+```
+
+#### Verifying Signature
+
+```rust
+let data = b"Hello, world!";
+let signature = // ... obtained signature ...
+
+match tpm_provider.lock().unwrap().verify_signature(data, &signature) {
+ Ok(valid) => {
+ if valid {
+ println!("Signature is valid");
+ } else {
+ println!("Signature is invalid");
+ }
+ }
+ Err(e) => println!("Failed to verify signature: {:?}", e),
+}
+```
+
+These examples demonstrate how to use the Windows TPM handler implementation to perform various cryptographic operations using the Crypto Layer.
+
+## Installation
+
+The Crypto Layer is distributed as a Rust crate and can be included in your project by adding the following line to your `Cargo.toml` file:
+
+```toml
+[dependencies]
+crypto-layer = "0.1.0"
+```
+
+## Contributing
+
+Contributions to the Crypto Layer are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on the project's GitHub repository.
+
+## License
+
+The Crypto Layer is released under the [MIT License](LICENSE).
+
+
+# YubiKey Provider Documentation
+
+
+## Overview
+
+This module provides cryptographic operations using a YubiKey. It implements the `Provider` trait and interacts with the YubiKey device for key management and cryptographic operations.
+
+## Table of Contents
+
+1. [Dependencies](#dependencies)
+2. [Constants](#constants)
+3. [Provider Implementation](#provider-implementation)
+ - [create_key](#create_key)
+ - [load_key](#load_key)
+ - [initialize_module](#initialize_module)
+4. [Helper Functions](#helper-functions)
+ - [save_key_object](#save_key_object)
+ - [parse_slot_data](#parse_slot_data)
+ - [get_free_slot](#get_free_slot)
+ - [get_reference_u32slot](#get_reference_u32slot)
+ - [list_all_slots](#list_all_slots)
+5. [License](#license)
+
+# Cryptographic Operations Test Documentation
+
+This document provides a comprehensive overview of the test cases designed for cryptographic operations within the system. These tests focus on signing, verifying, encrypting, and decrypting data using RSA and ECC keys. The goal is to ensure the integrity and reliability of these operations, which are critical for the security of the system's data and communications.
+
+## Overview
+
+The purpose of this module is to thoroughly test cryptographic operations, specifically focusing on:
+- Signing and verifying data with RSA and ECC keys.
+- Encrypting and decrypting data using RSA keys.
+
+## Test Cases
+
+### Signing and Verifying Data
+
+1. **`test_sign_and_verify_rsa_1024`**
+ - **Description**: Tests signing and verifying data using a 1024-bit RSA key.
+ - **Steps**:
+ 1. Initialize `YubiKeyProvider` with key ID and configuration.
+ 2. Initialize the HSM module on the YubiKey device.
+ 3. Create a 1024-bit RSA key pair.
+ 4. Sign predefined data.
+ 5. Verify the signature of the signed data.
+
+2. **`test_sign_and_verify_rsa_2048`**
+ - **Description**: Tests signing and verifying data using a 2048-bit RSA key.
+ - **Steps**: Follow the same steps as `test_sign_and_verify_rsa_1024`, but with a 2048-bit key configuration.
+
+3. **`test_sign_and_verify_ecc_256`**
+ - **Description**: Tests signing and verifying data using a 256-bit ECC key.
+ - **Steps**: Follow the same steps as `test_sign_and_verify_rsa_1024`, but with a 256-bit ECC key configuration.
+
+4. **`test_sign_and_verify_ecc_384`**
+ - **Description**: Tests signing and verifying data using a 384-bit ECC key.
+ - **Steps**: Follow the same steps as `test_sign_and_verify_rsa_1024`, but with a 384-bit ECC key configuration.
+
+### Encrypting and Decrypting Data
+
+1. **`test_encrypt_and_decrypt_rsa_1024`**
+ - **Description**: Tests encrypting and decrypting data using a 1024-bit RSA key.
+ - **Steps**:
+ 1. Initialize `YubiKeyProvider` with key ID and configuration.
+ 2. Initialize the HSM module on the YubiKey device.
+ 3. Create a 1024-bit RSA key pair.
+ 4. Encrypt predefined data.
+ 5. Decrypt the encrypted data and verify it matches the original data.
+
+2. **`test_encrypt_and_decrypt_rsa_2048`**
+ - **Description**: Tests encrypting and decrypting data using a 2048-bit RSA key.
+ - **Steps**: Follow the same steps as `test_encrypt_and_decrypt_rsa_1024`, but with a 2048-bit key configuration.
+
+## Test Procedures
+
+Each test case follows these general steps:
+1. **Initialization**: Set up the `YubiKeyProvider` with necessary parameters.
+2. **Module Initialization**: Initialize the HSM module on the YubiKey device.
+3. **Key Creation**: Generate a key pair according to the test requirements.
+4. **Operation**: Perform the cryptographic operation (sign, verify, encrypt, decrypt).
+5. **Verification**: Ensure the operation's outcome matches the expected result.
+
+## Test Parameters
+
+- **RSA Keys**: Tests cover 1024-bit and 2048-bit key sizes.
+- **ECC Keys**: Tests cover 256-bit and 384-bit key sizes.
+
+## Test Assumptions
+
+- A YubiKey device is connected and configured correctly.
+- The device is accessible via the system's USB interface.
+
+## Expected Behavior
+
+- Successful key creation, signing, verification, encryption, and decryption without errors.
+- Failures in these operations are considered test failures and should be reported.
+
+
+## Dependencies
+
+```rust
+use super::YubiKeyProvider;
+use crate::common::{
+ crypto::algorithms::{
+ encryption::{AsymmetricEncryption, EccCurves, EccSchemeAlgorithm},
+ KeyBits,
+ },
+ error::SecurityModuleError,
+ traits::module_provider::Provider,
+};
+use crate::hsm::{core::error::HsmError, HsmProviderConfig};
+use ::yubikey::{
+ piv::{self, AlgorithmId, RetiredSlotId, SlotId},
+ Error, YubiKey,
+};
+use base64::{engine::general_purpose, Engine};
+use std::any::Any;
+use std::sync::{Arc, Mutex};
+use tracing::instrument;
+use x509_cert::der::En ;
+use yubikey::MgmKey;
+Constants
+SLOTS
+rust
+
+const SLOTS: [RetiredSlotId; 20] = [
+ RetiredSlotId::R1,
+ RetiredSlotId::R2,
+ // ... remaining slots
+ RetiredSlotId::R20,
+];
+SLOTSU32
+rust
+
+const SLOTSU32: [u32; 20] = [
+ 0x005f_c10d,
+ // ... remaining slots
+ 0x005f_c120,
+];
+
+Provider Implementation
+create_key
+Creates a new cryptographic key identified by the provider-given key_id.#Example
+Below is an example of how to use the YubiKeyProvider to sign data.
+use super::YubiKeyProvider;
+use crate::{
+ common::{
+ crypto::algorithms::{
+ encryption::{AsymmetricEncryption, EccCurves, EccSchemeAlgorithm},
+ KeyBits,
+ },
+ error::SecurityModuleError,
+ traits::key_handle::KeyHandle,
+ },
+ hsm::core::error::HsmError,
+};
+use yubikey::{piv, AlgorithmId, SlotId, MgmKey};
+use base64::{engine::general_purpose, Engine};
+use openssl::{ec::EcKey, hash::MessageDigest, pkey::PKey, rsa::{Padding, Rsa}, sign::Verifier};
+use rsa::sha2::Digest;
+use sha2::Sha256;
+use tracing::instrument;
+use x509_cert::der::zeroize::Zeroizing;
+
+const BYTES_1024: usize = 128;
+const BYTES_2048: usize = 256;
+
+/// Provides cryptographic operations for asymmetric keys on a YubiKey.
+pub struct YubiKeyProvider {
+ yubikey: Option').html(content);
+
+ $link.appendTo($title);
+ $title.appendTo($li);
+ $content.appendTo($li);
+ $li.appendTo($searchList);
+ });
+ $('.body-inner').scrollTop(0);
+ }
+
+ function escapeReg(keyword) {
+ //escape regexp prevserve word
+ return String(keyword).replace(/([\*\.\?\+\$\^\[\]\(\)\{\}\|\/\\])/g, '\\$1');
+ }
+
+ function query(keyword) {
+ if (keyword == null || keyword.trim() === '') return;
+
+ var results = [],
+ index = -1;
+ for (var page in INDEX_DATA) {
+ if ((index = INDEX_DATA[page].body.toLowerCase().indexOf(keyword.toLowerCase())) !== -1) {
+ results.push({
+ url: page,
+ title: INDEX_DATA[page].title,
+ body: INDEX_DATA[page].body.substr(Math.max(0, index - 50), MAX_DESCRIPTION_SIZE).replace(new RegExp('(' + escapeReg(keyword) + ')', 'gi'), '$1')
+ });
+ }
+ }
+ displayResults({
+ count: results.length,
+ query: keyword,
+ results: results
+ });
+ }
+
+ function launchSearch(keyword) {
+ // Add class for loading
+ $body.addClass('with-search');
+ $body.addClass('search-loading');
+
+ function doSearch() {
+ query(keyword);
+ $body.removeClass('search-loading');
+ }
+
+ throttle(doSearch)();
+ }
+
+ function closeSearch() {
+ $body.removeClass('with-search');
+ $('#book-search-results').removeClass('open');
+ }
+
+ function bindSearch(target) {
+ // Asynchronously load the index data
+ {
+ var url = state.basePath + "/assets/search_plus_index.json";
+ $.getJSON(url).then(function(data) {
+ INDEX_DATA = data;
+ handleUpdate();
+ });
+ }
+
+ // Bind DOM
+ var $body = $('body');
+
+ // Launch query based on input content
+ function handleUpdate() {
+ var $searchInput = $(target);
+ var keyword = $searchInput.val();
+
+ if (keyword === undefined || keyword.length == 0) {
+ closeSearch();
+ } else {
+ launchSearch(keyword);
+ }
+ }
+
+ $body.on('keyup', target, function(e) {
+ if (e.keyCode === 13) {
+ if (usePushState) {
+ var uri = updateQueryString('q', $(this).val());
+ history.pushState({
+ path: uri
+ }, null, uri);
+ }
+ }
+ handleUpdate();
+ });
+
+ $body.on('click', target, function(e) {
+ if (Object.keys(INDEX_DATA).length === 0) {
+ var url = state.basePath + "/assets/search_plus_index.json";
+ $.getJSON(url).then(function(data) {
+ INDEX_DATA = data;
+ handleUpdate();
+ });
+ }
+ });
+
+ // Push to history on blur
+ $body.on('blur', target, function(e) {
+ // Update history state
+ if (usePushState) {
+ var uri = updateQueryString('q', $(this).val());
+ history.pushState({
+ path: uri
+ }, null, uri);
+ }
+ });
+ }
+
+ gitbook.events.on('start', function() {
+ bindSearch('#book-search-input input');
+ bindSearch('#book-search-input-inside input');
+
+ showResult();
+ closeSearch();
+ });
+
+ // ้ซไบฎๆๆฌ
+ var highLightPageInner = function(keyword) {
+ $('.page-inner').mark(keyword, {
+ 'ignoreJoiners': true,
+ 'acrossElements': true,
+ 'separateWordSearch': false
+ });
+
+ setTimeout(function() {
+ var mark = $('mark[data-markjs="true"]');
+ if (mark.length) {
+ mark[0].scrollIntoView();
+ }
+ }, 100);
+ };
+
+ function showResult() {
+ var keyword, type;
+ if (/\b(q|h)=([^&]+)/.test(location.search)) {
+ type = RegExp.$1;
+ keyword = decodeURIComponent(RegExp.$2);
+ if (type === 'q') {
+ launchSearch(keyword);
+ } else {
+ highLightPageInner(keyword);
+ }
+ $('#book-search-input input').val(keyword);
+ $('#book-search-input-inside input').val(keyword);
+ }
+ }
+
+ gitbook.events.on('page.change', showResult);
+
+ function getParameterByName(name) {
+ var url = window.location.href;
+ name = name.replace(/[\[\]]/g, '\\$&');
+ var regex = new RegExp('[?&]' + name + '(=([^]*)|&|#|$)', 'i'),
+ results = regex.exec(url);
+ if (!results) return null;
+ if (!results[2]) return '';
+ return decodeURIComponent(results[2].replace(/\+/g, ' '));
+ }
+
+ function updateQueryString(key, value) {
+ value = encodeURIComponent(value);
+
+ var url = window.location.href.replace(/([?&])(?:q|h)=([^&]+)(&|$)/, function(all, pre, value, end) {
+ if (end === '&') {
+ return pre;
+ }
+ return '';
+ });
+ var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'),
+ hash;
+
+ if (re.test(url)) {
+ if (typeof value !== 'undefined' && value !== null)
+ return url.replace(re, '$1' + key + '=' + value + '$2$3');
+ else {
+ hash = url.split('#');
+ url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
+ if (typeof hash[1] !== 'undefined' && hash[1] !== null)
+ url += '#' + hash[1];
+ return url;
+ }
+ } else {
+ if (typeof value !== 'undefined' && value !== null) {
+ var separator = url.indexOf('?') !== -1 ? '&' : '?';
+ hash = url.split('#');
+ url = hash[0] + separator + key + '=' + value;
+ if (typeof hash[1] !== 'undefined' && hash[1] !== null)
+ url += '#' + hash[1];
+ return url;
+ } else
+ return url;
+ }
+ }
+ window.addEventListener('click', function(e) {
+ if (e.target.tagName === 'A' && e.target.getAttribute('data-need-reload')) {
+ setTimeout(function() {
+ location.reload();
+ }, 100);
+ }
+ }, true);
+});
\ No newline at end of file
diff --git a/docs/assets/gitbook/gitbook-plugin-search/lunr.min.js b/docs/assets/gitbook/gitbook-plugin-search/lunr.min.js
new file mode 100644
index 0000000..6aa6bc7
--- /dev/null
+++ b/docs/assets/gitbook/gitbook-plugin-search/lunr.min.js
@@ -0,0 +1,7 @@
+/**
+ * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 0.5.12
+ * Copyright (C) 2015 Oliver Nightingale
+ * MIT Licensed
+ * @license
+ */
+!function(){var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.5.12",t.utils={},t.utils.warn=function(t){return function(e){t.console&&console.warn&&console.warn(e)}}(this),t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var t=Array.prototype.slice.call(arguments),e=t.pop(),n=t;if("function"!=typeof e)throw new TypeError("last argument must be a function");n.forEach(function(t){this.hasHandler(t)||(this.events[t]=[]),this.events[t].push(e)},this)},t.EventEmitter.prototype.removeListener=function(t,e){if(this.hasHandler(t)){var n=this.events[t].indexOf(e);this.events[t].splice(n,1),this.events[t].length||delete this.events[t]}},t.EventEmitter.prototype.emit=function(t){if(this.hasHandler(t)){var e=Array.prototype.slice.call(arguments,1);this.events[t].forEach(function(t){t.apply(void 0,e)})}},t.EventEmitter.prototype.hasHandler=function(t){return t in this.events},t.tokenizer=function(t){return arguments.length&&null!=t&&void 0!=t?Array.isArray(t)?t.map(function(t){return t.toLowerCase()}):t.toString().trim().toLowerCase().split(/[\s\-]+/):[]},t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.registeredFunctions[e];if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._stack.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");i+=1,this._stack.splice(i,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._stack.indexOf(e);if(-1==i)throw new Error("Cannot find existingFn");this._stack.splice(i,0,n)},t.Pipeline.prototype.remove=function(t){var e=this._stack.indexOf(t);-1!=e&&this._stack.splice(e,1)},t.Pipeline.prototype.run=function(t){for(var e=[],n=t.length,i=this._stack.length,o=0;n>o;o++){for(var r=t[o],s=0;i>s&&(r=this._stack[s](r,o,t),void 0!==r);s++);void 0!==r&&e.push(r)}return e},t.Pipeline.prototype.reset=function(){this._stack=[]},t.Pipeline.prototype.toJSON=function(){return this._stack.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Vector=function(){this._magnitude=null,this.list=void 0,this.length=0},t.Vector.Node=function(t,e,n){this.idx=t,this.val=e,this.next=n},t.Vector.prototype.insert=function(e,n){this._magnitude=void 0;var i=this.list;if(!i)return this.list=new t.Vector.Node(e,n,i),this.length++;if(e ').html(content);
+
+ $link.appendTo($title);
+ $title.appendTo($li);
+ $content.appendTo($li);
+ $li.appendTo($searchList);
+ });
+ }
+
+ function launchSearch(q) {
+ // Add class for loading
+ $body.addClass('with-search');
+ $body.addClass('search-loading');
+
+ // Launch search query
+ throttle(gitbook.search.query(q, 0, MAX_RESULTS)
+ .then(function(results) {
+ displayResults(results);
+ })
+ .always(function() {
+ $body.removeClass('search-loading');
+ }), 1000);
+ }
+
+ function closeSearch() {
+ $body.removeClass('with-search');
+ $bookSearchResults.removeClass('open');
+ }
+
+ function launchSearchFromQueryString() {
+ var q = getParameterByName('q');
+ if (q && q.length > 0) {
+ // Update search input
+ $searchInput.val(q);
+
+ // Launch search
+ launchSearch(q);
+ }
+ }
+
+ function bindSearch() {
+ // Bind DOM
+ $searchInput = $('#book-search-input input');
+ $bookSearchResults = $('#book-search-results');
+ $searchList = $bookSearchResults.find('.search-results-list');
+ $searchTitle = $bookSearchResults.find('.search-results-title');
+ $searchResultsCount = $searchTitle.find('.search-results-count');
+ $searchQuery = $searchTitle.find('.search-query');
+
+ // Launch query based on input content
+ function handleUpdate() {
+ var q = $searchInput.val();
+
+ if (q.length == 0) {
+ closeSearch();
+ }
+ else {
+ launchSearch(q);
+ }
+ }
+
+ // Detect true content change in search input
+ // Workaround for IE < 9
+ var propertyChangeUnbound = false;
+ $searchInput.on('propertychange', function(e) {
+ if (e.originalEvent.propertyName == 'value') {
+ handleUpdate();
+ }
+ });
+
+ // HTML5 (IE9 & others)
+ $searchInput.on('input', function(e) {
+ // Unbind propertychange event for IE9+
+ if (!propertyChangeUnbound) {
+ $(this).unbind('propertychange');
+ propertyChangeUnbound = true;
+ }
+
+ handleUpdate();
+ });
+
+ // Push to history on blur
+ $searchInput.on('blur', function(e) {
+ // Update history state
+ if (usePushState) {
+ var uri = updateQueryString('q', $(this).val());
+ history.pushState({ path: uri }, null, uri);
+ }
+ });
+ }
+
+ gitbook.events.on('page.change', function() {
+ bindSearch();
+ closeSearch();
+
+ // Launch search based on query parameter
+ if (gitbook.search.isInitialized()) {
+ launchSearchFromQueryString();
+ }
+ });
+
+ gitbook.events.on('search.ready', function() {
+ bindSearch();
+
+ // Launch search from query param at start
+ launchSearchFromQueryString();
+ });
+
+ function getParameterByName(name) {
+ var url = window.location.href;
+ name = name.replace(/[\[\]]/g, '\\$&');
+ var regex = new RegExp('[?&]' + name + '(=([^]*)|&|#|$)', 'i'),
+ results = regex.exec(url);
+ if (!results) return null;
+ if (!results[2]) return '';
+ return decodeURIComponent(results[2].replace(/\+/g, ' '));
+ }
+
+ function updateQueryString(key, value) {
+ value = encodeURIComponent(value);
+
+ var url = window.location.href;
+ var re = new RegExp('([?&])' + key + '=.*?(&|#|$)(.*)', 'gi'),
+ hash;
+
+ if (re.test(url)) {
+ if (typeof value !== 'undefined' && value !== null)
+ return url.replace(re, '$1' + key + '=' + value + '$2$3');
+ else {
+ hash = url.split('#');
+ url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
+ if (typeof hash[1] !== 'undefined' && hash[1] !== null)
+ url += '#' + hash[1];
+ return url;
+ }
+ }
+ else {
+ if (typeof value !== 'undefined' && value !== null) {
+ var separator = url.indexOf('?') !== -1 ? '&' : '?';
+ hash = url.split('#');
+ url = hash[0] + separator + key + '=' + value;
+ if (typeof hash[1] !== 'undefined' && hash[1] !== null)
+ url += '#' + hash[1];
+ return url;
+ }
+ else
+ return url;
+ }
+ }
+});
diff --git a/docs/assets/gitbook/gitbook-plugin-sharing/buttons.js b/docs/assets/gitbook/gitbook-plugin-sharing/buttons.js
new file mode 100644
index 0000000..654aa05
--- /dev/null
+++ b/docs/assets/gitbook/gitbook-plugin-sharing/buttons.js
@@ -0,0 +1,117 @@
+require(['gitbook', 'jquery'], function(gitbook, $) {
+ var SITES = {
+ 'facebook': {
+ 'label': 'Facebook',
+ 'icon': 'fa fa-facebook',
+ 'onClick': function(e) {
+ e.preventDefault();
+ window.open('http://www.facebook.com/sharer/sharer.php?s=100&p[url]='+encodeURIComponent(location.href));
+ }
+ },
+ 'twitter': {
+ 'label': 'Twitter',
+ 'icon': 'fa fa-twitter',
+ 'onClick': function(e) {
+ e.preventDefault();
+ window.open('http://twitter.com/home?status='+encodeURIComponent(document.title+' '+location.href));
+ }
+ },
+ 'github': {
+ 'label': 'Github',
+ 'icon': 'fa fa-github',
+ 'onClick': function(e) {
+ e.preventDefault();
+ window.open('https://github.com');
+ }
+ },
+ 'telegram': {
+ 'label': 'Telegram',
+ 'icon': 'fa fa-telegram',
+ 'onClick': function(e) {
+ e.preventDefault();
+ window.open('https://t.me');
+ }
+ },
+ 'google': {
+ 'label': 'Google+',
+ 'icon': 'fa fa-google-plus',
+ 'onClick': function(e) {
+ e.preventDefault();
+ window.open('https://plus.google.com/share?url='+encodeURIComponent(location.href));
+ }
+ },
+ 'weibo': {
+ 'label': 'Weibo',
+ 'icon': 'fa fa-weibo',
+ 'onClick': function(e) {
+ e.preventDefault();
+ window.open('http://service.weibo.com/share/share.php?content=utf-8&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title));
+ }
+ },
+ 'instapaper': {
+ 'label': 'Instapaper',
+ 'icon': 'fa fa-instapaper',
+ 'onClick': function(e) {
+ e.preventDefault();
+ window.open('http://www.instapaper.com/text?u='+encodeURIComponent(location.href));
+ }
+ },
+ 'vk': {
+ 'label': 'VK',
+ 'icon': 'fa fa-vk',
+ 'onClick': function(e) {
+ e.preventDefault();
+ window.open('http://vkontakte.ru/share.php?url='+encodeURIComponent(location.href));
+ }
+ }
+ };
+
+
+
+ gitbook.events.bind('start', function(e, config) {
+ var opts = config.sharing;
+
+ // Create dropdown menu
+ var menu = $.map(opts.all, function(id) {
+ var site = SITES[id];
+
+ return {
+ text: site.label,
+ onClick: site.onClick
+ };
+ });
+
+ // Create main button with dropdown
+ if (menu.length > 0) {
+ gitbook.toolbar.createButton({
+ icon: 'fa fa-share-alt',
+ label: 'Share',
+ position: 'right',
+ dropdown: [menu]
+ });
+ }
+
+ // Direct actions to share
+ $.each(SITES, function(sideId, site) {
+ if (!opts[sideId]) return;
+
+ var onClick = site.onClick;
+
+ // override target link with provided link
+ var side_link = opts[`${sideId}_link`]
+ if (side_link !== undefined && side_link !== "") {
+ onClick = function(e) {
+ e.preventDefault();
+ window.open(side_link);
+ }
+ }
+
+ gitbook.toolbar.createButton({
+ icon: site.icon,
+ label: site.text,
+ position: 'right',
+ onClick: onClick
+ });
+ });
+ });
+});
diff --git a/docs/assets/gitbook/gitbook-plugin-splitter/splitter.css b/docs/assets/gitbook/gitbook-plugin-splitter/splitter.css
new file mode 100644
index 0000000..8ada38b
--- /dev/null
+++ b/docs/assets/gitbook/gitbook-plugin-splitter/splitter.css
@@ -0,0 +1,24 @@
+.divider-content-summary {
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 100%;
+ width: 5px;
+ display: table;
+ cursor: col-resize;
+ color: #ccc;
+ -webkit-transition: color 350ms ease;
+ -moz-transition: color 350ms ease;
+ -o-transition: color 350ms ease;
+ transition: color 350ms ease
+}
+
+.divider-content-summary:hover {
+ color: #444;
+}
+
+.divider-content-summary__icon {
+ display: table-cell;
+ vertical-align: middle;
+ text-align: center;
+}
\ No newline at end of file
diff --git a/docs/assets/gitbook/gitbook-plugin-splitter/splitter.js b/docs/assets/gitbook/gitbook-plugin-splitter/splitter.js
new file mode 100644
index 0000000..4f7e2ec
--- /dev/null
+++ b/docs/assets/gitbook/gitbook-plugin-splitter/splitter.js
@@ -0,0 +1,127 @@
+require(['gitbook', 'jQuery'], function (gitbook, $) {
+ // MEMO:
+ // Gitbook is calculated as "calc (100% - 60px)" in the horizontal width when the width of the screen size is 600px
+ // or less.
+ // In this case, since contradiction occurs in the implementation of this module, return.
+ if($(window).width() <= 600) {
+ return;
+ }
+
+ gitbook.events.bind('start', function () {
+ });
+
+ gitbook.events.bind('page.change', function () {
+
+ var KEY_SPLIT_STATE = 'plugin_gitbook_split';
+
+ var dividerWidth = null;
+ var isDraggable = false;
+ var dividerCenterOffsetLeft = null;
+ var splitState = null;
+ var grabPointWidth = null;
+
+ var $body = $('body');
+ var $book = $('.book');
+ var $summary = $('.book-summary');
+ var $bookBody = $('.book-body');
+ var $divider = $(' =0&&n');
+
+ var $link = $('', {
+ 'href': gitbook.state.basePath + '/' + res.url,
+ 'text': res.title
+ });
+
+ var content = res.body.trim();
+ if (content.length > MAX_DESCRIPTION_SIZE) {
+ content = content.slice(0, MAX_DESCRIPTION_SIZE).trim()+'...';
+ }
+ var $content = $('
-1)o&&o.push(i);else if(c=de.contains(i.ownerDocument,i),s=v(f.appendChild(i),"script"),c&&y(s),n)for(l=0;i=s[l++];)Ve.test(i.type||"")&&n.push(i);return f}function b(){return!0}function w(){return!1}function T(){try{return te.activeElement}catch(e){}}function C(e,t,n,r,o,i){var s,a;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=void 0);for(a in t)C(e,a,n,r,t[a],i);return e}if(null==r&&null==o?(o=n,r=n=void 0):null==o&&("string"==typeof n?(o=r,r=void 0):(o=r,r=n,n=void 0)),o===!1)o=w;else if(!o)return e;return 1===i&&(s=o,o=function(e){return de().off(e),s.apply(this,arguments)},o.guid=s.guid||(s.guid=de.guid++)),e.each(function(){de.event.add(this,t,o,r,n)})}function j(e,t){return de.nodeName(e,"table")&&de.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e:e}function k(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function E(e){var t=rt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function S(e,t){var n,r,o,i,s,a,u,c;if(1===t.nodeType){if(Fe.hasData(e)&&(i=Fe.access(e),s=Fe.set(t,i),c=i.events)){delete s.handle,s.events={};for(o in c)for(n=0,r=c[o].length;n=s&&(r!==u&&(c=void 0,l=[e]),n.rejectWith(c,l))}};t?p():(de.Deferred.getStackHook&&(p.stackTrace=de.Deferred.getStackHook()),e.setTimeout(p))}}var s=0;return de.Deferred(function(e){n[0][3].add(i(0,e,de.isFunction(o)?o:a,e.notifyWith)),n[1][3].add(i(0,e,de.isFunction(t)?t:a)),n[2][3].add(i(0,e,de.isFunction(r)?r:u))}).promise()},promise:function(e){return null!=e?de.extend(e,o):o}},i={};return de.each(n,function(e,t){var s=t[2],a=t[5];o[t[1]]=s.add,a&&s.add(function(){r=a},n[3-e][2].disable,n[0][2].lock),s.add(t[3].fire),i[t[0]]=function(){return i[t[0]+"With"](this===i?void 0:this,arguments),this},i[t[0]+"With"]=s.fireWith}),o.promise(i),t&&t.call(i,i),i},when:function(e){var t=arguments.length,n=t,r=Array(n),o=re.call(arguments),i=de.Deferred(),s=function(e){return function(n){r[e]=this,o[e]=arguments.length>1?re.call(arguments):n,--t||i.resolveWith(r,o)}};if(t<=1&&(c(e,i.done(s(n)).resolve,i.reject),"pending"===i.state()||de.isFunction(o[n]&&o[n].then)))return i.then();for(;n--;)c(o[n],s(n),i.reject);return i.promise()}});var De=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;de.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&De.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},de.readyException=function(t){e.setTimeout(function(){throw t})};var Oe=de.Deferred();de.fn.ready=function(e){return Oe.then(e).catch(function(e){de.readyException(e)}),this},de.extend({isReady:!1,readyWait:1,holdReady:function(e){e?de.readyWait++:de.ready(!0)},ready:function(e){(e===!0?--de.readyWait:de.isReady)||(de.isReady=!0,e!==!0&&--de.readyWait>0||Oe.resolveWith(te,[de]))}}),de.ready.then=Oe.then,"complete"===te.readyState||"loading"!==te.readyState&&!te.documentElement.doScroll?e.setTimeout(de.ready):(te.addEventListener("DOMContentLoaded",l),e.addEventListener("load",l));var Le=function(e,t,n,r,o,i,s){var a=0,u=e.length,c=null==n;if("object"===de.type(n)){o=!0;for(a in n)Le(e,t,a,n[a],!0,i,s)}else if(void 0!==r&&(o=!0,de.isFunction(r)||(s=!0),c&&(s?(t.call(e,r),t=null):(c=t,t=function(e,t,n){return c.call(de(e),n)})),t))for(;a1,null,!0)},removeData:function(e){return this.each(function(){Re.remove(this,e)})}}),de.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Fe.get(e,t),n&&(!r||de.isArray(n)?r=Fe.access(e,t,de.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=de.queue(e,t),r=n.length,o=n.shift(),i=de._queueHooks(e,t),s=function(){de.dequeue(e,t)};"inprogress"===o&&(o=n.shift(),r--),o&&("fx"===t&&n.unshift("inprogress"),delete i.stop,o.call(e,s,i)),!r&&i&&i.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Fe.get(e,n)||Fe.access(e,n,{empty:de.Callbacks("once memory").add(function(){Fe.remove(e,[t+"queue",n])})})}}),de.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length","
"],col:[2,"
"],tr:[2,"","
"],td:[3,"
"],_default:[0,"",""]};Ge.optgroup=Ge.option,Ge.tbody=Ge.tfoot=Ge.colgroup=Ge.caption=Ge.thead,Ge.th=Ge.td;var Ye=/<|?\w+;/;!function(){var e=te.createDocumentFragment(),t=e.appendChild(te.createElement("div")),n=te.createElement("input");n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),t.appendChild(n),pe.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML="",pe.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue}();var Qe=te.documentElement,Je=/^key/,Ke=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ze=/^([^.]*)(?:\.(.+)|)/;de.event={global:{},add:function(e,t,n,r,o){var i,s,a,u,c,l,f,p,h,d,g,m=Fe.get(e);if(m)for(n.handler&&(i=n,n=i.handler,o=i.selector),o&&de.find.matchesSelector(Qe,o),n.guid||(n.guid=de.guid++),(u=m.events)||(u=m.events={}),(s=m.handle)||(s=m.handle=function(t){return"undefined"!=typeof de&&de.event.triggered!==t.type?de.event.dispatch.apply(e,arguments):void 0}),t=(t||"").match(qe)||[""],c=t.length;c--;)a=Ze.exec(t[c])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h&&(f=de.event.special[h]||{},h=(o?f.delegateType:f.bindType)||h,f=de.event.special[h]||{},l=de.extend({type:h,origType:g,data:r,handler:n,guid:n.guid,selector:o,needsContext:o&&de.expr.match.needsContext.test(o),namespace:d.join(".")},i),(p=u[h])||(p=u[h]=[],p.delegateCount=0,f.setup&&f.setup.call(e,r,d,s)!==!1||e.addEventListener&&e.addEventListener(h,s)),f.add&&(f.add.call(e,l),l.handler.guid||(l.handler.guid=n.guid)),o?p.splice(p.delegateCount++,0,l):p.push(l),de.event.global[h]=!0)},remove:function(e,t,n,r,o){var i,s,a,u,c,l,f,p,h,d,g,m=Fe.hasData(e)&&Fe.get(e);if(m&&(u=m.events)){for(t=(t||"").match(qe)||[""],c=t.length;c--;)if(a=Ze.exec(t[c])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){for(f=de.event.special[h]||{},h=(r?f.delegateType:f.bindType)||h,p=u[h]||[],a=a[2]&&new RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=i=p.length;i--;)l=p[i],!o&&g!==l.origType||n&&n.guid!==l.guid||a&&!a.test(l.namespace)||r&&r!==l.selector&&("**"!==r||!l.selector)||(p.splice(i,1),l.selector&&p.delegateCount--,f.remove&&f.remove.call(e,l));s&&!p.length&&(f.teardown&&f.teardown.call(e,d,m.handle)!==!1||de.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)de.event.remove(e,h+t[c],n,r,!0);de.isEmptyObject(u)&&Fe.remove(e,"handle events")}},dispatch:function(e){var t,n,r,o,i,s,a=de.event.fix(e),u=new Array(arguments.length),c=(Fe.get(this,"events")||{})[a.type]||[],l=de.event.special[a.type]||{};for(u[0]=a,t=1;t","