├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .huskyrc.json ├── .lintstagedrc.json ├── .prettierrc.json ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── examples ├── README.md ├── ReactNativeSample │ ├── .buckconfig │ ├── .eslintrc.js │ ├── .flowconfig │ ├── .gitattributes │ ├── .gitignore │ ├── .prettierrc.js │ ├── .watchmanconfig │ ├── App.js │ ├── README.md │ ├── __tests__ │ │ └── App-test.js │ ├── android │ │ ├── app │ │ │ ├── BUCK │ │ │ ├── build.gradle │ │ │ ├── build_defs.bzl │ │ │ ├── debug.keystore │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ │ └── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── reactnativesample │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ │ └── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── app.json │ ├── babel.config.js │ ├── index.js │ ├── ios │ │ ├── Podfile │ │ ├── Podfile.lock │ │ ├── ReactNativeSample-tvOS │ │ │ └── Info.plist │ │ ├── ReactNativeSample-tvOSTests │ │ │ └── Info.plist │ │ ├── ReactNativeSample.xcodeproj │ │ │ ├── project.pbxproj │ │ │ └── xcshareddata │ │ │ │ └── xcschemes │ │ │ │ ├── ReactNativeSample-tvOS.xcscheme │ │ │ │ └── ReactNativeSample.xcscheme │ │ ├── ReactNativeSample.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── ReactNativeSample │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── Base.lproj │ │ │ │ └── LaunchScreen.xib │ │ │ ├── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ └── main.m │ │ └── ReactNativeSampleTests │ │ │ ├── Info.plist │ │ │ └── ReactNativeSampleTests.m │ ├── metro.config.js │ └── package.json ├── authEncryptFile.html ├── backend │ ├── .env.example │ ├── README.md │ ├── index.js │ └── package.json ├── create-react-app │ ├── .env.example │ ├── .gitignore │ ├── README.md │ ├── config-overrides.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ ├── serviceWorker.js │ │ └── setupTests.js ├── ionic │ ├── .gitignore │ ├── README.md │ ├── angular.json │ ├── browserslist │ ├── e2e │ │ ├── protractor.conf.js │ │ ├── src │ │ │ ├── app.e2e-spec.ts │ │ │ └── app.po.ts │ │ └── tsconfig.json │ ├── ionic.config.json │ ├── karma.conf.js │ ├── package.json │ ├── src │ │ ├── app │ │ │ ├── app-routing.module.ts │ │ │ ├── app.component.html │ │ │ ├── app.component.scss │ │ │ ├── app.component.spec.ts │ │ │ ├── app.component.ts │ │ │ ├── app.module.ts │ │ │ └── home │ │ │ │ ├── e3kit.service.ts │ │ │ │ ├── home.module.ts │ │ │ │ ├── home.page.html │ │ │ │ ├── home.page.scss │ │ │ │ ├── home.page.spec.ts │ │ │ │ └── home.page.ts │ │ ├── assets │ │ │ ├── icon │ │ │ │ └── favicon.png │ │ │ └── shapes.svg │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── global.scss │ │ ├── index.html │ │ ├── main.ts │ │ ├── polyfills.ts │ │ ├── test.ts │ │ ├── theme │ │ │ └── variables.scss │ │ └── zone-flags.ts │ ├── tsconfig.app.json │ ├── tsconfig.json │ ├── tsconfig.spec.json │ └── tslint.json ├── node │ ├── .env.example │ ├── README.md │ ├── index.js │ └── package.json ├── umd │ ├── README.md │ ├── package.json │ └── src │ │ └── index.html └── webpack │ ├── .env.example │ ├── .eslintrc.json │ ├── README.md │ ├── index.html │ ├── index.js │ ├── package.json │ └── webpack.config.js ├── lerna.json ├── package.json ├── packages ├── e3kit-base │ ├── declarations.d.ts │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── AbstractEThree.ts │ │ ├── GroupLocalStorage.ts │ │ ├── GroupManager.ts │ │ ├── PrivateKeyLoader.ts │ │ ├── __tests__ │ │ │ ├── AbstractEThree.spec.ts │ │ │ └── GroupLocalStorage.spec.ts │ │ ├── array.ts │ │ ├── brainkey.ts │ │ ├── constants.ts │ │ ├── errors.ts │ │ ├── groups │ │ │ └── Group.ts │ │ ├── index.ts │ │ ├── log.ts │ │ ├── typeguards.ts │ │ ├── types.ts │ │ ├── utils │ │ │ ├── card.ts │ │ │ ├── date.ts │ │ │ ├── number.ts │ │ │ └── set.ts │ │ └── virgil-encrypt-down │ │ │ └── index.ts │ ├── tsconfig.json │ └── tsconfig.spec.json ├── e3kit-browser │ ├── README.md │ ├── browser.cjs.js │ ├── browser.es.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── EThree.ts │ │ ├── constants.ts │ │ ├── index.ts │ │ ├── processFile.ts │ │ ├── typeguards.ts │ │ └── types.ts │ ├── tsconfig.json │ ├── worker.cjs.js │ └── worker.es.js ├── e3kit-native │ ├── README.md │ ├── declarations.d.ts │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── EThree.ts │ │ ├── asyncstoragedown-clear-polyfill.ts │ │ ├── index.ts │ │ └── types.ts │ └── tsconfig.json ├── e3kit-node │ ├── README.md │ ├── declaration.d.ts │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── EThree.ts │ │ ├── index.ts │ │ └── types.ts │ └── tsconfig.json └── e3kit-tests │ ├── .env.example │ ├── .eslintrc.json │ ├── babel.config.json │ ├── jest.config.ts │ ├── karma.conf.js │ ├── package.json │ ├── setup-mocha.js │ ├── src │ ├── browser.ts │ ├── browser │ │ ├── EThreeBrowser.test.ts │ │ └── EthreeDocSnippets.test.ts │ ├── common │ │ ├── EThree.spec.ts │ │ ├── Group.spec.ts │ │ ├── compatibility_data.json │ │ └── utils.ts │ └── node.spec.ts │ └── tsconfig.json ├── scripts ├── doc-index-template.html.ejs └── generate-docs.js └── utils └── build.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "react", 5 | "stage-0" 6 | ], 7 | "plugins": [ 8 | "transform-class-properties", 9 | "transform-decorators", 10 | "transform-react-constant-elements", 11 | "transform-react-inline-elements" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | examples/ionic 2 | examples/*/dist 3 | examples/*/node_modules 4 | packages/*/dist 5 | packages/*/node_modules 6 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "eslint-plugin-prettier", 4 | "eslint-plugin-no-cyrillic-string" 5 | ], 6 | "rules": { 7 | "prettier/prettier": "error", 8 | "no-cyrillic-string/no-cyrillic-string": "error" 9 | }, 10 | "parser": "@typescript-eslint/parser", 11 | "parserOptions": { 12 | "ecmaVersion": 2022, 13 | "sourceType": "module" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | .idea 4 | .vscode 5 | 6 | node_modules 7 | package-lock.json 8 | yarn.lock 9 | *.log 10 | 11 | .env 12 | 13 | .rpt2_cache 14 | .virgil_key_entries 15 | .virgil-keyknox-storage 16 | .virgil-group-storage* 17 | .virgil-local-storage 18 | coverage 19 | dist 20 | docs 21 | build 22 | -------------------------------------------------------------------------------- /.huskyrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "hooks": { 3 | "pre-commit": "lint-staged" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "*.{js,ts}": [ 3 | "eslint --fix" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "tabWidth": 4, 4 | "singleQuote": true, 5 | "trailingComma": "all" 6 | } 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 10 4 | - 11 5 | - 12 6 | - 13 7 | - 14 8 | - 15 9 | - 16 10 | - 17 11 | - 18 12 | before_install: 13 | - yarn cache clean 14 | install: 15 | - yarn install --ignore-engines 16 | script: 17 | - yarn lint 18 | - yarn test 19 | before_deploy: 20 | - yarn docs 21 | deploy: 22 | provider: pages 23 | skip-cleanup: true 24 | github-token: $GITHUB_TOKEN 25 | keep-history: true 26 | local-dir: docs 27 | on: # deploy only tagged build on Node.js 10 28 | branch: master 29 | node: 10 30 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 2019-11-05 0.7.0-beta.0 4 | 5 | ### Added 6 | 7 | * Ability to create secure group chats. See example in [Readme](/README.md) 8 | * New method to search for other users' public keys - `EThree.findUsers`, which returns Virgil Cards instead of public keys. 9 | 10 | ### Deprecated 11 | 12 | * `EThree.lookupPublicKeys` - new implementations should use `EThree.findUsers` instead. 13 | * Calling `EThree.encrypt` and `EThree.decrypt` with the result of `EThree.lookupPublicKeys` method. New implementations should pass the result of `EThree.findUsers` instead. 14 | 15 | > A warning will be printed to the console if deprecated methods are called. 16 | 17 | ### Breaking changes 18 | 19 | * Starting from this version E3kit is distributed as a monorepo. We've split it up into separate packages for [Browsers](/packages/e3kit-browser), [Node.js](/packages/e3kit-node) and [React Native](/packages/e3kit-native). The [e3kit](/packages/e3kit) package will continue to exist on NPM, so this is actually a backward-compatible change, however we recommend new implementations to depend on a package specific to their platform for faster install times and correct type definitions. 20 | 21 | * `EThree.encrypt`, `EThree.decrypt` and `EThree.backupPrivateKey` now throw `MissingPrivateKeyError` instead of `RegisterRequiredError` when private key is not found. That error makes more sense because the identity might be registered even if the key does not exist on the device. 22 | 23 | ## 2019-10-24 0.6.2 24 | 25 | * Fixed: references to `process.env` remained in bundles due to a misconfiguration of Rollup plugin that was meant to replace them with actual values. This caused `ReferenceError: process is not defined` when using UMD bundle in a browser. And it also caused VirgilAgent header to not include the product and version info. 26 | 27 | ## 2019-10-15 0.6.1 28 | 29 | * Fixed errors during construction of custom error objects in React Native 30 | 31 | ## 2019-10-11 0.6.0 32 | 33 | * The only change comparing to beta version is that we now send users' e3kit version and platform information (not personal information or anything that can be used to track users online) in an HTTP header with each request to Virgil Cloud to help us improve our services and provide better support. 34 | 35 | ## 2019-09-12 0.6.0-beta.2 36 | 37 | * Fix: added missing exports for custom error classes and TypeScript type definitions 38 | 39 | ## 2019-09-09 0.6.0-beta.1 40 | 41 | * Switched to WebAssembly-based JS crypto library 42 | * Started using native crypto libraries in React Native via JS bridge 43 | * Added Node.js support 44 | 45 | ## 2019-08-28 0.5.3 46 | 47 | * Caching the private key in memory to improve performace. 48 | 49 | ## 2019-08-23 0.5.2 50 | 51 | * Added ability to provide custom keypair to `e3Instance.register` method. 52 | 53 | ## 2019-08-20 0.5.1 54 | 55 | * `EThree.initialize` now throws a `TypeError` if the `getToken` argument is not a function. 56 | 57 | ## 2019-06-24 0.5.0 58 | 59 | * Added `Ethree.unregister()` method to revoke the current user's Virgil Card in Virgil Cloud and delete the local private key (i.e. undo everything `register` does). 60 | 61 | ## 2019-05-10 0.3.9 62 | 63 | * Fixed public key checking in encrypt method. 64 | 65 | ## 2019-05-10 0.3.8 66 | 67 | * Fixed web worker usage. 68 | 69 | ## 2019-02-21 0.3.7 70 | 71 | * Changed method signature of EThree.resetPrivateKeyBackup(pwd?). Now password is optional. But if you using the Virgil Keyknox service directly to save some additional data, you should use password to not delete this data. 72 | 73 | ## 2019-02-13 0.3.6 74 | 75 | * Fixed compatibility with JWT generated by Python SDK 76 | 77 | ## 2019-01-10 0.3.5 78 | 79 | * Added React Native support, see https://github.com/VirgilSecurity/virgil-e3kit-js#react-native-usage 80 | 81 | ## 2018-12-22 0.3.4 82 | 83 | * Fixed broken buildings bugs 84 | * Fixed error when encryptor public key was passed in encrypt function 85 | 86 | ## 2018-11-30 0.3.0 87 | 88 | * Removed method EThree.boostrap(pwd) 89 | * Method EThree.bootstrap() renamed to EThree.register() 90 | * New method EThree.rotatePrivateKey() - used in case you lost your private key 91 | * New method EThree.restorePrivateKey(pwd) - used to fetch private key from Virgil Cloud 92 | * New method EThree.hasLocalPrivateKey() - used to check for private key existence on a device 93 | * New method EThree.resetPrivateKeyBackup(pwd) - used to reset private key backup. 94 | 95 | ## 2018-11-20 0.2.0 96 | 97 | * Rename EThree.init method to EThree.initialize 98 | * EThree.encrypt method now can accept single public key 99 | * EThree.decrypt method now accept sender public key instead of array 100 | * ЕThree.lookupPrivateKey now can lookup for one identity and return one public key. 101 | 102 | ## 2018-11-06 0.1.2 103 | 104 | * Make `identity` property of EThree class public 105 | * Expose instances of VirgilSDK thought `toolbox` property 106 | 107 | ## 2018-10-31 0.1.1 108 | 109 | * Fixed bug with Ionic 110 | * Fixed Typescript typings 111 | 112 | 113 | ## 2018-10-25 0.1.0 - Developer Preview 114 | 115 | * First draft, implemented init, boostrap, lookupPublicKey, backupPrivateKey, resetPrivateKey, encrypt and decrypt. 116 | * Not suitable for production 117 | * Tested on modern browsers 118 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018-2020, Virgil Security, Inc. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit TypeScript/JavaScript 2 | 3 | [![Build Status](https://travis-ci.com/VirgilSecurity/virgil-e3kit-js.svg?branch=master)](https://travis-ci.com/VirgilSecurity/virgil-e3kit-js) 4 | [![npm](https://img.shields.io/npm/v/@virgilsecurity/e3kit-browser.svg)](https://www.npmjs.com/package/@virgilsecurity/e3kit-browser) 5 | [![GitHub license](https://img.shields.io/github/license/VirgilSecurity/e3kit-js.svg)](https://github.com/VirgilSecurity/virgil-e3kit-js/blob/master/LICENSE) 6 | [![API Reference](https://img.shields.io/badge/API%20reference-e3kit--js-green)](https://virgilsecurity.github.io/virgil-e3kit-js/) 7 | 8 | [Introduction](#introduction) | [Benefits](#benefits) | [Features](#features) | [Installation](#installation) | [Resources](#resources) | [Samples](#samples) | [License](#license) | [Support](#support) 9 | 10 | ## Introduction 11 | 12 | [Virgil Security](https://virgilsecurity.com) provides [Virgil E3Kit](https://virgilsecurity.com/e3kit/) - an open-source client-side framework that allows developers to add end-to-end encryption to their messaging applications, file sharing programs, and other digital communication products in just a few simple steps to become HIPAA and GDPR compliant and more. 13 | 14 | ## Benefits 15 | 16 | - Easy to setup and integrate into new or existing projects 17 | - Compatible with any CPaaS provider, including Nexmo, Firebase, Twilio, PubNub and etc. 18 | - Strong secret keys storage, integration with all platform-specific storages 19 | - Provides GDPR and HIPAA compliance 20 | - Immune to quantum computers attacks 21 | 22 | ## Features 23 | 24 | - Strong one-to-one and group encryption 25 | - Files end-to-end encryption (for browser and React Native) 26 | - Data signature and verification as part of the encrypt and decrypt functions 27 | - Recoverable private encryption keys 28 | - Access to encrypted data from multiple user devices 29 | 30 | ## Installation 31 | 32 | Navigate to our [Developer Documentation](https://developer.virgilsecurity.com/docs/e3kit/get-started/setup-client/) to install and initialize Virgil E3Kit. 33 | 34 | Virgil E3Kit JS is provided in separate packages for different platforms: 35 | 36 | | Name | Description | 37 | | :--- | :---------- | 38 | | [e3kit-browser](/packages/e3kit-browser) | For use in web browsers. | 39 | | [e3kit-native](/packages/e3kit-native) | For use in React Native. | 40 | | [e3kit-node](/packages/e3kit-node) | For use in Node.js and Electron. | 41 | 42 | ## Resources 43 | 44 | - [E3Kit Product Page](https://virgilsecurity.com/e3kit/) 45 | - [E3Kit Documentation](https://developer.virgilsecurity.com/docs/e3kit/) - start integrating E3Kit into your project with our detailed guides. 46 | - [E3Kit TypeScript/JavaScript API Reference](https://virgilsecurity.github.io/virgil-e3kit-js/) - E3Kit API reference for the language of your choice. 47 | - [Quickstart Demo](https://developer.virgilsecurity.com/docs/e3kit/get-started/quickstart/) - will help you to get started with the Virgil E3Kit quickly, and to learn some common ways to build end-to-end encryption between two fictional characters Alice and Bob. 48 | 49 | ## Samples 50 | 51 | You can find examples for React Native, Webpack, Ionic, Node and UMD in the [examples folder](/examples), at our [Developer Documentation](https://developer.virgilsecurity.com/docs/e3kit/) and in the [E3kit Web Demo](https://github.com/VirgilSecurity/demo-e3kit-web). 52 | 53 | ## License 54 | 55 | This library is released under the [3-clause BSD License](LICENSE). 56 | 57 | ## Support 58 | 59 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com/). 60 | 61 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 62 | 63 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 64 | 65 | ## Troubleshooting 66 | 67 | ### Webpack 68 | 69 | Make sure you're following a similar approach to the [webpack example](/examples/webpack) and pay special attention to the webpack.config.js file. 70 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit TypeScript/JavaScript Examples 2 | 3 | This directory contains various demos for E3Kit JavaScript. 4 | 5 | ## Prerequisites 6 | 7 | - Navigate to the repository root and install dependencies with [Yarn](https://yarnpkg.com/en/). 8 | ```sh 9 | yarn install 10 | ``` 11 | > You need to use Yarn because we use [Workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) in this repository 12 | - Before launching any of the examples in the directory, first set up and run the [sample backend](https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/examples/backend) for them. 13 | 14 | ## Directory contents 15 | 16 | | Demo | Description | 17 | | --- | --- | 18 | | ReactNativeSample | Sample project demonstrating the usage of `@virgilsecurity/e3kit-native` in React Native projects. | 19 | | create-react-app | Sample project demonstating the usage of `@virgilsecurity/e3kit-browser` Create React App. | 20 | | ionic | Sample project demonstrating the usage of `@virgilsecurity/e3kit-browser` in Ionic project. | 21 | | node | Sample project demonstrating the usage of `@virgilsecurity/e3kit-node`. | 22 | | umd | Sample project demonstrating the usage of `@virgilsecurity/e3kit-browser` UMD build. | 23 | | webpack | Sample project demonstrating the usage of `@virgilsecurity/e3kit-browser`. | 24 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | }; 5 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/Libraries/react-native/react-native-interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native$' -> '/node_modules/react-native/Libraries/react-native/react-native-implementation' 40 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 41 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 42 | 43 | suppress_type=$FlowIssue 44 | suppress_type=$FlowFixMe 45 | suppress_type=$FlowFixMeProps 46 | suppress_type=$FlowFixMeState 47 | 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 50 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 51 | 52 | [lints] 53 | sketchy-null-number=warn 54 | sketchy-null-mixed=warn 55 | sketchy-number=warn 56 | untyped-type-import=warn 57 | nonstrict-import=warn 58 | deprecated-type=warn 59 | unsafe-getters-setters=warn 60 | inexact-spread=warn 61 | unnecessary-invariant=warn 62 | signature-verification-failure=warn 63 | deprecated-utility=error 64 | 65 | [strict] 66 | deprecated-type 67 | nonstrict-import 68 | sketchy-null 69 | unclear-type 70 | unsafe-getters-setters 71 | untyped-import 72 | untyped-type-import 73 | 74 | [version] 75 | ^0.105.0 76 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /examples/ReactNativeSample/README.md: -------------------------------------------------------------------------------- 1 | # E3kit + ReactNative 2 | 3 | Sample project demonstrating the usage of `@virgilsecurity/e3kit-native` in React Native projects. 4 | 5 | ## Get Started 6 | 7 | - Configure and start the server in the `examples/backend` folder following instructions in `../examples/backend/README.md`. 8 | - Install dependencies with [Yarn](https://yarnpkg.com/en/) 9 | ```sh 10 | yarn install 11 | ``` 12 | > You need to use Yarn because we use [Workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) in this repository :) 13 | - For install iOS dependencies 14 | ```sh 15 | yarn install:ios 16 | ``` 17 | - Run the project as you normally would: 18 | ```sh 19 | yarn android 20 | ``` 21 | 22 | ```sh 23 | yarn ios 24 | ``` 25 | > ⚠️ If you see `Cannot find module '@virgilsecurity/e3kit-native'` Error, make sure you did `yarn install` in the root folder 26 | 27 | 28 | Check the `runDemo` method in [App.js](App.js) file to see what this sample does. 29 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.reactnativesample", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.reactnativesample", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/debug.keystore -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/java/com/reactnativesample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.reactnativesample; 2 | 3 | import com.facebook.react.ReactActivity; 4 | 5 | public class MainActivity extends ReactActivity { 6 | 7 | /** 8 | * Returns the name of the main component registered from JavaScript. This is used to schedule 9 | * rendering of the component. 10 | */ 11 | @Override 12 | protected String getMainComponentName() { 13 | return "ReactNativeSample"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/java/com/reactnativesample/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.reactnativesample; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import com.facebook.react.ReactNativeHost; 8 | import com.facebook.react.ReactPackage; 9 | import com.facebook.soloader.SoLoader; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.util.List; 12 | 13 | public class MainApplication extends Application implements ReactApplication { 14 | 15 | private final ReactNativeHost mReactNativeHost = 16 | new ReactNativeHost(this) { 17 | @Override 18 | public boolean getUseDeveloperSupport() { 19 | return BuildConfig.DEBUG; 20 | } 21 | 22 | @Override 23 | protected List getPackages() { 24 | @SuppressWarnings("UnnecessaryLocalVariable") 25 | List packages = new PackageList(this).getPackages(); 26 | // Packages that cannot be autolinked yet can be added manually here, for example: 27 | // packages.add(new MyReactNativePackage()); 28 | return packages; 29 | } 30 | 31 | @Override 32 | protected String getJSMainModuleName() { 33 | return "index"; 34 | } 35 | }; 36 | 37 | @Override 38 | public ReactNativeHost getReactNativeHost() { 39 | return mReactNativeHost; 40 | } 41 | 42 | @Override 43 | public void onCreate() { 44 | super.onCreate(); 45 | SoLoader.init(this, /* native exopackage */ false); 46 | initializeFlipper(this); // Remove this line if you don't want Flipper enabled 47 | } 48 | 49 | /** 50 | * Loads Flipper in React Native templates. 51 | * 52 | * @param context 53 | */ 54 | private static void initializeFlipper(Context context) { 55 | if (BuildConfig.DEBUG) { 56 | try { 57 | /* 58 | We use reflection here to pick up the class that initializes Flipper, 59 | since Flipper library is not available in release mode 60 | */ 61 | Class aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper"); 62 | aClass.getMethod("initializeFlipper", Context.class).invoke(null, context); 63 | } catch (ClassNotFoundException e) { 64 | e.printStackTrace(); 65 | } catch (NoSuchMethodException e) { 66 | e.printStackTrace(); 67 | } catch (IllegalAccessException e) { 68 | e.printStackTrace(); 69 | } catch (InvocationTargetException e) { 70 | e.printStackTrace(); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ReactNativeSample 3 | 4 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | minSdkVersion = 31 6 | compileSdkVersion = 31 7 | targetSdkVersion = 31 8 | } 9 | repositories { 10 | google() 11 | jcenter() 12 | } 13 | dependencies { 14 | classpath("com.android.tools.build:gradle:7.0.2") 15 | 16 | // NOTE: Do not place your application dependencies here; they belong 17 | // in the individual module build.gradle files 18 | } 19 | } 20 | 21 | allprojects { 22 | repositories { 23 | mavenCentral() 24 | maven { 25 | url 'https://jitpack.io' 26 | } 27 | google() 28 | jcenter() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useAndroidX=true 21 | android.enableJetifier=true 22 | org.gradle.parallel=true 23 | org.gradle.daemon=true 24 | org.gradle.jvmargs=-Xmx4608m 25 | org.gradle.configureondemand=true 26 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ReactNativeSample/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem http://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'ReactNativeSample' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactNativeSample", 3 | "displayName": "ReactNativeSample" 4 | } -------------------------------------------------------------------------------- /examples/ReactNativeSample/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import { AppRegistry } from 'react-native'; 6 | import App from './App'; 7 | import { name as appName } from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '9.0' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | target 'ReactNativeSample' do 5 | use_frameworks! 6 | use_native_modules! 7 | 8 | # Pods for ReactNativeSample 9 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" 10 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" 11 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" 12 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" 13 | pod 'React', :path => '../node_modules/react-native/' 14 | pod 'React-Core', :path => '../node_modules/react-native/' 15 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' 16 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' 17 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' 18 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' 19 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' 20 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' 21 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' 22 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' 23 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' 24 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' 25 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' 26 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' 27 | 28 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' 29 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' 30 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' 31 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' 32 | pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon" 33 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" 34 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga' 35 | 36 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' 37 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' 38 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' 39 | 40 | target 'ReactNativeSampleTests' do 41 | inherit! :search_paths 42 | # Pods for testing 43 | end 44 | end 45 | 46 | target 'ReactNativeSample-tvOS' do 47 | # Pods for ReactNativeSample-tvOS 48 | 49 | target 'ReactNativeSample-tvOSTests' do 50 | inherit! :search_paths 51 | # Pods for testing 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (nonatomic, strong) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import "AppDelegate.h" 9 | 10 | #import 11 | #import 12 | #import 13 | 14 | @implementation AppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 19 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 20 | moduleName:@"ReactNativeSample" 21 | initialProperties:nil]; 22 | 23 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 24 | 25 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 26 | UIViewController *rootViewController = [UIViewController new]; 27 | rootViewController.view = rootView; 28 | self.window.rootViewController = rootViewController; 29 | [self.window makeKeyAndVisible]; 30 | return YES; 31 | } 32 | 33 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 34 | { 35 | #if DEBUG 36 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 37 | #else 38 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 39 | #endif 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ReactNativeSample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSExceptionDomains 32 | 33 | localhost 34 | 35 | NSExceptionAllowsInsecureHTTPLoads 36 | 37 | 38 | 39 | 40 | NSLocationWhenInUseUsageDescription 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIRequiredDeviceCapabilities 45 | 46 | armv7 47 | 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationLandscapeLeft 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | UIViewControllerBasedStatusBarAppearance 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSample/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/ios/ReactNativeSampleTests/ReactNativeSampleTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | #import 12 | #import 13 | 14 | #define TIMEOUT_SECONDS 600 15 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 16 | 17 | @interface ReactNativeSampleTests : XCTestCase 18 | 19 | @end 20 | 21 | @implementation ReactNativeSampleTests 22 | 23 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 24 | { 25 | if (test(view)) { 26 | return YES; 27 | } 28 | for (UIView *subview in [view subviews]) { 29 | if ([self findSubviewInView:subview matching:test]) { 30 | return YES; 31 | } 32 | } 33 | return NO; 34 | } 35 | 36 | - (void)testRendersWelcomeScreen 37 | { 38 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 39 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 40 | BOOL foundElement = NO; 41 | 42 | __block NSString *redboxError = nil; 43 | #ifdef DEBUG 44 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 45 | if (level >= RCTLogLevelError) { 46 | redboxError = message; 47 | } 48 | }); 49 | #endif 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | #ifdef DEBUG 64 | RCTSetLogFunction(RCTDefaultLogFunction); 65 | #endif 66 | 67 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 68 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 69 | } 70 | 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * Borrows heavily from https://github.com/invertase/react-native-firebase/blob/master/tests/metro.config.js 5 | * 6 | * @format 7 | */ 8 | 9 | const { resolve, join, basename, dirname } = require('path'); 10 | const { readdirSync, statSync } = require('fs'); 11 | 12 | const { createBlacklist } = require('metro'); 13 | 14 | const rootDir = resolve(__dirname, '../..'); 15 | const packagesDir = resolve(rootDir, 'packages'); 16 | 17 | const isDirectory = source => statSync(source).isDirectory(); 18 | const virgilModules = readdirSync(packagesDir) 19 | .map(name => join(packagesDir, name)) 20 | .filter(isDirectory); 21 | const virgilPackageNames = virgilModules.map(path => basename(dirname(path))); 22 | 23 | const config = { 24 | projectRoot: __dirname, 25 | resolver: { 26 | blackListRE: createBlacklist([ 27 | new RegExp( 28 | `^${escape( 29 | resolve(rootDir, 'examples/ReactNativeSample/android'), 30 | )}\\/.*$`, 31 | ), 32 | new RegExp( 33 | `^${escape( 34 | resolve(rootDir, 'examples/ReactNativeSample/ios'), 35 | )}\\/.*$`, 36 | ), 37 | new RegExp( 38 | `^${escape( 39 | resolve(rootDir, 'examples/ReactNativeSample/node_modules'), 40 | )}\\/.*$`, 41 | ), 42 | ]), 43 | extraNodeModules: new Proxy( 44 | {}, 45 | { 46 | get: (target, name) => { 47 | if (typeof name !== 'string') { 48 | return target[name]; 49 | } 50 | if (name && virgilPackageNames.includes(name)) { 51 | const packageName = name.replace( 52 | '@virgilsecurity/', 53 | '', 54 | ); 55 | return join(__dirname, `../packages/${packageName}`); 56 | } 57 | return join(__dirname, `node_modules/${name}`); 58 | }, 59 | }, 60 | ), 61 | }, 62 | watchFolders: [...virgilModules], 63 | }; 64 | 65 | module.exports = config; 66 | -------------------------------------------------------------------------------- /examples/ReactNativeSample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactNativeSample", 3 | "version": "2.4.5", 4 | "private": true, 5 | "scripts": { 6 | "install:ios": "cd ios && pod install && cd ../", 7 | "android": "react-native run-android", 8 | "ios": "react-native run-ios", 9 | "start": "react-native start", 10 | "test": "echo \"ignoring ReactNativeSample app tests\"", 11 | "lint": "eslint ." 12 | }, 13 | "dependencies": { 14 | "@react-native-community/async-storage": "^1.12.1", 15 | "@react-native-community/cli-platform-android": "^11.3.0", 16 | "@virgilsecurity/e3kit-native": "^2.5.1", 17 | "@virgilsecurity/key-storage-rn": "^1.0.0", 18 | "react": "^18.2.0", 19 | "react-native": "^0.71.2", 20 | "react-native-keychain": "^8.1.1", 21 | "react-native-virgil-crypto": "^0.6.3" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.6.4", 25 | "@babel/runtime": "^7.6.3", 26 | "@react-native-community/eslint-config": "^3.2.0", 27 | "babel-jest": "^29.5.0", 28 | "eslint": "^8.41.0", 29 | "jest": "^29.5.0", 30 | "metro-react-native-babel-preset": "^0.76.4", 31 | "react-test-renderer": "^18.2.0" 32 | }, 33 | "jest": { 34 | "preset": "react-native" 35 | }, 36 | "workspaces": { 37 | "nohoist": [ 38 | "**/@react-native-community/async-storage", 39 | "**/@react-native-community/async-storage/**", 40 | "**/@virgilsecurity/key-storage-rn", 41 | "**/@virgilsecurity/key-storage-rn/**", 42 | "**/react-native-keychain", 43 | "**/react-native-keychain/**", 44 | "**/react-native-virgil-crypto", 45 | "**/react-native-virgil-crypto/**" 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/backend/.env.example: -------------------------------------------------------------------------------- 1 | PORT=8080 2 | APP_ID=[APP_ID] 3 | API_KEY=[API_KEY] 4 | API_KEY_ID=[API_KEY_ID] 5 | API_URL=[API_URL] 6 | -------------------------------------------------------------------------------- /examples/backend/README.md: -------------------------------------------------------------------------------- 1 | # Sample backend for Virgil E3Kit SDK 2 | 3 | ## Get Started 4 | 1. Install dependencies with [Yarn](https://yarnpkg.com/en/) 5 | ```sh 6 | yarn install 7 | ``` 8 | > You need to use Yarn because we use [Yarn Workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) in this repository :) 9 | 2. Create `.env` file. Use `.env.example` as a reference 10 | 3. Run the following command to start the server 11 | ```sh 12 | yarn start 13 | ``` 14 | 15 | ## License 16 | This library is released under the [3-clause BSD License](LICENSE). 17 | 18 | ## Support 19 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 20 | 21 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 22 | 23 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 24 | -------------------------------------------------------------------------------- /examples/backend/index.js: -------------------------------------------------------------------------------- 1 | const dotenv = require('dotenv'); 2 | const express = require('express'); 3 | const { initCrypto, VirgilCrypto, VirgilAccessTokenSigner } = require('virgil-crypto'); 4 | const { JwtGenerator } = require('virgil-sdk'); 5 | 6 | dotenv.config(); 7 | 8 | const PORT = process.env.PORT || 8080; 9 | 10 | const app = express(); 11 | 12 | (async () => { 13 | await initCrypto(); 14 | 15 | const virgilCrypto = new VirgilCrypto(); 16 | const accessTokenSigner = new VirgilAccessTokenSigner(virgilCrypto); 17 | const apiKey = virgilCrypto.importPrivateKey({ 18 | value: process.env.APP_KEY, 19 | encoding: 'base64', 20 | }); 21 | const jwtGenerator = new JwtGenerator({ 22 | apiKey, 23 | accessTokenSigner, 24 | appId: process.env.APP_ID, 25 | apiKeyId: process.env.APP_KEY_ID, 26 | apiUrl: process.env.API_URL, 27 | }); 28 | 29 | app.get('/virgil-jwt', (request, response) => { 30 | const jwt = jwtGenerator.generateToken(request.query.identity); 31 | response.header('Access-Control-Allow-Origin', '*'); 32 | response.json({ virgil_jwt: jwt.toString() }); 33 | }); 34 | 35 | app.listen(PORT, () => { 36 | console.log(`Sample backend is running on port ${PORT}`); 37 | }); 38 | })(); 39 | -------------------------------------------------------------------------------- /examples/backend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/example-backend", 3 | "version": "2.4.5", 4 | "description": "Sample backend for Virgil E3Kit SDK examples", 5 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/example-backend", 6 | "author": "Virgil Security Inc. ", 7 | "license": "BSD-3-Clause", 8 | "private": true, 9 | "scripts": { 10 | "start": "node index.js" 11 | }, 12 | "dependencies": { 13 | "dotenv": "^8.1.0", 14 | "express": "^4.17.1", 15 | "virgil-crypto": "^4.2.2", 16 | "virgil-sdk": "^6.1.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/create-react-app/.env.example: -------------------------------------------------------------------------------- 1 | REACT_APP_API_URL=http://localhost:8080 2 | -------------------------------------------------------------------------------- /examples/create-react-app/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /examples/create-react-app/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit SDK for Browsers + [Create React App](https://github.com/facebook/create-react-app) 2 | 3 | ## Notable changes 4 | - Add [react-app-rewired](https://github.com/timarney/react-app-rewired) 5 | - Add [config-overrides.js](config-overrides.js) 6 | 7 | ## License 8 | This library is released under the [3-clause BSD License](LICENSE). 9 | 10 | ## Support 11 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 12 | 13 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 14 | 15 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 16 | 17 | -------- 18 | 19 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 20 | 21 | ## Get Started 22 | 23 | 1. Configure and start the server in the `examples/backend` folder following instructions in `../examples/backend/README.md`. 24 | 2. Install dependencies with [Yarn](https://yarnpkg.com/en/) 25 | ```sh 26 | yarn install 27 | ``` 28 | > You need to use Yarn because we use [Workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) in this repository :) 29 | 3. Create `.env` file. Use `.env.example` as a reference. 30 | 4. Run the following command to start the demo 31 | ```sh 32 | yarn start 33 | ``` 34 | > ⚠️ If you see `Cannot find module '@virgilsecurity/e3kit-browser'` Error, make sure you did `yarn install` in the root folder 35 | 36 | ## Available Scripts 37 | 38 | In the project directory, you can run: 39 | 40 | ### `yarn start` 41 | 42 | Runs the app in the development mode.
43 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 44 | 45 | The page will reload if you make edits.
46 | You will also see any lint errors in the console. 47 | 48 | ### `yarn test` 49 | 50 | Launches the test runner in the interactive watch mode.
51 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 52 | 53 | ### `yarn build` 54 | 55 | Builds the app for production to the `build` folder.
56 | It correctly bundles React in production mode and optimizes the build for the best performance. 57 | 58 | The build is minified and the filenames include the hashes.
59 | Your app is ready to be deployed! 60 | 61 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 62 | 63 | ### `yarn eject` 64 | 65 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 66 | 67 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 68 | 69 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 70 | 71 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 72 | 73 | ## Learn More 74 | 75 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 76 | 77 | To learn React, check out the [React documentation](https://reactjs.org/). 78 | 79 | ### Code Splitting 80 | 81 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 82 | 83 | ### Analyzing the Bundle Size 84 | 85 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 86 | 87 | ### Making a Progressive Web App 88 | 89 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 90 | 91 | ### Advanced Configuration 92 | 93 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 94 | 95 | ### Deployment 96 | 97 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 98 | 99 | ### `yarn build` fails to minify 100 | 101 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 102 | -------------------------------------------------------------------------------- /examples/create-react-app/config-overrides.js: -------------------------------------------------------------------------------- 1 | module.exports = (config, env) => { 2 | // Use file-loader to copy WebAssembly files 3 | // https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/config/webpack.config.js#L378 4 | config.module.rules[2].oneOf.unshift({ 5 | test: /\.wasm$/, 6 | type: 'javascript/auto', 7 | loader: 'file-loader', 8 | }); 9 | return config; 10 | }; 11 | -------------------------------------------------------------------------------- /examples/create-react-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-react-app", 3 | "version": "2.4.5", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "@virgilsecurity/e3kit-browser": "^2.4.5", 10 | "react": "^16.13.0", 11 | "react-app-rewired": "^2.1.5", 12 | "react-dom": "^16.13.0", 13 | "react-scripts": "3.4.0" 14 | }, 15 | "scripts": { 16 | "start": "react-app-rewired start", 17 | "build": "react-app-rewired build", 18 | "test": "react-app-rewired test --env=jsdom", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | }, 36 | "workspaces": { 37 | "nohoist": [ 38 | "@testing-library/jest-dom", 39 | "@testing-library/react", 40 | "@testing-library/user-event", 41 | "react", 42 | "react-app-rewired", 43 | "react-dom", 44 | "react-scripts" 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/create-react-app/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/create-react-app/public/favicon.ico -------------------------------------------------------------------------------- /examples/create-react-app/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/create-react-app/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/create-react-app/public/logo192.png -------------------------------------------------------------------------------- /examples/create-react-app/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/create-react-app/public/logo512.png -------------------------------------------------------------------------------- /examples/create-react-app/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /examples/create-react-app/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /examples/create-react-app/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/create-react-app/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/create-react-app/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /examples/create-react-app/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /examples/create-react-app/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/create-react-app/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /examples/ionic/.gitignore: -------------------------------------------------------------------------------- 1 | # Specifies intentionally untracked files to ignore when using Git 2 | # http://git-scm.com/docs/gitignore 3 | 4 | *~ 5 | *.sw[mnpcod] 6 | .tmp 7 | *.tmp 8 | *.tmp.* 9 | *.sublime-project 10 | *.sublime-workspace 11 | .DS_Store 12 | Thumbs.db 13 | UserInterfaceState.xcuserstate 14 | $RECYCLE.BIN/ 15 | 16 | *.log 17 | log.txt 18 | npm-debug.log* 19 | 20 | /.idea 21 | /.ionic 22 | /.sass-cache 23 | /.sourcemaps 24 | /.versions 25 | /.vscode 26 | /coverage 27 | /dist 28 | /node_modules 29 | /platforms 30 | /plugins 31 | /www 32 | -------------------------------------------------------------------------------- /examples/ionic/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit SDK for Browsers 2 | Sample project demonstrating the usage of `@virgilsecurity/e3kit-browser` in [Ionic](https://ionicframework.com/) project. 3 | 4 | ## Get Started 5 | 1. Configure and start the server in the `examples/backend` folder following instructions in `../examples/backend/README.md`. 6 | 2. Install dependencies with [Yarn](https://yarnpkg.com/en/) 7 | ```sh 8 | yarn install 9 | ``` 10 | > You need to use Yarn because we use [Workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) in this repository :) 11 | 3. Make sure that `API_URL` value in `e3kit.service.ts` is correct. 12 | 4. Run the following command to start the demo 13 | ```sh 14 | yarn start 15 | ``` 16 | > ⚠️ If you see `Cannot find module '@virgilsecurity/e3kit-browser'` Error, make sure you did `yarn install` in the root folder 17 | 18 | ## License 19 | This library is released under the [3-clause BSD License](LICENSE). 20 | 21 | ## Support 22 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 23 | 24 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 25 | 26 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 27 | -------------------------------------------------------------------------------- /examples/ionic/browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. 13 | -------------------------------------------------------------------------------- /examples/ionic/e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: ['./src/**/*.e2e-spec.ts'], 9 | capabilities: { 10 | browserName: 'chrome', 11 | }, 12 | directConnect: true, 13 | baseUrl: 'http://localhost:4200/', 14 | framework: 'jasmine', 15 | jasmineNodeOpts: { 16 | showColors: true, 17 | defaultTimeoutInterval: 30000, 18 | print: function() {}, 19 | }, 20 | onPrepare() { 21 | require('ts-node').register({ 22 | project: require('path').join(__dirname, './tsconfig.json'), 23 | }); 24 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 25 | }, 26 | }; 27 | -------------------------------------------------------------------------------- /examples/ionic/e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('new App', () => { 4 | let page: AppPage; 5 | 6 | beforeEach(() => { 7 | page = new AppPage(); 8 | }); 9 | 10 | it('should be blank', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toContain('The world is your oyster.'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /examples/ionic/e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.deepCss('app-root ion-content')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/ionic/e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/ionic/ionic.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic", 3 | "integrations": {}, 4 | "type": "angular" 5 | } 6 | -------------------------------------------------------------------------------- /examples/ionic/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function(config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma'), 14 | ], 15 | client: { 16 | clearContext: false, // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, '../coverage'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true, 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false, 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /examples/ionic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ionic", 3 | "version": "2.4.5", 4 | "author": "Ionic Framework", 5 | "homepage": "https://ionicframework.com/", 6 | "scripts": { 7 | "ng": "ng", 8 | "start": "ng serve", 9 | "build": "ng build", 10 | "test": "ng test", 11 | "lint": "ng lint", 12 | "e2e": "ng e2e" 13 | }, 14 | "private": true, 15 | "dependencies": { 16 | "@angular/common": "~8.1.2", 17 | "@angular/compiler": "~8.1.2", 18 | "@angular/core": "~8.1.2", 19 | "@angular/forms": "~8.1.2", 20 | "@angular/platform-browser": "~8.1.2", 21 | "@angular/platform-browser-dynamic": "~8.1.2", 22 | "@angular/router": "~8.1.2", 23 | "@ionic-native/core": "^5.0.0", 24 | "@ionic-native/splash-screen": "^5.0.0", 25 | "@ionic-native/status-bar": "^5.0.0", 26 | "@ionic/angular": "^4.7.1", 27 | "@virgilsecurity/e3kit-browser": "^2.4.5", 28 | "core-js": "^2.5.4", 29 | "rxjs": "~6.5.1", 30 | "tslib": "^1.9.0", 31 | "zone.js": "~0.9.1" 32 | }, 33 | "devDependencies": { 34 | "@angular-devkit/architect": "~0.801.2", 35 | "@angular-devkit/build-angular": "~0.801.2", 36 | "@angular-devkit/core": "~8.1.2", 37 | "@angular-devkit/schematics": "~8.1.2", 38 | "@angular/cli": "~8.1.2", 39 | "@angular/compiler": "~8.1.2", 40 | "@angular/compiler-cli": "~8.1.2", 41 | "@angular/language-service": "~8.1.2", 42 | "@ionic/angular-toolkit": "~2.0.0", 43 | "@types/jasmine": "~3.3.8", 44 | "@types/jasminewd2": "~2.0.3", 45 | "@types/node": "~8.9.4", 46 | "codelyzer": "^5.0.0", 47 | "jasmine-core": "~3.4.0", 48 | "jasmine-spec-reporter": "~4.2.1", 49 | "karma": "~4.1.0", 50 | "karma-chrome-launcher": "~2.2.0", 51 | "karma-coverage-istanbul-reporter": "~2.0.1", 52 | "karma-jasmine": "~2.0.1", 53 | "karma-jasmine-html-reporter": "^1.4.0", 54 | "protractor": "~5.4.0", 55 | "ts-node": "~7.0.0", 56 | "tslint": "~5.15.0", 57 | "typescript": "~3.4.3" 58 | }, 59 | "description": "An Ionic project" 60 | } 61 | -------------------------------------------------------------------------------- /examples/ionic/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; 3 | 4 | const routes: Routes = [ 5 | { path: '', redirectTo: 'home', pathMatch: 'full' }, 6 | { path: 'home', loadChildren: () => import('./home/home.module').then(m => m.HomePageModule) }, 7 | ]; 8 | 9 | @NgModule({ 10 | imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })], 11 | exports: [RouterModule], 12 | }) 13 | export class AppRoutingModule {} 14 | -------------------------------------------------------------------------------- /examples/ionic/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/ionic/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ionic/src/app/app.component.scss -------------------------------------------------------------------------------- /examples/ionic/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; 2 | import { TestBed, async } from '@angular/core/testing'; 3 | 4 | import { Platform } from '@ionic/angular'; 5 | import { SplashScreen } from '@ionic-native/splash-screen/ngx'; 6 | import { StatusBar } from '@ionic-native/status-bar/ngx'; 7 | 8 | import { AppComponent } from './app.component'; 9 | 10 | describe('AppComponent', () => { 11 | let statusBarSpy, splashScreenSpy, platformReadySpy, platformSpy; 12 | 13 | beforeEach(async(() => { 14 | statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']); 15 | splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']); 16 | platformReadySpy = Promise.resolve(); 17 | platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy }); 18 | 19 | TestBed.configureTestingModule({ 20 | declarations: [AppComponent], 21 | schemas: [CUSTOM_ELEMENTS_SCHEMA], 22 | providers: [ 23 | { provide: StatusBar, useValue: statusBarSpy }, 24 | { provide: SplashScreen, useValue: splashScreenSpy }, 25 | { provide: Platform, useValue: platformSpy }, 26 | ], 27 | }).compileComponents(); 28 | })); 29 | 30 | it('should create the app', () => { 31 | const fixture = TestBed.createComponent(AppComponent); 32 | const app = fixture.debugElement.componentInstance; 33 | expect(app).toBeTruthy(); 34 | }); 35 | 36 | it('should initialize the app', async () => { 37 | TestBed.createComponent(AppComponent); 38 | expect(platformSpy.ready).toHaveBeenCalled(); 39 | await platformReadySpy; 40 | expect(statusBarSpy.styleDefault).toHaveBeenCalled(); 41 | expect(splashScreenSpy.hide).toHaveBeenCalled(); 42 | }); 43 | 44 | // TODO: add more tests! 45 | }); 46 | -------------------------------------------------------------------------------- /examples/ionic/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | import { Platform } from '@ionic/angular'; 4 | import { SplashScreen } from '@ionic-native/splash-screen/ngx'; 5 | import { StatusBar } from '@ionic-native/status-bar/ngx'; 6 | 7 | @Component({ 8 | selector: 'app-root', 9 | templateUrl: 'app.component.html', 10 | styleUrls: ['app.component.scss'], 11 | }) 12 | export class AppComponent { 13 | constructor( 14 | private platform: Platform, 15 | private splashScreen: SplashScreen, 16 | private statusBar: StatusBar, 17 | ) { 18 | this.initializeApp(); 19 | } 20 | 21 | initializeApp() { 22 | this.platform.ready().then(() => { 23 | this.statusBar.styleDefault(); 24 | this.splashScreen.hide(); 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/ionic/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { RouteReuseStrategy } from '@angular/router'; 4 | 5 | import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; 6 | import { SplashScreen } from '@ionic-native/splash-screen/ngx'; 7 | import { StatusBar } from '@ionic-native/status-bar/ngx'; 8 | 9 | import { AppComponent } from './app.component'; 10 | import { AppRoutingModule } from './app-routing.module'; 11 | 12 | @NgModule({ 13 | declarations: [AppComponent], 14 | entryComponents: [], 15 | imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule], 16 | providers: [ 17 | StatusBar, 18 | SplashScreen, 19 | { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, 20 | ], 21 | bootstrap: [AppComponent], 22 | }) 23 | export class AppModule {} 24 | -------------------------------------------------------------------------------- /examples/ionic/src/app/home/e3kit.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import { Observable, Subscriber } from 'rxjs'; 4 | import { EThree } from '@virgilsecurity/e3kit-browser/dist/browser.es'; 5 | 6 | interface GetJwtResponse { 7 | virgil_jwt: string; 8 | } 9 | 10 | @Injectable() 11 | export class E3KitService { 12 | private static API_URL = 'http://localhost:8080'; 13 | 14 | private httpClient: HttpClient; 15 | 16 | constructor(httpClient: HttpClient) { 17 | this.httpClient = httpClient; 18 | } 19 | 20 | runDemo(): Observable { 21 | return new Observable(observer => { 22 | this.runDemoCode(observer); 23 | }); 24 | } 25 | 26 | private async runDemoCode(observer: Subscriber) { 27 | const messages = new Array(); 28 | try { 29 | const alice = await EThree.initialize(this.createGetToken('alice')); 30 | const bob = await EThree.initialize(this.createGetToken('bob')); 31 | 32 | messages.push('Alice registers...'); 33 | observer.next(messages); 34 | await alice.register(); 35 | 36 | messages.push('Alice creates private key backup...'); 37 | observer.next(messages); 38 | await alice.backupPrivateKey('alice_pa$$w0rd'); 39 | 40 | messages.push('Bob registers...'); 41 | observer.next(messages); 42 | await bob.register(); 43 | 44 | messages.push('Bob creates private key backup...'); 45 | observer.next(messages); 46 | await bob.backupPrivateKey('bob_pa$$w0rd'); 47 | 48 | messages.push("Alice searches for Bob's card..."); 49 | observer.next(messages); 50 | const bobCard = await alice.findUsers(bob.identity); 51 | 52 | messages.push('Alice encrypts message for Bob...'); 53 | observer.next(messages); 54 | const encryptedForBob = await alice.encrypt('Hello Bob!', bobCard); 55 | 56 | messages.push("Bob searches for Alice's card..."); 57 | observer.next(messages); 58 | const aliceCard = await bob.findUsers(alice.identity); 59 | 60 | messages.push('Bob decrypts the message...'); 61 | observer.next(messages); 62 | const decryptedByBob = await bob.decrypt(encryptedForBob, aliceCard); 63 | 64 | messages.push('Decrypted message: ' + decryptedByBob); 65 | observer.next(messages); 66 | 67 | const groupId = 'AliceAndBobGroup'; 68 | 69 | messages.push('Alice creates a group with Bob...'); 70 | observer.next(messages); 71 | const aliceGroup = await alice.createGroup(groupId, bobCard); 72 | 73 | messages.push('Alice encrypts message for the group...'); 74 | observer.next(messages); 75 | const encryptedForGroup = await aliceGroup.encrypt('Hello group!'); 76 | 77 | messages.push('Bob loads the group by ID from the Cloud...'); 78 | observer.next(messages); 79 | const bobGroup = await bob.loadGroup(groupId, aliceCard); 80 | 81 | messages.push('Bob decrypts the group message...'); 82 | observer.next(messages); 83 | const decryptedByGroup = await bobGroup.decrypt(encryptedForGroup, aliceCard); 84 | 85 | messages.push('Decrypted group message: ' + decryptedByGroup); 86 | observer.next(messages); 87 | 88 | messages.push('Alice deletes group...'); 89 | observer.next(messages); 90 | await alice.deleteGroup(groupId); 91 | 92 | messages.push('Alice deletes private key backup...'); 93 | observer.next(messages); 94 | await alice.resetPrivateKeyBackup(); 95 | 96 | messages.push('Alice unregisters...'); 97 | observer.next(messages); 98 | await alice.unregister(); 99 | 100 | messages.push('Bob deletes private key backup...'); 101 | observer.next(messages); 102 | await bob.resetPrivateKeyBackup(); 103 | 104 | messages.push('Bob unregisters...'); 105 | observer.next(messages); 106 | await bob.unregister(); 107 | 108 | messages.push('Success!'); 109 | } catch (error) { 110 | messages.push(error.toString()); 111 | observer.next(messages); 112 | } finally { 113 | observer.complete(); 114 | } 115 | } 116 | 117 | private createGetToken(identity: string) { 118 | return () => new Promise((resolve, reject) => { 119 | this.httpClient.get(`${E3KitService.API_URL}/virgil-jwt?identity=${identity}`) 120 | .subscribe( 121 | (data: GetJwtResponse) => { 122 | resolve(data.virgil_jwt); 123 | }, 124 | error => { 125 | reject(error); 126 | }, 127 | ); 128 | }); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /examples/ionic/src/app/home/home.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { HttpClientModule } from '@angular/common/http'; 4 | import { IonicModule } from '@ionic/angular'; 5 | import { FormsModule } from '@angular/forms'; 6 | import { RouterModule } from '@angular/router'; 7 | 8 | import { HomePage } from './home.page'; 9 | import { E3KitService } from './e3kit.service'; 10 | 11 | @NgModule({ 12 | imports: [ 13 | CommonModule, 14 | FormsModule, 15 | IonicModule, 16 | HttpClientModule, 17 | RouterModule.forChild([ 18 | { 19 | path: '', 20 | component: HomePage, 21 | }, 22 | ]), 23 | ], 24 | declarations: [HomePage], 25 | providers: [E3KitService], 26 | }) 27 | export class HomePageModule {} 28 | -------------------------------------------------------------------------------- /examples/ionic/src/app/home/home.page.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Ionic Blank 5 | 6 | 7 | 8 | 9 | 10 |
11 |

Virgil E3Kit SDK + Webpack usage example

12 |

If all goes well, you should see messages printed below in a moment...

13 |
14 |

{{ message }}

15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /examples/ionic/src/app/home/home.page.scss: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/ionic/src/app/home/home.page.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import { IonicModule } from '@ionic/angular'; 3 | import { HttpClientTestingModule } from '@angular/common/http/testing'; 4 | import { HomePage } from './home.page'; 5 | import { E3KitService } from './e3kit.service'; 6 | 7 | describe('HomePage', () => { 8 | let component: HomePage; 9 | let fixture: ComponentFixture; 10 | 11 | beforeEach(async(() => { 12 | TestBed.configureTestingModule({ 13 | declarations: [HomePage], 14 | providers: [E3KitService], 15 | imports: [HttpClientTestingModule, IonicModule.forRoot()], 16 | }).compileComponents(); 17 | 18 | fixture = TestBed.createComponent(HomePage); 19 | component = fixture.componentInstance; 20 | fixture.detectChanges(); 21 | })); 22 | 23 | it('should create', () => { 24 | expect(component).toBeTruthy(); 25 | component.ngOnInit() 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /examples/ionic/src/app/home/home.page.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Observable } from 'rxjs'; 3 | 4 | import { E3KitService } from './e3kit.service'; 5 | 6 | @Component({ 7 | selector: 'app-home', 8 | templateUrl: 'home.page.html', 9 | styleUrls: ['home.page.scss'], 10 | }) 11 | export class HomePage implements OnInit { 12 | private e3kitService: E3KitService; 13 | 14 | private messages: Observable; 15 | 16 | constructor(e3kitService: E3KitService) { 17 | this.e3kitService = e3kitService; 18 | } 19 | 20 | ngOnInit() { 21 | this.messages = this.e3kitService.runDemo(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ionic/src/assets/icon/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VirgilSecurity/virgil-e3kit-js/13f597bb7377dc647376c701dc758e3d26aa172d/examples/ionic/src/assets/icon/favicon.png -------------------------------------------------------------------------------- /examples/ionic/src/assets/shapes.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/ionic/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /examples/ionic/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /examples/ionic/src/global.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * App Global CSS 3 | * ---------------------------------------------------------------------------- 4 | * Put style rules here that you want to apply globally. These styles are for 5 | * the entire app and not just one component. Additionally, this file can be 6 | * used as an entry point to import other CSS/Sass files to be included in the 7 | * output CSS. 8 | * For more information on global stylesheets, visit the documentation: 9 | * https://ionicframework.com/docs/layout/global-stylesheets 10 | */ 11 | 12 | /* Core CSS required for Ionic components to work properly */ 13 | @import "~@ionic/angular/css/core.css"; 14 | 15 | /* Basic CSS for apps built with Ionic */ 16 | @import "~@ionic/angular/css/normalize.css"; 17 | @import "~@ionic/angular/css/structure.css"; 18 | @import "~@ionic/angular/css/typography.css"; 19 | @import '~@ionic/angular/css/display.css'; 20 | 21 | /* Optional CSS utils that can be commented out */ 22 | @import "~@ionic/angular/css/padding.css"; 23 | @import "~@ionic/angular/css/float-elements.css"; 24 | @import "~@ionic/angular/css/text-alignment.css"; 25 | @import "~@ionic/angular/css/text-transformation.css"; 26 | @import "~@ionic/angular/css/flex-utils.css"; 27 | -------------------------------------------------------------------------------- /examples/ionic/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Ionic App 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /examples/ionic/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch(err => console.log(err)); 14 | -------------------------------------------------------------------------------- /examples/ionic/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | import './zone-flags.ts'; 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | 61 | import 'zone.js/dist/zone'; // Included with Angular CLI. 62 | 63 | /*************************************************************************************************** 64 | * APPLICATION IMPORTS 65 | */ 66 | 67 | (window as any).global = window; 68 | (window as any).process = {}; 69 | -------------------------------------------------------------------------------- /examples/ionic/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting, 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); 14 | // Then we find all the tests. 15 | const context = require.context('./', true, /\.spec\.ts$/); 16 | // And load the modules. 17 | context.keys().map(context); 18 | -------------------------------------------------------------------------------- /examples/ionic/src/theme/variables.scss: -------------------------------------------------------------------------------- 1 | // Ionic Variables and Theming. For more info, please see: 2 | // http://ionicframework.com/docs/theming/ 3 | 4 | /** Ionic CSS Variables **/ 5 | :root { 6 | /** primary **/ 7 | --ion-color-primary: #3880ff; 8 | --ion-color-primary-rgb: 56, 128, 255; 9 | --ion-color-primary-contrast: #ffffff; 10 | --ion-color-primary-contrast-rgb: 255, 255, 255; 11 | --ion-color-primary-shade: #3171e0; 12 | --ion-color-primary-tint: #4c8dff; 13 | 14 | /** secondary **/ 15 | --ion-color-secondary: #0cd1e8; 16 | --ion-color-secondary-rgb: 12, 209, 232; 17 | --ion-color-secondary-contrast: #ffffff; 18 | --ion-color-secondary-contrast-rgb: 255, 255, 255; 19 | --ion-color-secondary-shade: #0bb8cc; 20 | --ion-color-secondary-tint: #24d6ea; 21 | 22 | /** tertiary **/ 23 | --ion-color-tertiary: #7044ff; 24 | --ion-color-tertiary-rgb: 112, 68, 255; 25 | --ion-color-tertiary-contrast: #ffffff; 26 | --ion-color-tertiary-contrast-rgb: 255, 255, 255; 27 | --ion-color-tertiary-shade: #633ce0; 28 | --ion-color-tertiary-tint: #7e57ff; 29 | 30 | /** success **/ 31 | --ion-color-success: #10dc60; 32 | --ion-color-success-rgb: 16, 220, 96; 33 | --ion-color-success-contrast: #ffffff; 34 | --ion-color-success-contrast-rgb: 255, 255, 255; 35 | --ion-color-success-shade: #0ec254; 36 | --ion-color-success-tint: #28e070; 37 | 38 | /** warning **/ 39 | --ion-color-warning: #ffce00; 40 | --ion-color-warning-rgb: 255, 206, 0; 41 | --ion-color-warning-contrast: #ffffff; 42 | --ion-color-warning-contrast-rgb: 255, 255, 255; 43 | --ion-color-warning-shade: #e0b500; 44 | --ion-color-warning-tint: #ffd31a; 45 | 46 | /** danger **/ 47 | --ion-color-danger: #f04141; 48 | --ion-color-danger-rgb: 245, 61, 61; 49 | --ion-color-danger-contrast: #ffffff; 50 | --ion-color-danger-contrast-rgb: 255, 255, 255; 51 | --ion-color-danger-shade: #d33939; 52 | --ion-color-danger-tint: #f25454; 53 | 54 | /** dark **/ 55 | --ion-color-dark: #222428; 56 | --ion-color-dark-rgb: 34, 34, 34; 57 | --ion-color-dark-contrast: #ffffff; 58 | --ion-color-dark-contrast-rgb: 255, 255, 255; 59 | --ion-color-dark-shade: #1e2023; 60 | --ion-color-dark-tint: #383a3e; 61 | 62 | /** medium **/ 63 | --ion-color-medium: #989aa2; 64 | --ion-color-medium-rgb: 152, 154, 162; 65 | --ion-color-medium-contrast: #ffffff; 66 | --ion-color-medium-contrast-rgb: 255, 255, 255; 67 | --ion-color-medium-shade: #86888f; 68 | --ion-color-medium-tint: #a2a4ab; 69 | 70 | /** light **/ 71 | --ion-color-light: #f4f5f8; 72 | --ion-color-light-rgb: 244, 244, 244; 73 | --ion-color-light-contrast: #000000; 74 | --ion-color-light-contrast-rgb: 0, 0, 0; 75 | --ion-color-light-shade: #d7d8da; 76 | --ion-color-light-tint: #f5f6f9; 77 | } 78 | -------------------------------------------------------------------------------- /examples/ionic/src/zone-flags.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Prevents Angular change detection from 3 | * running with certain Web Component callbacks 4 | */ 5 | (window as any).__Zone_disable_customElements = true; 6 | -------------------------------------------------------------------------------- /examples/ionic/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "include": [ 8 | "src/**/*.ts" 9 | ], 10 | "exclude": [ 11 | "src/test.ts", 12 | "src/**/*.spec.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /examples/ionic/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "module": "esnext", 9 | "moduleResolution": "node", 10 | "emitDecoratorMetadata": true, 11 | "experimentalDecorators": true, 12 | "importHelpers": true, 13 | "target": "es2015", 14 | "typeRoots": [ 15 | "node_modules/@types" 16 | ], 17 | "lib": [ 18 | "es2018", 19 | "dom" 20 | ] 21 | }, 22 | "angularCompilerOptions": { 23 | "fullTemplateTypeCheck": true, 24 | "strictInjectionParameters": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/ionic/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/zone-flags.ts", 13 | "src/polyfills.ts" 14 | ], 15 | "include": [ 16 | "src/**/*.spec.ts", 17 | "src/**/*.d.ts" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /examples/ionic/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rulesDirectory": [ 4 | "codelyzer" 5 | ], 6 | "rules": { 7 | "array-type": false, 8 | "arrow-parens": false, 9 | "deprecation": { 10 | "severity": "warn" 11 | }, 12 | "import-blacklist": [ 13 | true, 14 | "rxjs/Rx" 15 | ], 16 | "interface-name": false, 17 | "max-classes-per-file": false, 18 | "max-line-length": [ 19 | true, 20 | 140 21 | ], 22 | "member-access": false, 23 | "member-ordering": [ 24 | true, 25 | { 26 | "order": [ 27 | "static-field", 28 | "instance-field", 29 | "static-method", 30 | "instance-method" 31 | ] 32 | } 33 | ], 34 | "no-consecutive-blank-lines": false, 35 | "no-console": [ 36 | true, 37 | "debug", 38 | "info", 39 | "time", 40 | "timeEnd", 41 | "trace" 42 | ], 43 | "no-empty": false, 44 | "no-inferrable-types": [ 45 | true, 46 | "ignore-params" 47 | ], 48 | "no-non-null-assertion": true, 49 | "no-redundant-jsdoc": true, 50 | "no-switch-case-fall-through": true, 51 | "no-use-before-declare": true, 52 | "no-var-requires": false, 53 | "object-literal-key-quotes": [ 54 | true, 55 | "as-needed" 56 | ], 57 | "object-literal-sort-keys": false, 58 | "ordered-imports": false, 59 | "quotemark": [ 60 | true, 61 | "single" 62 | ], 63 | "trailing-comma": false, 64 | "no-output-on-prefix": true, 65 | "no-inputs-metadata-property": true, 66 | "no-host-metadata-property": true, 67 | "no-input-rename": true, 68 | "no-output-rename": true, 69 | "use-lifecycle-interface": true, 70 | "use-pipe-transform-interface": true, 71 | "one-variable-per-declaration": false, 72 | "component-class-suffix": [true, "Page", "Component"], 73 | "directive-class-suffix": true, 74 | "directive-selector": [ 75 | true, 76 | "attribute", 77 | "app", 78 | "camelCase" 79 | ], 80 | "component-selector": [ 81 | true, 82 | "element", 83 | "app", 84 | "page", 85 | "kebab-case" 86 | ] 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /examples/node/.env.example: -------------------------------------------------------------------------------- 1 | API_URL=http://localhost:8080 2 | -------------------------------------------------------------------------------- /examples/node/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit SDK for Node.js 2 | Sample project demonstrating the usage of `@virgilsecurity/e3kit-node`. 3 | 4 | ## Get Started 5 | 1. Configure and start the server in the `examples/backend` folder following instructions in `../examples/backend/README.md`. 6 | 2. Install dependencies with [Yarn](https://yarnpkg.com/en/) 7 | ```sh 8 | yarn install 9 | ``` 10 | > You need to use Yarn because we use [Workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) in this repository :) 11 | 3. Create `.env` file. Use `.env.example` as a reference. 12 | 4. Run the following command to start the demo 13 | ```sh 14 | yarn start 15 | ``` 16 | > ⚠️ If you see `Cannot find module '@virgilsecurity/e3kit-node'` Error, make sure you did `yarn install` in the root folder 17 | 18 | ## License 19 | This library is released under the [3-clause BSD License](LICENSE). 20 | 21 | ## Support 22 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 23 | 24 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 25 | 26 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 27 | -------------------------------------------------------------------------------- /examples/node/index.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | const querystring = require('querystring'); 3 | 4 | const { EThree } = require('@virgilsecurity/e3kit-node'); 5 | const dotenv = require('dotenv'); 6 | 7 | console.log('Virgil E3Kit SDK + Node.js usage example'); 8 | console.log('If all goes well, you should see messages printed below in a moment...'); 9 | 10 | dotenv.config(); 11 | const API_URL = process.env.API_URL; 12 | 13 | const getJson = url => 14 | new Promise((resolve, reject) => { 15 | const request = http.get(url, response => { 16 | let data = ''; 17 | response.on('data', chunk => { 18 | data += chunk; 19 | }); 20 | response.on('end', () => { 21 | resolve(JSON.parse(data)); 22 | }); 23 | }); 24 | request.on('error', error => { 25 | reject(error); 26 | }); 27 | }); 28 | 29 | const createGetToken = identity => async () => { 30 | const query = querystring.stringify({ identity }); 31 | const { virgil_jwt: virgilJwt } = await getJson(`${API_URL}/virgil-jwt?${query}`); 32 | return virgilJwt; 33 | }; 34 | 35 | (async () => { 36 | try { 37 | const alice = await EThree.initialize(createGetToken(`alice-${Math.random()}`), { 38 | apiUrl: process.env.VIRGIL_API_URL, 39 | groupStorageName: '.virgil-group-storage-alice', 40 | }); 41 | const bob = await EThree.initialize(createGetToken(`bob-${Math.random()}`), { 42 | apiUrl: process.env.VIRGIL_API_URL, 43 | }); 44 | 45 | console.log('Alice registers...'); 46 | await alice.register(); 47 | 48 | console.log('Alice creates private key backup...'); 49 | await alice.backupPrivateKey('alice_pa$$w0rd'); 50 | 51 | console.log('Bob registers...'); 52 | await bob.register(); 53 | 54 | console.log('Bob creates private key backup...'); 55 | await bob.backupPrivateKey('bob_pa$$w0rd'); 56 | 57 | console.log("Alice searches for Bob's card..."); 58 | const bobCard = await alice.findUsers(bob.identity); 59 | 60 | console.log('Alice encrypts message for Bob...'); 61 | const encryptedForBob = await alice.encrypt('Hello Bob!', bobCard); 62 | 63 | console.log("Bob searches for Alice's card..."); 64 | const aliceCard = await bob.findUsers(alice.identity); 65 | 66 | console.log('Bob decrypts the message...'); 67 | const decryptedByBob = await bob.decrypt(encryptedForBob, aliceCard); 68 | 69 | console.log('Decrypted message: ' + decryptedByBob); 70 | 71 | const groupId = 'AliceAndBobGroup'; 72 | 73 | console.log('Alice creates a group with Bob...'); 74 | const aliceGroup = await alice.createGroup(groupId, bobCard); 75 | 76 | console.log('Alice encrypts message for the group...'); 77 | const encryptedForGroup = await aliceGroup.encrypt('Hello group!'); 78 | 79 | console.log('Bob loads the group by ID from the Cloud...'); 80 | const bobGroup = await bob.loadGroup(groupId, aliceCard); 81 | 82 | console.log('Bob decrypts the group message...'); 83 | const decryptedByGroup = await bobGroup.decrypt(encryptedForGroup, aliceCard); 84 | 85 | console.log('Decrypted group message: ' + decryptedByGroup); 86 | 87 | console.log('Alice deletes group...'); 88 | await alice.deleteGroup(groupId); 89 | 90 | console.log('Alice deletes private key backup...'); 91 | await alice.resetPrivateKeyBackup(); 92 | 93 | console.log('Alice unregisters...'); 94 | await alice.unregister(); 95 | 96 | console.log('Bob deletes private key backup...'); 97 | await bob.resetPrivateKeyBackup(); 98 | 99 | console.log('Bob unregisters...'); 100 | await bob.unregister(); 101 | 102 | console.log('Success!'); 103 | } catch (error) { 104 | console.log(error.toString()); 105 | } 106 | })(); 107 | -------------------------------------------------------------------------------- /examples/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/example-node", 3 | "version": "2.4.5", 4 | "description": "Virgil E3Kit SDK + Node.js usage example", 5 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/example-node", 6 | "author": "Virgil Security Inc. ", 7 | "license": "BSD-3-Clause", 8 | "private": true, 9 | "scripts": { 10 | "start": "node index.js" 11 | }, 12 | "dependencies": { 13 | "@virgilsecurity/e3kit-node": "^2.4.5", 14 | "dotenv": "^8.1.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/umd/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit SDK for Browsers 2 | Sample project demonstrating the usage of `@virgilsecurity/e3kit-browser` UMD build. 3 | 4 | ## Get Started 5 | 1. Configure and start the server in the `examples/backend` folder following instructions in `../examples/backend/README.md`. 6 | 2. Install dependencies with [Yarn](https://yarnpkg.com/en/). 7 | ```sh 8 | yarn install 9 | ``` 10 | > You need to use Yarn because we use [Workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) in this repository :) 11 | 3. Make sure that `API_URL` value in `src/index.html` is correct. 12 | 4. Run the following command to start the demo(it simply serves the `src` folder) 13 | ```sh 14 | yarn start 15 | ``` 16 | 17 | ## License 18 | This library is released under the [3-clause BSD License](LICENSE). 19 | 20 | ## Support 21 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 22 | 23 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 24 | 25 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 26 | -------------------------------------------------------------------------------- /examples/umd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/example-umd", 3 | "version": "2.4.5", 4 | "description": "Virgil E3Kit SDK UMD example", 5 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/example-umd", 6 | "author": "Virgil Security Inc. ", 7 | "license": "BSD-3-Clause", 8 | "private": true, 9 | "scripts": { 10 | "start": "serve src" 11 | }, 12 | "devDependencies": { 13 | "serve": "^11.2.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/webpack/.env.example: -------------------------------------------------------------------------------- 1 | API_URL=http://localhost:8080 2 | -------------------------------------------------------------------------------- /examples/webpack/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /examples/webpack/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit SDK for Browsers 2 | Sample project demonstrating the usage of `@virgilsecurity/e3kit-browser`. 3 | 4 | ## Get Started 5 | 1. Configure and start the server in the `examples/backend` folder following instructions in `../examples/backend/README.md`. 6 | 2. Install dependencies with [Yarn](https://yarnpkg.com/en/) 7 | ```sh 8 | yarn install 9 | ``` 10 | > You need to use Yarn because we use [Workspaces](https://yarnpkg.com/lang/en/docs/workspaces/) in this repository :) 11 | 3. Create `.env` file. Use `.env.example` as a reference 12 | 4. Run the following command to start the demo 13 | ```sh 14 | yarn start 15 | ``` 16 | > ⚠️ If you see `Cannot find module '@virgilsecurity/e3kit-browser'` Error, make sure you did `yarn install` in the root folder 17 | 18 | ## License 19 | This library is released under the [3-clause BSD License](LICENSE). 20 | 21 | ## Support 22 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 23 | 24 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 25 | 26 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 27 | -------------------------------------------------------------------------------- /examples/webpack/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Virgil E3Kit SDK + Webpack 8 | 9 | 10 |

Virgil E3Kit SDK + Webpack usage example

11 |

If all goes well, you should see messages printed below in a moment...

12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/webpack/index.js: -------------------------------------------------------------------------------- 1 | import { EThree } from '@virgilsecurity/e3kit-browser'; 2 | 3 | const createGetToken = identity => async () => { 4 | const response = await fetch(`${process.env.API_URL}/virgil-jwt?identity=${identity}`); 5 | const { virgil_jwt: virgilJwt } = await response.json(); 6 | return virgilJwt; 7 | }; 8 | 9 | const report = message => { 10 | const paragraph = document.createElement('p'); 11 | const textNode = document.createTextNode(message); 12 | paragraph.appendChild(textNode); 13 | document.body.appendChild(paragraph); 14 | }; 15 | 16 | (async () => { 17 | try { 18 | const alice = await EThree.initialize(createGetToken(`alice-${Math.random()}`)); 19 | const bob = await EThree.initialize(createGetToken(`bob-${Math.random()}`)); 20 | 21 | report('Alice registers...'); 22 | await alice.register(); 23 | 24 | report('Alice creates private key backup...'); 25 | await alice.backupPrivateKey('alice_pa$$w0rd'); 26 | 27 | report('Bob registers...'); 28 | await bob.register(); 29 | 30 | report('Bob creates private key backup...'); 31 | await bob.backupPrivateKey('bob_pa$$w0rd'); 32 | 33 | report("Alice searches for Bob's card..."); 34 | const bobCard = await alice.findUsers(bob.identity); 35 | 36 | report('Alice encrypts message for Bob...'); 37 | const encryptedForBob = await alice.encrypt('Hello Bob!', bobCard); 38 | 39 | report("Bob searches for Alice's card..."); 40 | const aliceCard = await bob.findUsers(alice.identity); 41 | 42 | report('Bob decrypts the message...'); 43 | const decryptedByBob = await bob.decrypt(encryptedForBob, aliceCard); 44 | 45 | report('Decrypted message: ' + decryptedByBob); 46 | 47 | const groupId = 'AliceAndBobGroup'; 48 | 49 | report('Alice creates a group with Bob...'); 50 | const aliceGroup = await alice.createGroup(groupId, bobCard); 51 | 52 | report('Alice encrypts message for the group...'); 53 | const encryptedForGroup = await aliceGroup.encrypt('Hello group!'); 54 | 55 | report('Bob loads the group by ID from the Cloud...'); 56 | const bobGroup = await bob.loadGroup(groupId, aliceCard); 57 | 58 | report('Bob decrypts the group message...'); 59 | const decryptedByGroup = await bobGroup.decrypt(encryptedForGroup, aliceCard); 60 | 61 | report('Decrypted group message: ' + decryptedByGroup); 62 | 63 | report('Alice deletes group...'); 64 | await alice.deleteGroup(groupId); 65 | 66 | report('Alice deletes private key backup...'); 67 | await alice.resetPrivateKeyBackup(); 68 | 69 | report('Alice unregisters...'); 70 | await alice.unregister(); 71 | 72 | report('Bob deletes private key backup...'); 73 | await bob.resetPrivateKeyBackup(); 74 | 75 | report('Bob unregisters...'); 76 | await bob.unregister(); 77 | 78 | report('Success!'); 79 | } catch (error) { 80 | report(error.toString()); 81 | } 82 | })(); 83 | -------------------------------------------------------------------------------- /examples/webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/example-webpack", 3 | "version": "2.4.5", 4 | "description": "Virgil E3Kit SDK + Webpack usage example", 5 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/example-webpack", 6 | "author": "Virgil Security Inc. ", 7 | "license": "BSD-3-Clause", 8 | "private": true, 9 | "scripts": { 10 | "start": "webpack-dev-server", 11 | "build": "webpack" 12 | }, 13 | "dependencies": { 14 | "@virgilsecurity/e3kit-browser": "^2.4.5" 15 | }, 16 | "devDependencies": { 17 | "dotenv": "^8.1.0", 18 | "file-loader": "^4.2.0", 19 | "html-webpack-plugin": "^3.2.0", 20 | "webpack": "^4.41.0", 21 | "webpack-cli": "^3.3.9", 22 | "webpack-dev-server": "^3.8.1" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/webpack/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const dotenv = require('dotenv'); 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const { DefinePlugin } = require('webpack'); 6 | 7 | dotenv.config(); 8 | 9 | module.exports = { 10 | mode: 'development', 11 | entry: path.join(__dirname, 'index.js'), 12 | module: { 13 | rules: [ 14 | { 15 | test: /\.wasm$/, 16 | type: 'javascript/auto', 17 | loader: 'file-loader', 18 | }, 19 | ], 20 | }, 21 | plugins: [ 22 | new DefinePlugin({ 23 | 'process.env.API_URL': JSON.stringify(process.env.API_URL), 24 | }), 25 | new HtmlWebpackPlugin({ template: path.join(__dirname, 'index.html') }), 26 | ], 27 | }; 28 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "version": "8.0.2" 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "private": true, 4 | "scripts": { 5 | "lint": "eslint '**/*.{js,ts}'", 6 | "test": "lerna run test --parallel --ignore create-react-app --ignore ionic", 7 | "prepare": "lerna run prepare --stream", 8 | "docs": "node scripts/generate-docs.js" 9 | }, 10 | "devDependencies": { 11 | "@typescript-eslint/eslint-plugin": "^5.40.0", 12 | "@typescript-eslint/parser": "^5.40.0", 13 | "ejs": "^3.0.1", 14 | "eslint": "^8.25.0", 15 | "eslint-config-prettier": "^8.5.0", 16 | "eslint-plugin-no-cyrillic-string": "^1.0.5", 17 | "eslint-plugin-prettier": "^4.2.1", 18 | "eslint-plugin-simple-import-sort": "^8.0.0", 19 | "husky": "^4.2.1", 20 | "lerna": "^8.0.2", 21 | "lerna-update-wizard": "^1.1.2", 22 | "lint-staged": "^10.0.2", 23 | "prettier": "^2.7.1", 24 | "typedoc": "^0.23.16", 25 | "typescript": "^4.8.4" 26 | }, 27 | "workspaces": { 28 | "packages": [ 29 | "packages/*" 30 | ], 31 | "examples": [ 32 | "examples/*" 33 | ], 34 | "nohoist": [ 35 | "**/react-native", 36 | "**/react-native/**", 37 | "**/abstract-leveldown", 38 | "**/webpack", 39 | "**/webpack-dev-server" 40 | ] 41 | }, 42 | "version": "2.5.2" 43 | } 44 | -------------------------------------------------------------------------------- /packages/e3kit-base/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'subleveldown' { 2 | import { LevelUp } from 'levelup'; 3 | import { AbstractOptions } from 'abstract-leveldown'; 4 | 5 | export default function(db: LevelUp, name: string, options?: AbstractOptions): LevelUp; 6 | } 7 | -------------------------------------------------------------------------------- /packages/e3kit-base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/e3kit-base", 3 | "version": "3.0.7", 4 | "description": "End-to-end encryption with multiple device support powered by Virgil Security", 5 | "main": "./dist/e3kit-base.cjs.js", 6 | "module": "./dist/e3kit-base.es.js", 7 | "typings": "./dist/types/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "declarations.d.ts" 11 | ], 12 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-base", 13 | "author": "Virgil Security Inc. ", 14 | "license": "BSD-3-Clause", 15 | "scripts": { 16 | "build": "rollup -c", 17 | "clean": "rimraf .rpt2_cache dist", 18 | "prepare": "npm run clean && npm run build", 19 | "ts-mocha": "ts-mocha -p tsconfig.spec.json src/__tests__/*.spec.ts" 20 | }, 21 | "dependencies": { 22 | "@types/abstract-leveldown": "^7.2.0", 23 | "@types/expect": "^24.3.0", 24 | "@types/levelup": "^5.1.2", 25 | "@virgilsecurity/crypto-types": "^1.1.1", 26 | "@virgilsecurity/keyknox": "^1.0.3", 27 | "@virgilsecurity/sdk-crypto": "^2.0.0", 28 | "abstract-leveldown": "^7.2.0", 29 | "levelup": "^5.1.1", 30 | "subleveldown": "^6.0.1", 31 | "virgil-pythia": "^1.0.2", 32 | "virgil-sdk": "^6.1.2" 33 | }, 34 | "devDependencies": { 35 | "@rollup/plugin-typescript": "^11.1.6", 36 | "@types/chai": "^4.3.3", 37 | "@types/chai-as-promised": "^7.1.5", 38 | "@types/memdown": "^3.0.0", 39 | "@types/mocha": "^10.0.0", 40 | "@types/sinon": "^10.0.13", 41 | "chai": "^4.3.6", 42 | "chai-as-promised": "^7.1.1", 43 | "memdown": "^5.1.0", 44 | "rimraf": "^3.0.2", 45 | "rollup": "^3.1.0", 46 | "rollup-plugin-license": "^2.8.1", 47 | "sinon": "^14.0.1", 48 | "ts-mocha": "^10.0.0", 49 | "ts-node": "^10.9.1", 50 | "typescript": "^5.4.5", 51 | "virgil-crypto": "^5.1.2" 52 | }, 53 | "publishConfig": { 54 | "access": "public" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/e3kit-base/rollup.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const license = require('rollup-plugin-license'); 4 | const typescript = require('@rollup/plugin-typescript'); 5 | 6 | const packageJson = require('./package.json'); 7 | 8 | const FORMAT = { 9 | CJS: 'cjs', 10 | ES: 'es', 11 | }; 12 | 13 | const sourcePath = path.join(__dirname, 'src'); 14 | const outputPath = path.join(__dirname, 'dist'); 15 | 16 | const createEntry = (format) => ({ 17 | external: Object.keys(packageJson.dependencies), 18 | input: path.join(sourcePath, 'index.ts'), 19 | output: { 20 | format, 21 | file: path.join(outputPath, `e3kit-base.${format}.js`), 22 | }, 23 | plugins: [ 24 | typescript(), 25 | license({ 26 | banner: { 27 | content: { 28 | file: path.join(__dirname, '..', '..', 'LICENSE'), 29 | }, 30 | }, 31 | }), 32 | ], 33 | }); 34 | 35 | module.exports = [createEntry(FORMAT.CJS), createEntry(FORMAT.ES)]; 36 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/array.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @hidden 3 | */ 4 | export function hasDuplicates(array: T[]) { 5 | return new Set(array).size !== array.length; 6 | } 7 | 8 | /** 9 | * @hidden 10 | */ 11 | export function getObjectValues(obj: { [x: string]: T }): T[] { 12 | if (Object.values) return Object.values(obj); 13 | return Object.keys(obj).map(function(e) { 14 | return obj[e]; 15 | }); 16 | } 17 | 18 | /** 19 | * @hidden 20 | * 21 | * Splits the `array` into separate chunks of the specified `size` 22 | * 23 | * @param array 24 | * @param size 25 | */ 26 | export function chunkArray(array: T[], size: number): T[][] { 27 | size = Math.max(size, 0); 28 | const length = array == null ? 0 : array.length; 29 | if (!length || size < 1) { 30 | return []; 31 | } 32 | let index = 0; 33 | let resIndex = 0; 34 | const result = Array(Math.ceil(length / size)); 35 | 36 | while (index < length) { 37 | result[resIndex++] = array.slice(index, (index += size)); 38 | } 39 | 40 | return result; 41 | } 42 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/brainkey.ts: -------------------------------------------------------------------------------- 1 | import { BrainKey, PythiaClient } from 'virgil-pythia'; 2 | import { VirgilAgent } from 'virgil-sdk'; 3 | 4 | import { IKeyPair, ICrypto, IBrainKeyCrypto, IAccessTokenProvider } from './types'; 5 | 6 | const BRAIN_KEY_RATE_LIMIT_DELAY = 2000; 7 | const BRAIN_KEY_THROTTLING_ERROR_CODE = 60007; 8 | 9 | /** 10 | * @hidden 11 | */ 12 | export type BrainkeyOptions = { 13 | virgilCrypto: ICrypto; 14 | pythiaCrypto: IBrainKeyCrypto; 15 | accessTokenProvider: IAccessTokenProvider; 16 | apiUrl?: string; 17 | }; 18 | 19 | /** 20 | * @hidden 21 | */ 22 | export async function generateBrainPair(pwd: string, options: BrainkeyOptions): Promise { 23 | const pythiaClient = new PythiaClient( 24 | options.accessTokenProvider, 25 | options.apiUrl, 26 | // eslint-disable-next-line @typescript-eslint/no-non-null-assertion 27 | new VirgilAgent( 28 | process.env.__VIRGIL_PRODUCT_NAME__!, 29 | process.env.__VIRGIL_PRODUCT_VERSION__!, 30 | ), 31 | ); 32 | const brainKey = new BrainKey({ 33 | pythiaClient, 34 | crypto: options.virgilCrypto, 35 | brainKeyCrypto: options.pythiaCrypto, 36 | }); 37 | return await brainKey.generateKeyPair(pwd).catch((e: Error & { code?: number }) => { 38 | if (typeof e === 'object' && e.code === BRAIN_KEY_THROTTLING_ERROR_CODE) { 39 | const promise = new Promise((resolve, reject) => { 40 | const repeat = () => 41 | brainKey 42 | .generateKeyPair(pwd) 43 | .then(resolve) 44 | .catch(reject); 45 | setTimeout(repeat, BRAIN_KEY_RATE_LIMIT_DELAY); 46 | }); 47 | return promise as Promise; 48 | } 49 | throw e; 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @hidden 3 | */ 4 | export const DEFAULT_STORAGE_NAME = '.virgil-local-storage'; 5 | 6 | /** 7 | * @hidden 8 | */ 9 | export const DEFAULT_GROUP_STORAGE_NAME = '.virgil-group-storage'; 10 | 11 | /** 12 | * @hidden 13 | */ 14 | export const DEFAULT_API_URL = 'https://api.virgilsecurity.com'; 15 | 16 | /** 17 | * @hidden 18 | */ 19 | export const MAX_IDENTITIES_TO_SEARCH = 50; 20 | 21 | /** 22 | * @hidden 23 | */ 24 | export const CLOUD_GROUP_SESSIONS_ROOT = 'group-sessions'; 25 | 26 | /** 27 | * @hidden 28 | */ 29 | export const VALID_GROUP_PARTICIPANT_COUNT_RANGE: [number, number] = [1, 100]; 30 | 31 | /** 32 | * @hidden 33 | */ 34 | export const MAX_EPOCHS_IN_GROUP_SESSION = 50; 35 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/index.ts: -------------------------------------------------------------------------------- 1 | export { AbstractEThree } from './AbstractEThree'; 2 | export * from './constants'; 3 | export * from './errors'; 4 | export { PrivateKeyLoader } from './PrivateKeyLoader'; 5 | export { 6 | NodeBuffer, 7 | Data, 8 | StringEncoding, 9 | IKeyPair, 10 | IPrivateKey, 11 | IPublicKey, 12 | ICrypto, 13 | ICardCrypto, 14 | IBrainKeyCrypto, 15 | IAccessTokenProvider, 16 | ICard, 17 | IKeyEntryStorage, 18 | IKeyEntry, 19 | EThreeInitializeOptions, 20 | EThreeCtorOptions, 21 | LookupResult, 22 | EncryptPublicKeyArg, 23 | FindUsersResult, 24 | Ticket, 25 | GroupInfo, 26 | RawGroup, 27 | } from './types'; 28 | export { GroupLocalStorage } from './GroupLocalStorage'; 29 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/log.ts: -------------------------------------------------------------------------------- 1 | export function warn(message: string) { 2 | if (typeof console !== 'undefined' && typeof console.warn === 'function') { 3 | console.warn(message); 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/typeguards.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | import { ICard, FindUsersResult, LookupResult } from './types'; 3 | import { getObjectValues } from './array'; 4 | 5 | /** 6 | * @hidden 7 | */ 8 | export const isArray = (val: any): val is Array => { 9 | return Array.isArray(val); 10 | }; 11 | 12 | /** 13 | * @hidden 14 | */ 15 | export const isString = (val: any): val is string => { 16 | return typeof val === 'string'; 17 | }; 18 | 19 | /** 20 | * @hidden 21 | */ 22 | export function isObject(obj: any) { 23 | return typeof obj === 'object' && obj !== null; 24 | } 25 | 26 | /** 27 | * @hidden 28 | */ 29 | export function isVirgilCard(obj: any): obj is ICard { 30 | return isObject(obj) && 'identity' in obj && 'publicKey' in obj; 31 | } 32 | 33 | /** 34 | * @hidden 35 | */ 36 | export function isFindUsersResult(obj: any): obj is FindUsersResult { 37 | if (!isObject(obj)) return false; 38 | 39 | const values = getObjectValues(obj); 40 | if (values.length === 0) return false; 41 | 42 | return values.every(val => isVirgilCard(val)); 43 | } 44 | 45 | /** 46 | * @hidden 47 | */ 48 | export function isLookupResult( 49 | obj: any, 50 | isPublicKeyFn: (obj: any) => boolean, 51 | ): obj is LookupResult { 52 | if (!isObject(obj)) return false; 53 | 54 | const values = getObjectValues(obj); 55 | if (values.length === 0) return false; 56 | 57 | return values.every(val => isPublicKeyFn(val)); 58 | } 59 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/types.ts: -------------------------------------------------------------------------------- 1 | export type NodeBuffer = import('@virgilsecurity/crypto-types').NodeBuffer; 2 | export type Data = import('@virgilsecurity/crypto-types').Data; 3 | export type StringEncoding = import('@virgilsecurity/crypto-types').StringEncoding; 4 | export type IKeyPair = import('@virgilsecurity/crypto-types').IKeyPair; 5 | export type IPrivateKey = import('@virgilsecurity/crypto-types').IPrivateKey; 6 | export type IPublicKey = import('@virgilsecurity/crypto-types').IPublicKey; 7 | export type ICrypto = import('@virgilsecurity/crypto-types').ICrypto; 8 | export type ICardCrypto = import('@virgilsecurity/crypto-types').ICardCrypto; 9 | export type IBrainKeyCrypto = import('@virgilsecurity/crypto-types').IBrainKeyCrypto; 10 | export type IGroupSession = import('@virgilsecurity/crypto-types').IGroupSession; 11 | export type IGroupSessionMessageInfo = import('@virgilsecurity/crypto-types').IGroupSessionMessageInfo; 12 | 13 | export type IAccessTokenProvider = import('virgil-sdk').IAccessTokenProvider; 14 | export type IKeyEntryStorage = import('virgil-sdk').IKeyEntryStorage; 15 | export type ICard = import('virgil-sdk').ICard; 16 | export type IKeyEntry = import('virgil-sdk').IKeyEntry; 17 | 18 | export interface EThreeInitializeOptions { 19 | /** 20 | * Implementation of IKeyEntryStorage. Used IndexedDB Key Storage from 21 | * [Virgil SDK](https://github.com/virgilsecurity/virgil-sdk-javascript) by default. 22 | */ 23 | keyEntryStorage?: IKeyEntryStorage; 24 | /** 25 | * Url of the Card Services. Used for development purposes. 26 | */ 27 | apiUrl?: string; 28 | /** 29 | * Indicates whether to use old algorithm to calculate keypair identifiers. 30 | */ 31 | useSha256Identifiers?: boolean; 32 | /** 33 | * Name of the key storage. Default `.virgil-local-storage`. 34 | */ 35 | storageName?: string; 36 | 37 | /** 38 | * Name of the group storage. Default `.virgil-group-storage`. 39 | */ 40 | groupStorageName?: string; 41 | 42 | /** 43 | * Key type that will be used for key generation. Default is ED25519. 44 | */ 45 | keyPairType?: any; 46 | } 47 | 48 | /** 49 | * @hidden 50 | */ 51 | export interface EThreeCtorOptions extends EThreeInitializeOptions { 52 | /** 53 | * Implementation of IAccessTokenProvider from [Virgil SDK](https://github.com/virgilsecurity/virgil-sdk-javascript); 54 | */ 55 | accessTokenProvider: IAccessTokenProvider; 56 | } 57 | 58 | /** 59 | * Dictionary returned from lookupPublicKey method 60 | * 61 | * @deprecated and will be removed in next major release. 62 | */ 63 | export type LookupResult = { 64 | [identity: string]: IPublicKey; 65 | }; 66 | 67 | /** 68 | * Argument for encrypt function can be single IPublicKey or LookupResult 69 | * 70 | * @deprecated and will be removed in next major release. 71 | */ 72 | export type EncryptPublicKeyArg = LookupResult | IPublicKey; 73 | 74 | /** 75 | * Dictionary returned from {@link Ethree.findUsers} method when searching for multiple users. 76 | */ 77 | export type FindUsersResult = { 78 | [identity: string]: ICard; 79 | }; 80 | 81 | export interface Ticket { 82 | groupSessionMessage: IGroupSessionMessageInfo; 83 | participants: string[]; 84 | } 85 | 86 | export interface GroupInfo { 87 | initiator: string; 88 | } 89 | 90 | export interface RawGroup { 91 | info: GroupInfo; 92 | tickets: Ticket[]; 93 | } 94 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/utils/card.ts: -------------------------------------------------------------------------------- 1 | import { ICard, FindUsersResult } from '../types'; 2 | import { isVirgilCard, isFindUsersResult } from '../typeguards'; 3 | import { getObjectValues } from '../array'; 4 | import { isValidDate } from './date'; 5 | 6 | /** 7 | * @hidden 8 | */ 9 | export function getCardActiveAtMoment(card: ICard, activeAt?: Date | number) { 10 | if (!activeAt) { 11 | return card; 12 | } 13 | 14 | const activeAtDate = new Date(activeAt); 15 | if (!isValidDate(activeAtDate)) { 16 | throw new TypeError( 17 | 'Cannot get active card. Second argument, if provided, must be a Date or a timestamp', 18 | ); 19 | } 20 | 21 | let actualCard: ICard | undefined = card; 22 | while (actualCard && actualCard.createdAt > activeAt) { 23 | actualCard = actualCard.previousCard; 24 | } 25 | 26 | if (!actualCard) { 27 | throw new Error( 28 | 'The given sender Virgil Card is newer than the encrypted data.' + 29 | 'This may happen if they un-registered and registered again with the same identity.' + 30 | 'Try loading their Virgil Card by its ID.', 31 | ); 32 | } 33 | 34 | return actualCard; 35 | } 36 | 37 | /** 38 | * @hidden 39 | */ 40 | export const getCardsArray = (cardOrFindUsersResult: ICard | FindUsersResult) => { 41 | if (isVirgilCard(cardOrFindUsersResult)) { 42 | return [cardOrFindUsersResult]; 43 | } 44 | if (isFindUsersResult(cardOrFindUsersResult)) { 45 | return getObjectValues(cardOrFindUsersResult); 46 | } 47 | return []; 48 | }; 49 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/utils/date.ts: -------------------------------------------------------------------------------- 1 | const DATE_TAG = '[object Date]'; 2 | const toString = Object.prototype.toString; 3 | 4 | /** 5 | * @hidden 6 | */ 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | export function isValidDate(date: any): date is Date { 9 | return date && toString.call(date) === DATE_TAG && !isNaN(date); 10 | } 11 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/utils/number.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @hidden 3 | */ 4 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 5 | export const isInteger = (val: any): val is number => { 6 | if (Number.isInteger) return Number.isInteger(val); 7 | return typeof val === 'number' && isFinite(val) && Math.floor(val) === val; 8 | }; 9 | 10 | /** 11 | * @hidden 12 | */ 13 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 14 | export const isSafeInteger = (val: any): val is number => { 15 | if (Number.isSafeInteger) return Number.isSafeInteger(val); 16 | return isInteger(val) && Math.abs(val) <= Number.MAX_SAFE_INTEGER; 17 | }; 18 | 19 | /** 20 | * @hidden 21 | */ 22 | export const isNumberInRange = (num: number, range: [number, number]) => { 23 | return typeof num === 'number' && num >= range[0] && num <= range[1]; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/e3kit-base/src/utils/set.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @hidden 3 | */ 4 | export const setDifference = (a: Set, b: Set) => { 5 | return new Set([...a].filter(it => !b.has(it))); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/e3kit-base/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/types", 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitReturns": false, 8 | "strictPropertyInitialization": false, 9 | "noFallthroughCasesInSwitch": true, 10 | "sourceMap": true, 11 | "declaration": true, 12 | "declarationDir": "./dist/types", 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "noImplicitAny": true, 16 | "moduleResolution": "node", 17 | "importHelpers": true, 18 | "esModuleInterop": true, 19 | "target": "es2020", 20 | "module": "es2015", 21 | "lib": [ 22 | "es2018", 23 | "dom" 24 | ] 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /packages/e3kit-base/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/types", 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitReturns": false, 8 | "strictPropertyInitialization": false, 9 | "noFallthroughCasesInSwitch": true, 10 | "sourceMap": true, 11 | "declaration": true, 12 | "declarationDir": "./dist/types", 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "noImplicitAny": true, 16 | "moduleResolution": "node", 17 | "importHelpers": true, 18 | "esModuleInterop": true, 19 | "target": "es2020", 20 | "module": "commonjs", 21 | "lib": [ 22 | "es2018", 23 | "dom" 24 | ] 25 | }, 26 | } 27 | -------------------------------------------------------------------------------- /packages/e3kit-browser/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit SDK for Browsers 2 | Virgil E3Kit SDK is also available on other platforms: 3 | - [Node.js](https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-node) 4 | - [React Native](https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-native) 5 | 6 | > E3Kit's underlying crypto library is compiled to WebAssembly. You need to make sure your target browsers [support WebAssembly](https://caniuse.com/#search=WebAssembly). We also have asm.js fallback for environments that don't support WebAssembly. The downside of it is much slower download and execution time. 7 | 8 | ## Install 9 | - npm: 10 | ```sh 11 | npm install @virgilsecurity/e3kit-browser 12 | ``` 13 | - yarn: 14 | ```sh 15 | yarn add @virgilsecurity/e3kit-browser 16 | ``` 17 | - UMD: 18 | 19 | **WebAssembly** 20 | ```html 21 | 22 | ``` 23 | 24 | **asm.js** (Use this only if your target environments don't support WebAssembly) 25 | ```html 26 | 27 | ``` 28 | 29 | ## Use 30 | - npm: 31 | 32 | **WebAssembly** 33 | 34 | ```javascript 35 | import { EThree } from '@virgilsecurity/e3kit-browser'; 36 | 37 | // Promise 38 | EThree.initialize(tokenCallback) 39 | .then(eThree => { 40 | // register user, encrypt, decrypt, etc. 41 | }); 42 | 43 | // async/await 44 | const eThree = await EThree.initialize(tokenCallback); 45 | // register user, encrypt, decrypt, etc. 46 | ``` 47 | 48 | **asm.js** (Use this only if your target environments don't support WebAssembly) 49 | ```javascript 50 | import { EThree } from '@virgilsecurity/e3kit-browser/dist/browser.asmjs.es'; 51 | 52 | // Promise 53 | EThree.initialize(tokenCallback) 54 | .then(eThree => { 55 | // register user, encrypt, decrypt, etc. 56 | }); 57 | 58 | // async/await 59 | const eThree = await EThree.initialize(tokenCallback); 60 | // register user, encrypt, decrypt, etc. 61 | ``` 62 | 63 | - UMD: 64 | ```html 65 | 78 | ``` 79 | 80 | ## Encrypt & decrypt large files 81 | 82 | See the following methods if you need to encrypt & decrypt large files with the best speed/browser performance ratio: 83 | - [authEncryptFile](https://virgilsecurity.github.io/virgil-e3kit-js/e3kit-browser/classes/ethree.html#authencryptfile) 84 | - [authDecryptFile](https://virgilsecurity.github.io/virgil-e3kit-js/e3kit-browser/classes/ethree.html#authdecryptfile) 85 | 86 | Both methods take an instance of `File` class as input instead of binary `ArrayBuffer`. 87 | The files are encrypted in small chunks, so it doesn't block the main thread and it returns an encrypted instance of `File`. The chunk size by default is 64kb which produces the best speed/browser performance ratio, but it can be changed. Larger chunk size speeds up encryption but can cause browser lags. 88 | 89 | The code sample can be found [here](https://github.com/VirgilSecurity/virgil-e3kit-js/blob/master/examples/authEncryptFile.html). 90 | 91 | > This approach for file encryption is currently only supported in browser environments and mobile apps built with the Ionic framework. 92 | 93 | ## Further reading 94 | You can find detailed guides on library usage [here](https://github.com/VirgilSecurity/virgil-e3kit-js#resources). 95 | 96 | ## License 97 | This library is released under the [3-clause BSD License](LICENSE). 98 | 99 | ## Support 100 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 101 | 102 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 103 | 104 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 105 | -------------------------------------------------------------------------------- /packages/e3kit-browser/browser.cjs.js: -------------------------------------------------------------------------------- 1 | const { EThree } = require('./dist/browser.cjs'); 2 | const foundationWasm = require('./dist/libfoundation.browser.wasm'); 3 | const pythiaWasm = require('./dist/libpythia.browser.wasm'); 4 | 5 | const rawInitialize = EThree.initialize; 6 | 7 | EThree.initialize = (getToken, options) => 8 | rawInitialize(getToken, { 9 | ...options, 10 | foundationWasmPath: 11 | options && options.foundationWasmPath ? options.foundationWasmPath : foundationWasm, 12 | pythiaWasmPath: options && options.pythiaWasmPath ? options.pythiaWasmPath : pythiaWasm, 13 | }); 14 | 15 | module.exports = require('./dist/browser.cjs'); 16 | -------------------------------------------------------------------------------- /packages/e3kit-browser/browser.es.js: -------------------------------------------------------------------------------- 1 | import { EThree } from './dist/browser.es'; 2 | import foundationWasm from './dist/libfoundation.browser.wasm'; 3 | import pythiaWasm from './dist/libpythia.browser.wasm'; 4 | 5 | const rawInitialize = EThree.initialize; 6 | 7 | EThree.initialize = (getToken, options) => 8 | rawInitialize(getToken, { 9 | ...options, 10 | foundationWasmPath: 11 | options && options.foundationWasmPath ? options.foundationWasmPath : foundationWasm, 12 | pythiaWasmPath: options && options.pythiaWasmPath ? options.pythiaWasmPath : pythiaWasm, 13 | }); 14 | 15 | export * from './dist/browser.es'; 16 | -------------------------------------------------------------------------------- /packages/e3kit-browser/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/e3kit-browser", 3 | "version": "3.0.6", 4 | "description": "End-to-end encryption with multiple device support powered by Virgil Security", 5 | "main": "./browser.cjs.js", 6 | "module": "./browser.es.js", 7 | "typings": "./dist/types/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "browser.cjs.js", 11 | "browser.es.js", 12 | "worker.cjs.js", 13 | "worker.es.js" 14 | ], 15 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-browser", 16 | "author": "Virgil Security Inc. ", 17 | "license": "BSD-3-Clause", 18 | "scripts": { 19 | "build": "rollup -c", 20 | "clean": "rimraf .rpt2_cache dist", 21 | "prepare": "npm run clean && npm run build" 22 | }, 23 | "dependencies": { 24 | "@types/level-js": "^4.0.2", 25 | "@virgilsecurity/e3kit-base": "^3.0.5", 26 | "@virgilsecurity/pythia-crypto": "^2.1.0", 27 | "level-js": "^5.0.1", 28 | "virgil-crypto": "^5.1.2", 29 | "virgil-sdk": "^6.1.2" 30 | }, 31 | "devDependencies": { 32 | "@rollup/plugin-commonjs": "^25.0.7", 33 | "@rollup/plugin-json": "^5.0.0", 34 | "@rollup/plugin-node-resolve": "^15.0.1", 35 | "@rollup/plugin-typescript": "^11.1.1", 36 | "@rollup/plugin-wasm": "^6.0.0", 37 | "cross-env": "^7.0.3", 38 | "rimraf": "^3.0.2", 39 | "rollup": "^3.11.0", 40 | "rollup-plugin-copy": "^3.4.0", 41 | "rollup-plugin-license": "^2.8.1", 42 | "rollup-plugin-node-builtins": "^2.1.2", 43 | "rollup-plugin-node-globals": "^1.4.0", 44 | "rollup-plugin-node-polyfills": "^0.2.1", 45 | "rollup-plugin-re": "^1.0.7", 46 | "typescript": "^4.8.4" 47 | }, 48 | "publishConfig": { 49 | "access": "public" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /packages/e3kit-browser/src/constants.ts: -------------------------------------------------------------------------------- 1 | export type VIRGIL_STREAM_SIGNING_STATE = 'Signing'; 2 | export const VIRGIL_STREAM_SIGNING_STATE = 'Signing'; 3 | 4 | export type VIRGIL_STREAM_ENCRYPTING_STATE = 'Encrypting'; 5 | export const VIRGIL_STREAM_ENCRYPTING_STATE = 'Encrypting'; 6 | 7 | export type VIRGIL_STREAM_DECRYPTING_STATE = 'Decrypting'; 8 | export const VIRGIL_STREAM_DECRYPTING_STATE = 'Decrypting'; 9 | 10 | export type VIRGIL_STREAM_VERIFYING_STATE = 'Verifying'; 11 | export const VIRGIL_STREAM_VERIFYING_STATE = 'Verifying'; 12 | -------------------------------------------------------------------------------- /packages/e3kit-browser/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | // errors 3 | SdkError, 4 | IdentityAlreadyExistsError, 5 | RegisterRequiredError, 6 | WrongKeyknoxPasswordError, 7 | PrivateKeyAlreadyExistsError, 8 | PrivateKeyNoBackupError, 9 | MultipleCardsError, 10 | LookupResultWithErrors, 11 | LookupError, 12 | LookupNotFoundError, 13 | IntegrityCheckFailedError, 14 | AbortError, 15 | GroupErrorCode, 16 | GroupError, 17 | MissingPrivateKeyError, 18 | // types 19 | NodeBuffer, 20 | Data, 21 | IKeyPair, 22 | IPrivateKey, 23 | IPublicKey, 24 | ICrypto, 25 | ICardCrypto, 26 | IBrainKeyCrypto, 27 | IAccessTokenProvider, 28 | ICard, 29 | IKeyEntryStorage, 30 | IKeyEntry, 31 | LookupResult, 32 | EncryptPublicKeyArg, 33 | FindUsersResult, 34 | Ticket, 35 | GroupInfo, 36 | RawGroup, 37 | } from '@virgilsecurity/e3kit-base'; 38 | export { KeyPairType } from 'virgil-crypto'; 39 | export * from './constants'; 40 | export { EThree } from './EThree'; 41 | export { 42 | onEncryptProgressCallback, 43 | onDecryptProgressCallback, 44 | onProgressCallback, 45 | onEncryptProgressSnapshot, 46 | onDecryptProgressSnapshot, 47 | onProgressSnapshot, 48 | EThreeInitializeOptions, 49 | EThreeCtorOptions, 50 | EncryptFileOptions, 51 | DecryptFileOptions, 52 | } from './types'; 53 | -------------------------------------------------------------------------------- /packages/e3kit-browser/src/processFile.ts: -------------------------------------------------------------------------------- 1 | import { AbortError } from '@virgilsecurity/e3kit-base'; 2 | 3 | /** 4 | * @hidden 5 | */ 6 | export type onChunkCallback = (chunk: string | ArrayBuffer, offset: number) => void; 7 | 8 | /** 9 | * @hidden 10 | */ 11 | export type processFileOptions = { 12 | file: Blob; 13 | chunkSize: number; 14 | signal?: AbortSignal; 15 | onChunkCallback: onChunkCallback; 16 | onFinishCallback: () => void; 17 | onErrorCallback: (err: any) => void; 18 | }; 19 | 20 | /** 21 | * @hidden 22 | */ 23 | export function processFile({ 24 | file, 25 | chunkSize, 26 | signal, 27 | onChunkCallback, 28 | onFinishCallback, 29 | onErrorCallback, 30 | }: processFileOptions) { 31 | const reader = new FileReader(); 32 | 33 | const dataSize = file.size; 34 | 35 | let offset = 0; 36 | let endOffset = Math.min(offset + chunkSize, dataSize); 37 | 38 | if (signal) { 39 | const onAbort = () => { 40 | reader.abort(); 41 | onErrorCallback(new AbortError()); 42 | }; 43 | if (signal.aborted) return onAbort(); 44 | else signal.addEventListener('abort', onAbort); 45 | } 46 | 47 | reader.onload = () => { 48 | if (!reader.result) throw new Error('reader.result is null'); 49 | 50 | try { 51 | onChunkCallback(reader.result, endOffset); 52 | } catch (err) { 53 | return onErrorCallback(err); 54 | } 55 | 56 | offset = endOffset; 57 | endOffset = Math.min(offset + chunkSize, dataSize); 58 | 59 | if (offset === dataSize) { 60 | try { 61 | onFinishCallback(); 62 | } catch (err) { 63 | onErrorCallback(err); 64 | } 65 | } else { 66 | reader.readAsArrayBuffer(file.slice(offset, endOffset)); 67 | } 68 | }; 69 | 70 | reader.onerror = () => onErrorCallback(reader.error); 71 | 72 | reader.readAsArrayBuffer(file.slice(offset, endOffset)); 73 | } 74 | -------------------------------------------------------------------------------- /packages/e3kit-browser/src/typeguards.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @hidden 3 | */ 4 | export const isFile = (val: any): val is File => { 5 | return val instanceof File; 6 | }; 7 | -------------------------------------------------------------------------------- /packages/e3kit-browser/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitReturns": false, 8 | "strictPropertyInitialization": false, 9 | "noFallthroughCasesInSwitch": true, 10 | "sourceMap": true, 11 | "declaration": true, 12 | "declarationDir": "./dist/types", 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "moduleResolution": "node", 16 | "importHelpers": true, 17 | "esModuleInterop": true, 18 | "target": "es2020", 19 | "module": "es2020", 20 | "lib": [ 21 | "es2018", 22 | "dom" 23 | ] 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /packages/e3kit-browser/worker.cjs.js: -------------------------------------------------------------------------------- 1 | const { EThree } = require('./dist/worker.cjs'); 2 | const foundationWasm = require('./dist/libfoundation.worker.wasm'); 3 | const pythiaWasm = require('./dist/libpythia.worker.wasm'); 4 | 5 | const rawInitialize = EThree.initialize; 6 | 7 | EThree.initialize = (getToken, options) => 8 | rawInitialize(getToken, { 9 | ...options, 10 | foundationWasmPath: 11 | options && options.foundationWasmPath ? options.foundationWasmPath : foundationWasm, 12 | pythiaWasmPath: options && options.pythiaWasmPath ? options.pythiaWasmPath : pythiaWasm, 13 | }); 14 | 15 | module.exports = require('./dist/worker.cjs'); 16 | -------------------------------------------------------------------------------- /packages/e3kit-browser/worker.es.js: -------------------------------------------------------------------------------- 1 | import { EThree } from './dist/worker.es'; 2 | import foundationWasm from './dist/libfoundation.worker.wasm'; 3 | import pythiaWasm from './dist/libpythia.worker.wasm'; 4 | 5 | const rawInitialize = EThree.initialize; 6 | 7 | EThree.initialize = (getToken, options) => 8 | rawInitialize(getToken, { 9 | ...options, 10 | foundationWasmPath: 11 | options && options.foundationWasmPath ? options.foundationWasmPath : foundationWasm, 12 | pythiaWasmPath: options && options.pythiaWasmPath ? options.pythiaWasmPath : pythiaWasm, 13 | }); 14 | 15 | export * from './dist/worker.es'; 16 | -------------------------------------------------------------------------------- /packages/e3kit-native/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit SDK for React Native 2 | Virgil E3Kit SDK is also available on other platforms: 3 | - [Browser](https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-browser) 4 | - [Node.js](https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-node) 5 | 6 | ## Installation 7 | Install `@virgilsecurity/e3kit-native` 8 | ```sh 9 | npm install @virgilsecurity/e3kit-native 10 | ``` 11 | 12 | Also you need to install several mandatory dependencies that aren't bundled in the package: 13 | - [react-native-virgil-crypto](https://github.com/VirgilSecurity/react-native-virgil-crypto) - Virgil Crypto Library for React Native. 14 | - [@react-native-community/async-storage](https://github.com/react-native-community/async-storage) - storage backend for group chats. 15 | - [@virgilsecurity/key-storage-rn](https://github.com/VirgilSecurity/virgil-key-storage-rn) - storage adapter for React Native. 16 | - [react-native-keychain](https://github.com/oblador/react-native-keychain) - storage backend for [@virgilsecurity/key-storage-rn](https://github.com/VirgilSecurity/virgil-key-storage-rn). 17 | 18 | > Tip: carefully follow the installation guides of each library to avoid problems in future. 19 | 20 | ## Usage 21 | ```js 22 | import AsyncStorage from '@react-native-community/async-storage'; 23 | import { EThree } from '@virgilsecurity/e3kit-native'; 24 | 25 | // Promise 26 | EThree.initialize(tokenCallback, { AsyncStorage }) 27 | .then(eThree => { 28 | // register user, encrypt, decrypt, etc. 29 | }); 30 | 31 | // async/await 32 | const eThree = await EThree.initialize(tokenCallback, { AsyncStorage }); 33 | // register user, encrypt, decrypt, etc. 34 | ``` 35 | > You need to explicitly pass `AsyncStorage` implementation to E3Kit. Otherwise an app will crash. 36 | 37 | ## Further reading 38 | You can find detailed guides on library usage [here](https://github.com/VirgilSecurity/virgil-e3kit-js#resources). 39 | 40 | ## License 41 | This library is released under the [3-clause BSD License](LICENSE). 42 | 43 | ## Support 44 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 45 | 46 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 47 | 48 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 49 | -------------------------------------------------------------------------------- /packages/e3kit-native/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'asyncstorage-down' { 2 | import { AbstractLevelDOWN } from 'abstract-leveldown'; 3 | import { AsyncStorageStatic } from 'react-native'; 4 | 5 | export interface AsyncStorageDown extends AbstractLevelDOWN { 6 | readonly location: string; 7 | } 8 | 9 | export interface AsyncStorageDownConstructor { 10 | new ( 11 | location: string, 12 | options: { AsyncStorage: AsyncStorageStatic }, 13 | ): AsyncStorageDown; 14 | (location: string, options: { AsyncStorage: unknown }): AsyncStorageDown< 15 | K, 16 | V 17 | >; 18 | } 19 | 20 | export const AsyncStorageDown: AsyncStorageDownConstructor; 21 | export default AsyncStorageDown; 22 | } 23 | -------------------------------------------------------------------------------- /packages/e3kit-native/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/e3kit-native", 3 | "version": "3.0.6", 4 | "description": "End-to-end encryption with multiple device support powered by Virgil Security", 5 | "main": "./dist/e3kit-native.cjs.js", 6 | "module": "./dist/e3kit-native.es.js", 7 | "typings": "./dist/types/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "declarationds.d.ts" 11 | ], 12 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-native", 13 | "author": "Virgil Security Inc. ", 14 | "license": "BSD-3-Clause", 15 | "scripts": { 16 | "build": "rollup -c", 17 | "clean": "rimraf .rpt2_cache dist", 18 | "prepare": "npm run clean && npm run build" 19 | }, 20 | "dependencies": { 21 | "@types/abstract-leveldown": "^7.2.0", 22 | "@types/react-native": "^0.70.4", 23 | "@typescript-eslint/eslint-plugin": "^5.40.0", 24 | "@typescript-eslint/parser": "^5.40.0", 25 | "@virgilsecurity/e3kit-base": "^3.0.5", 26 | "@virgilsecurity/sdk-crypto": "^2.0.0", 27 | "asyncstorage-down": "^4.2.0", 28 | "ejs": "^3.0.1", 29 | "eslint": "^8.25.0", 30 | "eslint-config-prettier": "^8.5.0", 31 | "lerna": "^8.0.2", 32 | "typedoc": "^0.23.16", 33 | "typescript": "^4.8.4", 34 | "virgil-sdk": "^6.1.2" 35 | }, 36 | "devDependencies": { 37 | "@rollup/plugin-commonjs": "^24.0.1", 38 | "@rollup/plugin-json": "^5.0.0", 39 | "@rollup/plugin-node-resolve": "^15.0.1", 40 | "@virgilsecurity/key-storage-rn": "^1.0.0", 41 | "react-native-keychain": "^8.1.1", 42 | "react-native-virgil-crypto": "^0.6.4", 43 | "rimraf": "^3.0.2", 44 | "rollup": "^3.1.0", 45 | "rollup-plugin-license": "^2.8.1", 46 | "rollup-plugin-node-builtins": "^2.1.2", 47 | "rollup-plugin-node-globals": "^1.4.0", 48 | "rollup-plugin-typescript2": "^0.34.1", 49 | "typescript": "^4.8.4" 50 | }, 51 | "peerDependencies": { 52 | "@virgilsecurity/key-storage-rn": "1.0.0", 53 | "react-native-virgil-crypto": "0.6.3" 54 | }, 55 | "publishConfig": { 56 | "access": "public" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /packages/e3kit-native/rollup.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const commonjs = require('@rollup/plugin-commonjs'); 4 | const license = require('rollup-plugin-license'); 5 | const nodeResolve = require('@rollup/plugin-node-resolve'); 6 | const typescript = require('rollup-plugin-typescript2'); 7 | const builtins = require('rollup-plugin-node-builtins'); 8 | const globals = require('rollup-plugin-node-globals'); 9 | const replace = require('rollup-plugin-re'); 10 | const json = require('@rollup/plugin-json'); 11 | 12 | const packageJson = require('./package.json'); 13 | const PRODUCT_NAME = 'e3kit'; 14 | 15 | const FORMAT = { 16 | CJS: 'cjs', 17 | ES: 'es', 18 | }; 19 | 20 | const sourcePath = path.join(__dirname, 'src'); 21 | const outputPath = path.join(__dirname, 'dist'); 22 | 23 | const createEntry = (format) => ({ 24 | external: [ 25 | '@react-native-community/async-storage', 26 | '@virgilsecurity/key-storage-rn/native', 27 | 'react-native', 28 | 'react-native-virgil-crypto', 29 | 'react-native-keychain', 30 | ], 31 | input: path.join(sourcePath, 'index.ts'), 32 | output: { 33 | format, 34 | file: path.join(outputPath, `e3kit-native.${format}.js`), 35 | }, 36 | plugins: [ 37 | replace({ 38 | replaces: { 39 | 'process.env.__VIRGIL_PRODUCT_NAME__': JSON.stringify(PRODUCT_NAME), 40 | 'process.env.__VIRGIL_PRODUCT_VERSION__': JSON.stringify(packageJson.version), 41 | }, 42 | }), 43 | nodeResolve({ browser: true, preferBuiltins: false }), 44 | commonjs(), 45 | globals(), 46 | builtins(), 47 | typescript({ 48 | useTsconfigDeclarationDir: true, 49 | tsconfigOverride: { 50 | compilerOptions: { 51 | noImplicitAny: false, 52 | }, 53 | }, 54 | }), 55 | json(), 56 | license({ 57 | banner: { 58 | content: { 59 | file: path.join(__dirname, '..', '..', 'LICENSE'), 60 | }, 61 | }, 62 | }), 63 | ], 64 | }); 65 | 66 | module.exports = [createEntry(FORMAT.CJS), createEntry(FORMAT.ES)]; 67 | -------------------------------------------------------------------------------- /packages/e3kit-native/src/EThree.ts: -------------------------------------------------------------------------------- 1 | import { 2 | DEFAULT_API_URL, 3 | DEFAULT_STORAGE_NAME, 4 | DEFAULT_GROUP_STORAGE_NAME, 5 | AbstractEThree, 6 | PrivateKeyLoader, 7 | } from '@virgilsecurity/e3kit-base'; 8 | import { ReactNativeKeychainStorageAdapter } from '@virgilsecurity/key-storage-rn'; 9 | import { VirgilCardCrypto } from '@virgilsecurity/sdk-crypto'; 10 | import { virgilCrypto, virgilBrainKeyCrypto, HashAlgorithm } from 'react-native-virgil-crypto'; 11 | import { CachingJwtProvider, CardManager, VirgilCardVerifier, KeyEntryStorage } from 'virgil-sdk'; 12 | import asyncstorageDown from 'asyncstorage-down'; 13 | 14 | import { Data, EThreeCtorOptions, EThreeInitializeOptions } from './types'; 15 | 16 | import './asyncstoragedown-clear-polyfill'; 17 | 18 | export interface EThreeNativeInitializeOptions extends EThreeInitializeOptions { 19 | AsyncStorage: import('react-native').AsyncStorageStatic; 20 | } 21 | 22 | export interface EThreeNativeCtorOptions extends EThreeCtorOptions { 23 | AsyncStorage: import('react-native').AsyncStorageStatic; 24 | } 25 | 26 | export class EThree extends AbstractEThree { 27 | /** 28 | * @hidden 29 | */ 30 | constructor(identity: string, options: EThreeNativeCtorOptions) { 31 | const opts = { 32 | apiUrl: DEFAULT_API_URL, 33 | storageName: DEFAULT_STORAGE_NAME, 34 | groupStorageName: DEFAULT_GROUP_STORAGE_NAME, 35 | useSha256Identifiers: false, 36 | ...options, 37 | }; 38 | const accessTokenProvider = opts.accessTokenProvider; 39 | const keyEntryStorage = 40 | opts.keyEntryStorage || 41 | new KeyEntryStorage({ adapter: new ReactNativeKeychainStorageAdapter() }); 42 | const cardCrypto = new VirgilCardCrypto(virgilCrypto); 43 | const cardVerifier = new VirgilCardVerifier(cardCrypto); 44 | const keyLoader = new PrivateKeyLoader(identity, { 45 | accessTokenProvider, 46 | virgilCrypto, 47 | brainKeyCrypto: virgilBrainKeyCrypto, 48 | keyEntryStorage, 49 | apiUrl: opts.apiUrl, 50 | }); 51 | const cardManager = new CardManager({ 52 | cardCrypto, 53 | cardVerifier, 54 | accessTokenProvider, 55 | retryOnUnauthorized: true, 56 | apiUrl: opts.apiUrl, 57 | productInfo: { 58 | product: process.env.__VIRGIL_PRODUCT_NAME__ ?? '', 59 | version: process.env.__VIRGIL_PRODUCT_VERSION__ ?? '', 60 | }, 61 | }); 62 | const groupStorageLeveldown = asyncstorageDown(opts.groupStorageName!, { 63 | AsyncStorage: opts.AsyncStorage, 64 | }); 65 | 66 | super({ 67 | identity, 68 | virgilCrypto, 69 | cardManager, 70 | accessTokenProvider, 71 | keyEntryStorage, 72 | keyLoader, 73 | groupStorageLeveldown, 74 | keyPairType: options.keyPairType, 75 | }); 76 | } 77 | 78 | /** 79 | * Initialize a new instance of EThree which tied to specific user. 80 | * @param getToken - Function that receive JWT. 81 | */ 82 | static async initialize( 83 | getToken: () => Promise, 84 | options: EThreeNativeInitializeOptions, 85 | ): Promise { 86 | if (typeof getToken !== 'function') { 87 | throw new TypeError( 88 | `EThree.initialize expects a function that returns Virgil JWT, got ${typeof getToken}`, 89 | ); 90 | } 91 | 92 | const opts = { 93 | accessTokenProvider: new CachingJwtProvider(getToken), 94 | ...options, 95 | }; 96 | const token = await opts.accessTokenProvider.getToken({ 97 | service: 'cards', 98 | operation: '', 99 | }); 100 | const identity = token.identity(); 101 | return new EThree(identity, opts); 102 | } 103 | 104 | static derivePasswords(password: Data) { 105 | const hash1 = virgilCrypto.calculateHash(password, HashAlgorithm.SHA256); 106 | const hash2 = virgilCrypto.calculateHash(hash1, HashAlgorithm.SHA512); 107 | const loginPassword = hash2.slice(0, 32); 108 | const backupPassword = hash2.slice(32, 64); 109 | return { loginPassword, backupPassword }; 110 | } 111 | 112 | /** 113 | * @hidden 114 | */ 115 | protected isPublicKey(publicKey: any) { 116 | return publicKey != null && typeof (publicKey as any).value === 'string'; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /packages/e3kit-native/src/asyncstoragedown-clear-polyfill.ts: -------------------------------------------------------------------------------- 1 | import asyncstorageDown from 'asyncstorage-down'; 2 | 3 | if (typeof asyncstorageDown.prototype.clear === 'undefined') { 4 | asyncstorageDown.prototype.clear = function (opts?: any, cb?: (err?: Error) => void) { 5 | let options; 6 | let callback: (err?: Error) => void; 7 | if (typeof opts === 'function') { 8 | options = {}; 9 | callback = opts; 10 | } else { 11 | options = opts; 12 | callback = cb!; 13 | } 14 | 15 | if (typeof callback !== 'function') { 16 | throw new Error('clear() requires a callback argument'); 17 | } 18 | 19 | options.reverse = !!options.reverse; 20 | options.limit = 'limit' in options ? options.limit : -1; 21 | options.keys = true; 22 | options.values = false; 23 | options.keyAsBuffer = false; 24 | options.valueAsBuffer = false; 25 | 26 | const iterator = this.iterator(options); 27 | const emptyOptions = {}; 28 | const operations: { type: 'del'; key: string }[] = []; 29 | 30 | const next = (err?: Error) => { 31 | if (err) { 32 | return iterator.end(() => { 33 | callback(err); 34 | }); 35 | } 36 | 37 | iterator.next((err: Error | undefined, key: string) => { 38 | if (err) return next(err); 39 | if (key === undefined) { 40 | this.batch(operations, emptyOptions, (batchErr?: Error) => { 41 | iterator.end((endErr?: Error) => { 42 | callback(batchErr || endErr); 43 | }); 44 | }); 45 | return; 46 | } 47 | 48 | operations.push({ type: 'del', key }); 49 | next(); 50 | }); 51 | }; 52 | 53 | next(); 54 | }; 55 | } 56 | -------------------------------------------------------------------------------- /packages/e3kit-native/src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | // errors 3 | SdkError, 4 | IdentityAlreadyExistsError, 5 | RegisterRequiredError, 6 | WrongKeyknoxPasswordError, 7 | PrivateKeyAlreadyExistsError, 8 | PrivateKeyNoBackupError, 9 | MultipleCardsError, 10 | LookupResultWithErrors, 11 | LookupError, 12 | LookupNotFoundError, 13 | IntegrityCheckFailedError, 14 | AbortError, 15 | GroupErrorCode, 16 | GroupError, 17 | MissingPrivateKeyError, 18 | // types 19 | NodeBuffer, 20 | Data, 21 | IKeyPair, 22 | IPrivateKey, 23 | IPublicKey, 24 | ICrypto, 25 | ICardCrypto, 26 | IBrainKeyCrypto, 27 | IAccessTokenProvider, 28 | ICard, 29 | IKeyEntryStorage, 30 | IKeyEntry, 31 | EThreeInitializeOptions, 32 | EThreeCtorOptions, 33 | LookupResult, 34 | EncryptPublicKeyArg, 35 | FindUsersResult, 36 | Ticket, 37 | GroupInfo, 38 | RawGroup, 39 | } from '@virgilsecurity/e3kit-base'; 40 | export { KeyPairType } from 'react-native-virgil-crypto'; 41 | export { EThree, EThreeNativeInitializeOptions } from './EThree'; 42 | -------------------------------------------------------------------------------- /packages/e3kit-native/src/types.ts: -------------------------------------------------------------------------------- 1 | export type Data = import('@virgilsecurity/e3kit-base').Data; 2 | export type IPublicKey = import('@virgilsecurity/e3kit-base').IPublicKey; 3 | export type EThreeInitializeOptions = import('@virgilsecurity/e3kit-base').EThreeInitializeOptions; 4 | export type EThreeCtorOptions = import('@virgilsecurity/e3kit-base').EThreeCtorOptions; 5 | -------------------------------------------------------------------------------- /packages/e3kit-native/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/types", 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitReturns": false, 8 | "strictPropertyInitialization": false, 9 | "noFallthroughCasesInSwitch": true, 10 | "sourceMap": true, 11 | "declaration": true, 12 | "declarationDir": "./dist/types", 13 | "downlevelIteration": true, 14 | "experimentalDecorators": true, 15 | "moduleResolution": "node", 16 | "importHelpers": true, 17 | "esModuleInterop": true, 18 | "target": "es2020", 19 | "module": "es2015", 20 | "lib": [ 21 | "es2018", 22 | "dom" 23 | ] 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /packages/e3kit-node/README.md: -------------------------------------------------------------------------------- 1 | # Virgil E3Kit SDK for Node.js 2 | Virgil E3Kit SDK is also available on other platforms: 3 | - [Browser](https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-browser) 4 | - [React Native](https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-native) 5 | 6 | > Minimum supported version of Node.js is `8.6.0`. 7 | 8 | ## Install 9 | - npm: 10 | ```sh 11 | npm install @virgilsecurity/e3kit-node 12 | ``` 13 | - yarn: 14 | ```sh 15 | yarn add @virgilsecurity/e3kit-node 16 | ``` 17 | 18 | ## Use 19 | 20 | ```javascript 21 | import { EThree } from '@virgilsecurity/e3kit-node'; 22 | 23 | // Promise 24 | EThree.initialize(tokenCallback) 25 | .then(eThree => { 26 | // register user, encrypt, decrypt, etc. 27 | }); 28 | 29 | // async/await 30 | const eThree = await EThree.initialize(tokenCallback); 31 | // register user, encrypt, decrypt, etc. 32 | ``` 33 | 34 | ## Further reading 35 | You can find detailed guides on library usage [here](https://github.com/VirgilSecurity/virgil-e3kit-js#resources). 36 | 37 | ## License 38 | This library is released under the [3-clause BSD License](LICENSE). 39 | 40 | ## Support 41 | Our developer support team is here to help you. Find out more information on our [Help Center](https://help.virgilsecurity.com). 42 | 43 | You can find us on [Twitter](https://twitter.com/VirgilSecurity) or send us email support@VirgilSecurity.com. 44 | 45 | Also, get extra help from our support team on [Slack](https://virgilsecurity.com/join-community). 46 | -------------------------------------------------------------------------------- /packages/e3kit-node/declaration.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'is-invalid-path' { 2 | function isInvalidPath(path: string): boolean; 3 | export = isInvalidPath; 4 | } 5 | -------------------------------------------------------------------------------- /packages/e3kit-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/e3kit-node", 3 | "version": "3.0.5", 4 | "description": "End-to-end encryption with multiple device support powered by Virgil Security", 5 | "main": "./dist/node.cjs.js", 6 | "module": "./dist/node.es.js", 7 | "typings": "./dist/types/src/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "declaration.d.ts" 11 | ], 12 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-node", 13 | "author": "Virgil Security Inc. ", 14 | "license": "BSD-3-Clause", 15 | "scripts": { 16 | "build": "rollup -c", 17 | "clean": "rimraf .rpt2_cache dist", 18 | "prepare": "npm run clean && npm run build" 19 | }, 20 | "dependencies": { 21 | "@types/leveldown": "^4.0.3", 22 | "@types/mkdirp": "^1.0.2", 23 | "@virgilsecurity/e3kit-base": "^3.0.6", 24 | "@virgilsecurity/pythia-crypto": "^2.1.0", 25 | "leveldown": "^6.1.1", 26 | "mkdirp": "^1.0.4", 27 | "virgil-crypto": "^5.1.2", 28 | "virgil-sdk": "^6.2.0" 29 | }, 30 | "devDependencies": { 31 | "@rollup/plugin-json": "^5.0.0", 32 | "builtin-modules": "^3.3.0", 33 | "rimraf": "^3.0.2", 34 | "rollup": "^3.11.0", 35 | "rollup-plugin-license": "^2.8.1", 36 | "rollup-plugin-re": "^1.0.7", 37 | "@rollup/plugin-typescript": "^11.1.6", 38 | "typescript": "^5.4.5" 39 | }, 40 | "publishConfig": { 41 | "access": "public" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/e3kit-node/rollup.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const builtinModules = require('builtin-modules'); 4 | const license = require('rollup-plugin-license'); 5 | const replace = require('rollup-plugin-re'); 6 | const typescript = require('@rollup/plugin-typescript'); 7 | const json = require('@rollup/plugin-json'); 8 | const { generateCrossPlatformPath } = require('../../utils/build'); 9 | 10 | const packageJson = require('./package.json'); 11 | const { includes } = require('builtin-modules'); 12 | 13 | const FORMAT = { 14 | CJS: 'cjs', 15 | ES: 'es', 16 | }; 17 | 18 | const CRYPTO_TYPE = { 19 | WASM: 'wasm', 20 | ASMJS: 'asmjs', 21 | }; 22 | 23 | const sourcePath = path.join(__dirname, 'src'); 24 | const outputPath = path.join(__dirname, 'dist'); 25 | 26 | const getCryptoEntryPointName = (cryptoType, format) => 27 | `node${cryptoType === CRYPTO_TYPE.ASMJS ? '.asmjs' : ''}.${format}.js`; 28 | 29 | const createEntry = (cryptoType, format) => { 30 | const foundationModuleName = 'virgil-crypto'; 31 | let foundationEntryPoint = generateCrossPlatformPath( 32 | foundationModuleName, 33 | 'dist', 34 | getCryptoEntryPointName(cryptoType, format), 35 | ); 36 | 37 | const pythiaModuleName = '@virgilsecurity/pythia-crypto'; 38 | const pythiaEntryPoint = generateCrossPlatformPath( 39 | pythiaModuleName, 40 | 'dist', 41 | getCryptoEntryPointName(cryptoType, format), 42 | ); 43 | 44 | const external = builtinModules 45 | .concat(Object.keys(packageJson.dependencies)) 46 | .concat([foundationEntryPoint, pythiaEntryPoint]); 47 | 48 | const outputFileName = getCryptoEntryPointName(cryptoType, format); 49 | 50 | return { 51 | external, 52 | input: path.join(sourcePath, 'index.ts'), 53 | output: { 54 | format, 55 | file: path.join(outputPath, outputFileName), 56 | }, 57 | plugins: [ 58 | replace({ 59 | patterns: [ 60 | { 61 | match: /(index|EThree)\.ts$/, 62 | test: foundationModuleName, 63 | replace: foundationEntryPoint, 64 | }, 65 | { 66 | match: /EThree\.ts$/, 67 | test: pythiaModuleName, 68 | replace: pythiaEntryPoint, 69 | }, 70 | ], 71 | }), 72 | typescript({ 73 | tsconfig: './tsconfig.json', 74 | }), 75 | json(), 76 | license({ 77 | banner: { 78 | content: { 79 | file: path.join(__dirname, '..', '..', 'LICENSE'), 80 | }, 81 | }, 82 | }), 83 | ], 84 | }; 85 | }; 86 | 87 | module.exports = [ 88 | createEntry(CRYPTO_TYPE.ASMJS, FORMAT.CJS), 89 | createEntry(CRYPTO_TYPE.WASM, FORMAT.CJS), 90 | createEntry(CRYPTO_TYPE.ASMJS, FORMAT.ES), 91 | createEntry(CRYPTO_TYPE.WASM, FORMAT.ES), 92 | ]; 93 | -------------------------------------------------------------------------------- /packages/e3kit-node/src/index.ts: -------------------------------------------------------------------------------- 1 | import { version } from '../package.json'; 2 | 3 | process.env.__VIRGIL_PRODUCT_NAME__ = 'e3kit'; 4 | process.env.__VIRGIL_PRODUCT_VERSION__ = version; 5 | 6 | export { 7 | // errors 8 | SdkError, 9 | IdentityAlreadyExistsError, 10 | RegisterRequiredError, 11 | WrongKeyknoxPasswordError, 12 | PrivateKeyAlreadyExistsError, 13 | PrivateKeyNoBackupError, 14 | MultipleCardsError, 15 | LookupResultWithErrors, 16 | LookupError, 17 | LookupNotFoundError, 18 | IntegrityCheckFailedError, 19 | AbortError, 20 | GroupErrorCode, 21 | GroupError, 22 | MissingPrivateKeyError, 23 | // types 24 | NodeBuffer, 25 | Data, 26 | IKeyPair, 27 | IPrivateKey, 28 | IPublicKey, 29 | ICrypto, 30 | ICardCrypto, 31 | IBrainKeyCrypto, 32 | IAccessTokenProvider, 33 | ICard, 34 | IKeyEntryStorage, 35 | IKeyEntry, 36 | LookupResult, 37 | EncryptPublicKeyArg, 38 | FindUsersResult, 39 | Ticket, 40 | GroupInfo, 41 | RawGroup, 42 | } from '@virgilsecurity/e3kit-base'; 43 | export { KeyPairType } from 'virgil-crypto'; 44 | export { EThree } from './EThree'; 45 | export { EThreeInitializeOptions, EThreeCtorOptions } from './types'; 46 | -------------------------------------------------------------------------------- /packages/e3kit-node/src/types.ts: -------------------------------------------------------------------------------- 1 | export type Data = import('@virgilsecurity/e3kit-base').Data; 2 | export type IPublicKey = import('@virgilsecurity/e3kit-base').IPublicKey; 3 | export type EThreeBaseInitializeOptions = import('@virgilsecurity/e3kit-base').EThreeInitializeOptions; 4 | export type EThreeBaseCtorOptions = import('@virgilsecurity/e3kit-base').EThreeCtorOptions; 5 | 6 | export type KeyPairType = import('virgil-crypto').KeyPairType; 7 | 8 | export interface FoundationLibraryOptions { 9 | foundationWasmPath?: string; 10 | } 11 | 12 | export interface PythiaLibraryOptions { 13 | pythiaWasmPath?: string; 14 | } 15 | 16 | export interface EThreeInitializeOptions 17 | extends EThreeBaseInitializeOptions, 18 | FoundationLibraryOptions, 19 | PythiaLibraryOptions { 20 | keyPairType?: KeyPairType; 21 | } 22 | 23 | export interface EThreeCtorOptions extends EThreeBaseCtorOptions { 24 | keyPairType?: KeyPairType; 25 | } 26 | -------------------------------------------------------------------------------- /packages/e3kit-node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "noImplicitAny": false, 6 | "resolveJsonModule": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitReturns": false, 10 | "strictPropertyInitialization": false, 11 | "noFallthroughCasesInSwitch": true, 12 | "sourceMap": true, 13 | "declaration": true, 14 | "declarationDir": "./dist/types", 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "esModuleInterop": true, 20 | "target": "es2020", 21 | "module": "es2020", 22 | "lib": [ 23 | "es2018", 24 | "dom" 25 | ] 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /packages/e3kit-tests/.env.example: -------------------------------------------------------------------------------- 1 | APP_ID=APP_ID 2 | APP_KEY=APP_KEY 3 | APP_KEY_ID=APP_KEY_ID 4 | API_URL=API_URL 5 | -------------------------------------------------------------------------------- /packages/e3kit-tests/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "@typescript-eslint/no-non-null-assertion": "off" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/e3kit-tests/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "modules": "commonjs", 7 | "targets": { 8 | "node": "current" 9 | } 10 | } 11 | ], 12 | "@babel/preset-typescript" 13 | ], 14 | "plugins": [ 15 | "@babel/plugin-transform-async-to-generator", 16 | "babel-plugin-transform-class-properties", 17 | "babel-plugin-transform-decorators-legacy", 18 | "babel-plugin-transform-es2015-modules-commonjs" 19 | ], 20 | "env": { 21 | "test": { 22 | "presets": ["@babel/preset-env"], 23 | "plugins": [ 24 | "@babel/plugin-transform-async-to-generator", 25 | "@babel/plugin-transform-modules-commonjs", 26 | [ 27 | "@babel/plugin-transform-runtime", 28 | { 29 | "regenerator": true 30 | } 31 | ], 32 | "transform-class-properties" 33 | ] 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/e3kit-tests/jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from 'jest'; 2 | 3 | const config: Config = { 4 | verbose: true, 5 | preset: 'ts-jest', 6 | transform: { 7 | '^.+\\.ts?$': 'ts-jest', 8 | '^.+\\.js?$': 'babel-jest', // had to add this 9 | }, 10 | testMatch: ['**.ts'], 11 | runner: 'jest-runner-mocha', 12 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 13 | moduleDirectories: ['node_modules', 'src'], 14 | transformIgnorePatterns: ['e3kit-tests/node_modules'], 15 | }; 16 | 17 | export default config; 18 | -------------------------------------------------------------------------------- /packages/e3kit-tests/karma.conf.js: -------------------------------------------------------------------------------- 1 | const dotenv = require('dotenv'); 2 | const webpack = require('webpack'); 3 | 4 | dotenv.config(); 5 | 6 | module.exports = (config) => { 7 | config.set({ 8 | frameworks: ['mocha', 'karma-typescript', 'webpack'], 9 | autoWatch: true, 10 | files: [ 11 | { 12 | pattern: 'src/**/browser.ts', 13 | type: 'module', 14 | }, 15 | ], 16 | browsers: ['ChromeHeadless'], 17 | colors: true, 18 | logLevel: config.DEBUG, 19 | browserNoActivityTimeout: 60 * 1000, 20 | singleRun: false, 21 | mime: { 22 | 'text/x-typescript': ['ts'], 23 | 'application/wasm': ['wasm'], 24 | }, 25 | preprocessors: { 26 | 'src/browser.ts': ['webpack'], 27 | }, 28 | client: { 29 | mocha: { 30 | timeout: 15000, 31 | }, 32 | }, 33 | reporters: ['spec', 'karma-typescript'], 34 | // karmaTypescriptConfig: { 35 | // bundlerOptions: { 36 | // entrypoints: '**.spec.ts', 37 | // transforms: [require('karma-typescript-es6-transform')()], 38 | // resolve: 'src', 39 | // }, 40 | // tsconfig: 'tsconfig.json', 41 | // }, 42 | webpack: { 43 | mode: 'production', 44 | resolve: { 45 | extensions: ['.js', '.ts'], 46 | }, 47 | output: { 48 | path: __dirname + '/build', 49 | }, 50 | module: { 51 | rules: [ 52 | { 53 | test: /\.ts$/, 54 | loader: 'ts-loader', 55 | }, 56 | { 57 | test: /\.wasm$/, 58 | type: 'javascript/auto', 59 | loader: 'file-loader', 60 | }, 61 | ], 62 | }, 63 | experiments: { 64 | asyncWebAssembly: false, 65 | layers: true, 66 | outputModule: true, 67 | syncWebAssembly: true, 68 | topLevelAwait: true, 69 | }, 70 | plugins: [ 71 | new webpack.NormalModuleReplacementPlugin( 72 | /@virgilsecurity\/e3kit-node/, 73 | '@virgilsecurity/e3kit-browser', 74 | ), 75 | new webpack.EnvironmentPlugin({ 76 | APP_KEY_ID: JSON.stringify(process.env.APP_KEY_ID), 77 | APP_KEY: JSON.stringify(process.env.APP_KEY), 78 | APP_ID: JSON.stringify(process.env.APP_ID), 79 | API_URL: JSON.stringify(process.env.API_URL), 80 | NODE_ENV: 'production', 81 | }), 82 | ], 83 | }, 84 | }); 85 | }; 86 | -------------------------------------------------------------------------------- /packages/e3kit-tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@virgilsecurity/e3kit-tests", 3 | "version": "2.4.5", 4 | "description": "Virgil E3Kit SDK tests", 5 | "repository": "https://github.com/VirgilSecurity/virgil-e3kit-js/tree/master/packages/e3kit-tests", 6 | "author": "Virgil Security Inc. ", 7 | "license": "BSD-3-Clause", 8 | "private": true, 9 | "scripts": { 10 | "test": "concurrently 'npm:test:*'", 11 | "test:node": "ts-mocha -t 0 -r dotenv/config -r ts-node/register -r setup-mocha src/node.spec.ts", 12 | "test:browser": "karma start" 13 | }, 14 | "dependencies": { 15 | "@babel/plugin-transform-async-to-generator": "^7.18.6", 16 | "@babel/plugin-transform-runtime": "^7.19.6", 17 | "@babel/preset-typescript": "^7.18.6", 18 | "@types/chai": "^4.3.3", 19 | "@types/expect": "^24.3.0", 20 | "@types/is-buffer": "^2.0.0", 21 | "@types/jest": "^29.2.0", 22 | "@types/mocha": "^10.0.0", 23 | "@types/uuid": "^8.3.4", 24 | "@virgilsecurity/e3kit-browser": "^2.5.0", 25 | "@virgilsecurity/e3kit-node": "^2.5.0", 26 | "@virgilsecurity/keyknox": "^1.0.3", 27 | "@virgilsecurity/pythia-crypto": "^1.1.3", 28 | "babel-env": "^2.4.1", 29 | "babel-jest": "^29.2.1", 30 | "babel-plugin-transform-class-properties": "^6.24.1", 31 | "babel-plugin-transform-decorators-legacy": "^1.3.5", 32 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.2", 33 | "chai": "^4.3.6", 34 | "concurrently": "^7.4.0", 35 | "dotenv": "^16.0.3", 36 | "file-loader": "^6.2.0", 37 | "is-buffer": "^2.0.5", 38 | "jasmine": "^4.4.0", 39 | "jest": "^29.2.1", 40 | "jest-runner-mocha": "^0.6.0", 41 | "karma": "^6.4.1", 42 | "karma-chai": "^0.1.0", 43 | "karma-chrome-launcher": "^3.1.1", 44 | "karma-jasmine": "^5.1.0", 45 | "karma-mocha": "^2.0.1", 46 | "karma-spec-reporter": "^0.0.34", 47 | "karma-typescript": "^5.5.3", 48 | "karma-typescript-angular2-transform": "^5.5.3", 49 | "karma-typescript-es6-transform": "^5.5.3", 50 | "karma-webpack": "^5.0.0", 51 | "mime": "^3.0.0", 52 | "mocha": "^10.0.0", 53 | "ts-jest": "^29.0.3", 54 | "ts-loader": "^9.4.1", 55 | "ts-mocha": "^10.0.0", 56 | "ts-node": "^10.9.1", 57 | "typescript": "^4.8.4", 58 | "uuid": "^9.0.0", 59 | "virgil-crypto": "^5.0.2", 60 | "virgil-pythia": "^1.0.2", 61 | "virgil-sdk": "^6.1.2", 62 | "webpack": "^5.74.0" 63 | }, 64 | "workspaces": { 65 | "nohoist": [ 66 | "@types/chai", 67 | "@types/mocha", 68 | "chai", 69 | "karma", 70 | "karma-chai", 71 | "karma-chrome-launcher", 72 | "karma-mocha", 73 | "karma-webpack", 74 | "mocha", 75 | "ts-loader", 76 | "ts-node", 77 | "webpack" 78 | ] 79 | }, 80 | "devDependencies": { 81 | "readable-stream": "^4.2.0", 82 | "rollup-plugin-typescript2": "^0.34.1" 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /packages/e3kit-tests/setup-mocha.js: -------------------------------------------------------------------------------- 1 | const { version } = require('./package.json'); 2 | 3 | process.env.__VIRGIL_PRODUCT_NAME__ = 'e3kit'; 4 | process.env.__VIRGIL_PRODUCT_VERSION__ = version; 5 | -------------------------------------------------------------------------------- /packages/e3kit-tests/src/browser.ts: -------------------------------------------------------------------------------- 1 | import './browser/EThreeBrowser.test'; 2 | import './browser/EthreeDocSnippets.test'; 3 | -------------------------------------------------------------------------------- /packages/e3kit-tests/src/common/utils.ts: -------------------------------------------------------------------------------- 1 | export const sleep = (ms: number) => 2 | new Promise((resolve) => { 3 | setTimeout(resolve, ms); 4 | }); 5 | 6 | export const b64toBlob = (b64Data: string, contentType = 'text/plain', sliceSize = 512) => { 7 | const byteCharacters = atob(b64Data); 8 | const byteArrays = []; 9 | 10 | for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { 11 | const slice = byteCharacters.slice(offset, offset + sliceSize); 12 | 13 | const byteNumbers = new Array(slice.length); 14 | for (let i = 0; i < slice.length; i++) { 15 | byteNumbers[i] = slice.charCodeAt(i); 16 | } 17 | 18 | const byteArray = new Uint8Array(byteNumbers); 19 | byteArrays.push(byteArray); 20 | } 21 | 22 | const blob = new Blob(byteArrays, { type: contentType }); 23 | return blob; 24 | }; 25 | -------------------------------------------------------------------------------- /packages/e3kit-tests/src/node.spec.ts: -------------------------------------------------------------------------------- 1 | import './common/EThree.spec'; 2 | import './common/Group.spec'; 3 | -------------------------------------------------------------------------------- /packages/e3kit-tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./build", 4 | "forceConsistentCasingInFileNames": true, 5 | "strict": true, 6 | "noImplicitReturns": false, 7 | "strictPropertyInitialization": false, 8 | "noFallthroughCasesInSwitch": true, 9 | "sourceMap": true, 10 | "declaration": true, 11 | "downlevelIteration": true, 12 | "experimentalDecorators": true, 13 | "moduleResolution": "node", 14 | "importHelpers": true, 15 | "isolatedModules": true, 16 | "esModuleInterop": true, 17 | "resolveJsonModule": true, 18 | "allowJs": false, 19 | "target": "es2020", 20 | "module": "es2015", 21 | "types" : [ 22 | "mocha", 23 | ], 24 | "lib": [ 25 | "es2018", 26 | "dom" 27 | ] 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /scripts/doc-index-template.html.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Index of E3Kit API Reference 8 | 21 | 22 | 23 |

E3Kit JavaScript API Reference

24 | 25 | 26 | <% links.forEach(function(link) { %> 27 | 28 | 29 | 30 | 31 | <% }); %> 32 | 33 |
<%= link.title %>v<%= link.version %>
34 | 35 | 36 | -------------------------------------------------------------------------------- /scripts/generate-docs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const TypeDoc = require('typedoc'); 6 | const ejs = require('ejs'); 7 | 8 | const packagesDir = path.resolve(__dirname, '..', 'packages'); 9 | const outDir = path.resolve(__dirname, '..', 'docs'); 10 | 11 | const template = ejs.compile( 12 | fs.readFileSync(path.join(__dirname, 'doc-index-template.html.ejs'), 'utf8'), 13 | ); 14 | 15 | function buildDocsForPackage(pkg) { 16 | const app = new TypeDoc.Application(); 17 | app.bootstrap({ 18 | mode: 'file', 19 | module: 'es2015', 20 | moduleResolution: 'node', 21 | exclude: '**/__tests__/**', 22 | excludeExternals: true, 23 | excludeNotExported: true, 24 | excludePrivate: true, 25 | ignoreCompilerErrors: true, 26 | readme: 'none', 27 | stripInternal: true, 28 | suppressExcessPropertyErrors: true, 29 | suppressImplicitAnyIndexErrors: true, 30 | target: 'es2015', 31 | }); 32 | 33 | console.log(`Generating docs for ${pkg.dirName}`); 34 | 35 | const project = app.convert(app.expandInputFiles([pkg.srcPath])); 36 | if (!project) { 37 | throw new Error(`Failed to generate docs for ${pkg.name}`); 38 | } 39 | 40 | app.generateDocs(project, path.join(outDir, pkg.dirName)); 41 | 42 | return { 43 | href: pkg.dirName, 44 | title: pkg.name, 45 | version: pkg.version, 46 | }; 47 | } 48 | 49 | const links = fs 50 | .readdirSync(packagesDir, { encoding: 'utf8' }) 51 | .filter(entry => fs.statSync(path.join(packagesDir, entry)).isDirectory()) 52 | .map(dirName => { 53 | const absPath = path.join(packagesDir, dirName); 54 | const srcPath = path.join(absPath, 'src'); 55 | const packageJson = require(path.join(absPath, 'package.json')); 56 | return { 57 | name: packageJson.name, 58 | version: packageJson.version, 59 | isPrivate: packageJson.private, 60 | srcPath: fs.existsSync(srcPath) ? srcPath : undefined, 61 | dirName: dirName, 62 | }; 63 | }) 64 | .filter(pkg => !pkg.isPrivate && pkg.srcPath) 65 | .map(buildDocsForPackage); 66 | 67 | console.log('Generating Index'); 68 | const indexContent = template({ links }); 69 | fs.writeFileSync(path.join(outDir, 'index.html'), indexContent, 'utf8'); 70 | 71 | console.log('All done!'); 72 | -------------------------------------------------------------------------------- /utils/build.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const generateCrossPlatformPath = (...args) => { 4 | let result = path.join.apply(null, args); 5 | 6 | if (process.platform === 'win32') { 7 | result = result.replace(/\\/g, '/'); 8 | } 9 | 10 | return result; 11 | }; 12 | 13 | module.exports = { generateCrossPlatformPath }; 14 | --------------------------------------------------------------------------------