├── .gitignore
├── .jscsrc
├── .jshintrc
├── .travis.yml
├── README.md
├── RNOpenPGP.podspec
├── android
    ├── app
    │   ├── build.gradle
    │   └── src
    │   │   └── main
    │   │       ├── AndroidManifest.xml
    │   │       └── java
    │   │           └── com
    │   │               └── github
    │   │                   └── orhan
    │   │                       └── openpgp
    │   │                           ├── RNOpenPGPModule.java
    │   │                           └── RNOpenPGPPackage.java
    ├── build.gradle
    ├── gradle
    │   └── wrapper
    │   │   ├── gradle-wrapper.jar
    │   │   └── gradle-wrapper.properties
    ├── gradlew
    ├── gradlew.bat
    ├── local.properties
    └── settings.gradle
├── iOS
    ├── RNOpenPGP.h
    ├── RNOpenPGP.m
    └── RNOpenPGP.xcodeproj
    │   ├── project.pbxproj
    │   ├── project.xcworkspace
    │       ├── contents.xcworkspacedata
    │       └── xcuserdata
    │       │   ├── orhan.xcuserdatad
    │       │       └── UserInterfaceState.xcuserstate
    │       │   └── tenaciousmv.xcuserdatad
    │       │       └── UserInterfaceState.xcuserstate
    │   └── xcuserdata
    │       ├── orhan.xcuserdatad
    │           └── xcschemes
    │           │   ├── RNOpenPGP.xcscheme
    │           │   └── xcschememanagement.plist
    │       └── tenaciousmv.xcuserdatad
    │           └── xcschemes
    │               ├── RNRandomBytes.xcscheme
    │               └── xcschememanagement.plist
├── package.json
└── src
    ├── cleartext.js
    ├── compression
        ├── huffman.js
        ├── rawdeflate.js
        ├── rawinflate.js
        └── zlib.min.js
    ├── config
        ├── config.js
        ├── index.js
        └── localStorage.js
    ├── crypto
        ├── cfb.js
        ├── cipher
        │   ├── aes.js
        │   ├── blowfish.js
        │   ├── cast5.js
        │   ├── des.js
        │   ├── index.js
        │   └── twofish.js
        ├── crypto.js
        ├── hash
        │   ├── index.js
        │   ├── md5.js
        │   ├── ripe-md.js
        │   └── sha.js
        ├── index.js
        ├── isaac.js
        ├── pkcs1.js
        ├── public_key
        │   ├── dsa.js
        │   ├── elgamal.js
        │   ├── index.js
        │   ├── jsbn.js
        │   └── rsa.js
        ├── random.js
        ├── randomBytes.js
        └── signature.js
    ├── encoding
        ├── armor.js
        └── base64.js
    ├── enums.js
    ├── hkp.js
    ├── index.js
    ├── key.js
    ├── keyring
        ├── index.js
        ├── keyring.js
        └── localstore.js
    ├── message.js
    ├── openpgp.js
    ├── packet
        ├── all_packets.js
        ├── clone.js
        ├── compressed.js
        ├── index.js
        ├── literal.js
        ├── marker.js
        ├── one_pass_signature.js
        ├── packet.js
        ├── packetlist.js
        ├── public_key.js
        ├── public_key_encrypted_session_key.js
        ├── public_subkey.js
        ├── secret_key.js
        ├── secret_subkey.js
        ├── signature.js
        ├── sym_encrypted_integrity_protected.js
        ├── sym_encrypted_session_key.js
        ├── symmetrically_encrypted.js
        ├── trust.js
        ├── user_attribute.js
        └── userid.js
    ├── type
        ├── keyid.js
        ├── mpi.js
        └── s2k.js
    ├── util.js
    └── worker
        ├── async_proxy.js
        └── worker.js
/.gitignore:
--------------------------------------------------------------------------------
 1 | build/
 2 | .DS_Store
 3 | node_modules/
 4 | npm*
 5 | test/lib/
 6 | dist/
 7 | dist/*.tgz
 8 | dist/*_debug.js
 9 | openpgp.store/
10 | doc/
11 | 
--------------------------------------------------------------------------------
/.jscsrc:
--------------------------------------------------------------------------------
1 | {
2 |   "disallowTrailingWhitespace": true,
3 |   "validateIndentation": 2
4 | }
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
 1 | {
 2 |   "node": true,
 3 |   "browser": true,
 4 |   "nonew": true,
 5 |   "curly": true,
 6 |   "eqeqeq": true,
 7 |   "immed": true,
 8 |   "regexp": true,
 9 |   "evil": true,
10 |   "eqnull": true,
11 |   "expr": true,
12 |   "undef": true,
13 |   "unused": true,
14 |   "esnext": true,
15 | 
16 |   "globals": {
17 |     "console": true,
18 |     "Promise": true,
19 |     "importScripts": true,
20 |     "process": true,
21 |     "Event": true,
22 |     "describe": true,
23 |     "it": true,
24 |     "sinon": true,
25 |     "mocha": true,
26 |     "before": true,
27 |     "beforeEach": true,
28 |     "after": true,
29 |     "afterEach": true,
30 |     "escape": true,
31 |     "unescape": true,
32 |     "postMessage": true,
33 |     "resolves": true,
34 |     "rejects": true
35 |   }
36 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
 1 | sudo: false
 2 | language: node_js
 3 | cache:
 4 |   directories:
 5 |     - node_modules
 6 | addons:
 7 |     code_climate:
 8 |         repo_token: $CODECLIMATE_REPO_TOKEN
 9 | matrix:
10 |   fast_finish: true
11 |   include:
12 |     - node_js: "0.12"
13 |       env: OPENPGPJSTEST='unit' OPENPGP_NODE_JS='0.12'
14 |     - node_js: "4"
15 |       env: OPENPGPJSTEST='unit' OPENPGP_NODE_JS='4.2'
16 |     - node_js: "5"
17 |       env: OPENPGPJSTEST='unit' OPENPGP_NODE_JS='5'
18 |     - node_js: "4"
19 |       env: OPENPGPJSTEST='end2end-4' BROWSER='chrome 46'
20 |     - node_js: "4"
21 |       env: OPENPGPJSTEST='end2end-1' BROWSER='firefox 42'
22 |     - node_js: "4"
23 |       env: OPENPGPJSTEST='end2end-6' BROWSER='internet explorer 11'
24 |     - node_js: "4"
25 |       env: OPENPGPJSTEST='end2end-9' BROWSER='safari 9'
26 |     - node_js: "4"
27 |       env: OPENPGPJSTEST='end2end-0' BROWSER='firefox 38'
28 |     - node_js: "4"
29 |       env: OPENPGPJSTEST='end2end-2' BROWSER='firefox beta'
30 |     - node_js: "4"
31 |       env: OPENPGPJSTEST='end2end-3' BROWSER='chrome 38'
32 |     - node_js: "4"
33 |       env: OPENPGPJSTEST='end2end-5' BROWSER='chrome beta'
34 |     - node_js: "4"
35 |       env: OPENPGPJSTEST='end2end-7' BROWSER='microsoft edge 20.10240'
36 |     - node_js: "4"
37 |       env: OPENPGPJSTEST='end2end-8' BROWSER='safari 8'
38 |     - node_js: "4"
39 |       env: OPENPGPJSTEST='end2end-10' BROWSER='android 4.4'
40 |     - node_js: "4"
41 |       env: OPENPGPJSTEST='end2end-11' BROWSER='android 5.1'
42 |     - node_js: "4"
43 |       env: OPENPGPJSTEST='end2end-12' BROWSER='iphone 7.0'
44 |     - node_js: "4"
45 |       env: OPENPGPJSTEST='end2end-13' BROWSER='iphone 9.1'
46 |   allow_failures:
47 |     - env: OPENPGPJSTEST='end2end-0' BROWSER='firefox 38'
48 |     - env: OPENPGPJSTEST='end2end-2' BROWSER='firefox beta'
49 |     - env: OPENPGPJSTEST='end2end-3' BROWSER='chrome 38'
50 |     - env: OPENPGPJSTEST='end2end-5' BROWSER='chrome beta'
51 |     - env: OPENPGPJSTEST='end2end-7' BROWSER='microsoft edge 20.10240'
52 |     - env: OPENPGPJSTEST='end2end-8' BROWSER='safari 8'
53 |     - env: OPENPGPJSTEST='end2end-10' BROWSER='android 4.4'
54 |     - env: OPENPGPJSTEST='end2end-11' BROWSER='android 5.1'
55 |     - env: OPENPGPJSTEST='end2end-12' BROWSER='iphone 7.0'
56 |     - env: OPENPGPJSTEST='end2end-13' BROWSER='iphone 9.1'
57 | before_script:
58 |   - npm install -g grunt-cli codeclimate-test-reporter
59 | script:
60 |   - $TRAVIS_BUILD_DIR/travis.sh
61 | 
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
  1 | React-Native-OpenPGP
  2 | ==========
  3 | 
  4 | [React-Native-OpenPGP](http://openpgpjs.org/) is a Javascript implementation of the OpenPGP protocol based on [OpenPGP.js](https://github.com/openpgpjs/openpgpjs).
  5 | 
  6 | 
  7 | ## Getting started
  8 | 
  9 | #### Installation
 10 | 
 11 |     npm install --save react-native-openpgp
 12 |     
 13 |     // not needed if using auto-linking RN > 0.060
 14 |     react-native link react-native-openpgp
 15 | 
 16 | Alternatively you can add the Android and iOS modules library by following the official guide.
 17 | 
 18 | ## Usage
 19 | 
 20 | ```js
 21 | import * as openpgp from 'react-native-openpgp';
 22 | ```
 23 | 
 24 | #### Encrypt and decrypt *String* data with a password
 25 | 
 26 | ```js
 27 | var options, encrypted;
 28 | 
 29 | options = {
 30 |   data: 'Hello, World!',      // input as String
 31 |   passwords: ['secret stuff'] // multiple passwords possible
 32 | };
 33 | 
 34 | openpgp.encrypt(options)
 35 |   .then((ciphertext) => {
 36 |     encrypted = ciphertext.data; // '-----BEGIN PGP MESSAGE ... END PGP MESSAGE-----'
 37 |   })
 38 |   .catch((error) => {
 39 |     console.log("Something went wrong: " + error);
 40 |   });
 41 | ```
 42 | 
 43 | ```js
 44 | options = {
 45 |   message: openpgp.readMessage(encrypted), // parse armored message
 46 |   password: 'secret stuff'                         // decrypt with password
 47 | };
 48 | 
 49 | openpgp.decrypt(options)
 50 |   .then((plaintext) => {
 51 |     return plaintext.data; // 'Hello, World!'
 52 |   })
 53 |   .catch((error) => {
 54 |     console.log("Something went wrong: " + error);
 55 |   });
 56 | ```
 57 | 
 58 | #### Encrypt and decrypt *Uint8Array* data with PGP keys
 59 | 
 60 | ```js
 61 | var options, encrypted;
 62 | 
 63 | var pubkey = '-----BEGIN PGP PUBLIC KEY BLOCK ... END PGP PUBLIC KEY BLOCK-----';
 64 | var privkey = '-----BEGIN PGP PRIVATE KEY BLOCK ... END PGP PRIVATE KEY BLOCK-----';
 65 | 
 66 | options = {
 67 |   data: new Uint8Array([0x01, 0x01, 0x01]),           // input as Uint8Array
 68 |   publicKeys: openpgp.readArmoredKey(pubkey).keys,   // for encryption
 69 |   privateKeys: openpgp.readArmoredKey(privkey).keys, // for signing (optional)
 70 |   armor: false                                        // don't ASCII armor
 71 | };
 72 | 
 73 | openpgp.encrypt(options)
 74 |   .then((ciphertext) => {
 75 |     encrypted = ciphertext.message.packets.write(); // get raw encrypted packets as Uint8Array
 76 |   })
 77 |   .catch((error) => {
 78 |     console.log("Something went wrong: " + error);
 79 |   });
 80 | ```
 81 | 
 82 | ```js
 83 | options = {
 84 |   message: openpgp.readBinaryMessage(encrypted),             // parse encrypted bytes
 85 |   publicKeys: openpgp.readArmoredKey(pubkey).keys,     // for verification (optional)
 86 |   privateKey: openpgp.readArmoredKey(privkey).keys[0], // for decryption
 87 |   format: 'binary'                                      // output as Uint8Array
 88 | };
 89 | 
 90 | openpgp.decrypt(options)
 91 |   .then((plaintext) => {
 92 |     return plaintext.data // Uint8Array([0x01, 0x01, 0x01])
 93 |   })
 94 |   .catch((error) => {
 95 |     console.log("Something went wrong: " + error);
 96 |   });
 97 | ```
 98 | 
 99 | #### Generate new key pair
100 | 
101 | ```js
102 | var options = {
103 |   userIds: [{ name:'Jon Smith', email:'jon@example.com' }], // multiple user IDs
104 |   numBits: 2048,                                            // RSA key size
105 |   passphrase: 'super long and hard to guess secret'         // protects the private key
106 | };
107 | 
108 | openpgp.generateKey(options)
109 |   .then((key) => {
110 |     var privkey = key.privateKeyArmored; // '-----BEGIN PGP PRIVATE KEY BLOCK ... '
111 |     var pubkey = key.publicKeyArmored;   // '-----BEGIN PGP PUBLIC KEY BLOCK ... '
112 |   })
113 |   .catch((error) => {
114 |     console.log("Something went wrong: " + error);
115 |   });
116 | 
117 | ```
118 | 
--------------------------------------------------------------------------------
/RNOpenPGP.podspec:
--------------------------------------------------------------------------------
 1 | require "json"
 2 | 
 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
 4 | 
 5 | Pod::Spec.new do |s|
 6 |   s.name         = "RNOpenPGP"
 7 |   s.version      = package["version"]
 8 |   s.summary      = package["description"]
 9 |   s.homepage     = "https://github.com/orhan/react-native-openpgp"
10 |   s.license      = "MIT"
11 |   s.authors      = { "Place Holder" => "email@email.com" }
12 |   s.platforms    = { :ios => "9.0", :tvos => "9.0" }
13 |   s.source       = { :git => "https://github.com/orhan/react-native-openpgp.git", :tag => "v#{s.version}" }
14 | 
15 |   s.source_files = "ios/**/*.{h,m,swift}"
16 |   s.requires_arc = true
17 | 
18 |   s.dependency "React"
19 | end
20 | 
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'com.android.library'
 2 | 
 3 | android {
 4 |     compileSdkVersion 23
 5 |     buildToolsVersion "23.0.1"
 6 | 
 7 |     defaultConfig {
 8 |         minSdkVersion 16
 9 |         targetSdkVersion 22
10 |         versionCode 1
11 |         versionName "1.0"
12 |     }
13 | }
14 | 
15 | dependencies {
16 |     compile 'com.facebook.react:react-native:0.13.+'
17 | }
18 | 
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 | 
3 | 
4 | 
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/orhan/openpgp/RNOpenPGPModule.java:
--------------------------------------------------------------------------------
 1 | package com.github.orhan.openpgp;
 2 | 
 3 | import com.facebook.react.bridge.ReactMethod;
 4 | import com.facebook.react.bridge.ReactApplicationContext;
 5 | import com.facebook.react.bridge.Callback;
 6 | 
 7 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
 8 | 
 9 | import java.security.SecureRandom;
10 | 
11 | import android.util.Base64;
12 | 
13 | public class RNOpenPGPModule extends ReactContextBaseJavaModule {
14 | 
15 |   public RNOpenPGPModule(ReactApplicationContext reactContext) {
16 |     super(reactContext);
17 |   }
18 | 
19 |   @Override
20 |   public String getName() {
21 |     return "RNOpenPGP";
22 |   }
23 |   @ReactMethod
24 |   public void randomBytes(int size, Callback success) {
25 |     SecureRandom sr = new SecureRandom();
26 |     byte[] output = new byte[size];
27 |     sr.nextBytes(output);
28 |     String string = Base64.encodeToString(output, Base64.DEFAULT);
29 |     success.invoke(null, string);
30 |   }
31 | }
32 | 
--------------------------------------------------------------------------------
/android/app/src/main/java/com/github/orhan/openpgp/RNOpenPGPPackage.java:
--------------------------------------------------------------------------------
 1 | package com.github.orhan.openpgp;
 2 | 
 3 | import com.facebook.react.ReactPackage;
 4 | import com.facebook.react.bridge.JavaScriptModule;
 5 | import com.facebook.react.bridge.NativeModule;
 6 | import com.facebook.react.bridge.ReactApplicationContext;
 7 | import com.facebook.react.uimanager.ViewManager;
 8 | 
 9 | import java.util.ArrayList;
10 | import java.util.Collections;
11 | import java.util.List;
12 | 
13 | public class RNOpenPGPPackage implements ReactPackage {
14 | 
15 |   @Override
16 |   public List createNativeModules(
17 |                               ReactApplicationContext reactContext) {
18 |     List modules = new ArrayList<>();
19 | 
20 |     modules.add(new RNOpenPGPModule(reactContext));
21 | 
22 |     return modules;
23 |   }
24 | 
25 |   @Override
26 |   public List createViewManagers(ReactApplicationContext reactContext) {
27 |     return Collections.emptyList();
28 |   }
29 | 
30 |   @Override
31 |   public List> createJSModules() {
32 |     return Collections.emptyList();
33 |   }
34 | }
35 | 
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
 1 | buildscript {
 2 |     repositories {
 3 |         jcenter()
 4 |     }
 5 |     dependencies {
 6 |         classpath 'com.android.tools.build:gradle:1.3.0'
 7 | 
 8 |         // NOTE: Do not place your application dependencies here; they belong
 9 |         // in the individual module build.gradle files
10 |     }
11 | }
12 | 
13 | allprojects {
14 |     repositories {
15 |         mavenLocal()
16 |         jcenter()
17 |     }
18 | }
19 | 
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orhan/react-native-openpgp/922da5126c888f8f31e7ca889a6d018a1536fd9a/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Apr 10 02:20:41 CEST 2016
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-all.zip
7 | 
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
  1 | #!/usr/bin/env bash
  2 | 
  3 | ##############################################################################
  4 | ##
  5 | ##  Gradle start up script for UN*X
  6 | ##
  7 | ##############################################################################
  8 | 
  9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
 10 | DEFAULT_JVM_OPTS=""
 11 | 
 12 | APP_NAME="Gradle"
 13 | APP_BASE_NAME=`basename "$0"`
 14 | 
 15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
 16 | MAX_FD="maximum"
 17 | 
 18 | warn ( ) {
 19 |     echo "$*"
 20 | }
 21 | 
 22 | die ( ) {
 23 |     echo
 24 |     echo "$*"
 25 |     echo
 26 |     exit 1
 27 | }
 28 | 
 29 | # OS specific support (must be 'true' or 'false').
 30 | cygwin=false
 31 | msys=false
 32 | darwin=false
 33 | case "`uname`" in
 34 |   CYGWIN* )
 35 |     cygwin=true
 36 |     ;;
 37 |   Darwin* )
 38 |     darwin=true
 39 |     ;;
 40 |   MINGW* )
 41 |     msys=true
 42 |     ;;
 43 | esac
 44 | 
 45 | # Attempt to set APP_HOME
 46 | # Resolve links: $0 may be a link
 47 | PRG="$0"
 48 | # Need this for relative symlinks.
 49 | while [ -h "$PRG" ] ; do
 50 |     ls=`ls -ld "$PRG"`
 51 |     link=`expr "$ls" : '.*-> \(.*\)$'`
 52 |     if expr "$link" : '/.*' > /dev/null; then
 53 |         PRG="$link"
 54 |     else
 55 |         PRG=`dirname "$PRG"`"/$link"
 56 |     fi
 57 | done
 58 | SAVED="`pwd`"
 59 | cd "`dirname \"$PRG\"`/" >/dev/null
 60 | APP_HOME="`pwd -P`"
 61 | cd "$SAVED" >/dev/null
 62 | 
 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 64 | 
 65 | # Determine the Java command to use to start the JVM.
 66 | if [ -n "$JAVA_HOME" ] ; then
 67 |     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
 68 |         # IBM's JDK on AIX uses strange locations for the executables
 69 |         JAVACMD="$JAVA_HOME/jre/sh/java"
 70 |     else
 71 |         JAVACMD="$JAVA_HOME/bin/java"
 72 |     fi
 73 |     if [ ! -x "$JAVACMD" ] ; then
 74 |         die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
 75 | 
 76 | Please set the JAVA_HOME variable in your environment to match the
 77 | location of your Java installation."
 78 |     fi
 79 | else
 80 |     JAVACMD="java"
 81 |     which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 82 | 
 83 | Please set the JAVA_HOME variable in your environment to match the
 84 | location of your Java installation."
 85 | fi
 86 | 
 87 | # Increase the maximum file descriptors if we can.
 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
 89 |     MAX_FD_LIMIT=`ulimit -H -n`
 90 |     if [ $? -eq 0 ] ; then
 91 |         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
 92 |             MAX_FD="$MAX_FD_LIMIT"
 93 |         fi
 94 |         ulimit -n $MAX_FD
 95 |         if [ $? -ne 0 ] ; then
 96 |             warn "Could not set maximum file descriptor limit: $MAX_FD"
 97 |         fi
 98 |     else
 99 |         warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 |     fi
101 | fi
102 | 
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 |     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 | 
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 |     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 |     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 |     JAVACMD=`cygpath --unix "$JAVACMD"`
113 | 
114 |     # We build the pattern for arguments to be converted via cygpath
115 |     ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 |     SEP=""
117 |     for dir in $ROOTDIRSRAW ; do
118 |         ROOTDIRS="$ROOTDIRS$SEP$dir"
119 |         SEP="|"
120 |     done
121 |     OURCYGPATTERN="(^($ROOTDIRS))"
122 |     # Add a user-defined pattern to the cygpath arguments
123 |     if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 |         OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 |     fi
126 |     # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 |     i=0
128 |     for arg in "$@" ; do
129 |         CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 |         CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
131 | 
132 |         if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
133 |             eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 |         else
135 |             eval `echo args$i`="\"$arg\""
136 |         fi
137 |         i=$((i+1))
138 |     done
139 |     case $i in
140 |         (0) set -- ;;
141 |         (1) set -- "$args0" ;;
142 |         (2) set -- "$args0" "$args1" ;;
143 |         (3) set -- "$args0" "$args1" "$args2" ;;
144 |         (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 |         (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 |         (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 |         (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 |         (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 |         (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 |     esac
151 | fi
152 | 
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 |     JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 | 
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 | 
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
 1 | @if "%DEBUG%" == "" @echo off
 2 | @rem ##########################################################################
 3 | @rem
 4 | @rem  Gradle startup script for Windows
 5 | @rem
 6 | @rem ##########################################################################
 7 | 
 8 | @rem Set local scope for the variables with windows NT shell
 9 | if "%OS%"=="Windows_NT" setlocal
10 | 
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 | 
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 | 
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 | 
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 | 
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 | 
32 | goto fail
33 | 
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 | 
38 | if exist "%JAVA_EXE%" goto init
39 | 
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 | 
46 | goto fail
47 | 
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 | 
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 | 
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 | 
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 | 
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 | 
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 | 
69 | :execute
70 | @rem Setup the command line
71 | 
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 | 
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 | 
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 | 
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 | 
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 | 
90 | :omega
91 | 
--------------------------------------------------------------------------------
/android/local.properties:
--------------------------------------------------------------------------------
 1 | ## This file is automatically generated by Android Studio.
 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
 3 | #
 4 | # This file must *NOT* be checked into Version Control Systems,
 5 | # as it contains information specific to your local configuration.
 6 | #
 7 | # Location of the SDK. This is only used by Gradle.
 8 | # For customization when using a Version Control System, please read the
 9 | # header note.
10 | #Sun Apr 10 02:20:08 CEST 2016
11 | sdk.dir=/Users/orhan/Library/Android/sdk
12 | 
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'openpgp'
2 | include ':app'
3 | 
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.h:
--------------------------------------------------------------------------------
 1 | //  RNOpenPGP.h
 2 | 
 3 | #import 
 4 | #import 
 5 | #import 
 6 | 
 7 | @interface RNOpenPGP : NSObject
 8 | 
 9 | @end
10 | 
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.m:
--------------------------------------------------------------------------------
 1 | #import "RNOpenPGP.h"
 2 | #import 
 3 | #import 
 4 | 
 5 | @implementation RNOpenPGP
 6 | 
 7 | + (BOOL)requiresMainQueueSetup
 8 | {
 9 |     return YES;
10 | }
11 | 
12 | RCT_EXPORT_MODULE()
13 | 
14 | @synthesize bridge = _bridge;
15 | 
16 | RCT_EXPORT_METHOD(randomBytes:(NSUInteger)length
17 |                   callback:(RCTResponseSenderBlock)callback)
18 | {
19 |     callback(@[[NSNull null], [self randomBytes:length]]);
20 | }
21 | 
22 | - (NSString *) randomBytes:(NSUInteger)length
23 | {
24 |     NSMutableData* bytes = [NSMutableData dataWithLength:length];
25 |     SecRandomCopyBytes(kSecRandomDefault, length, [bytes mutableBytes]);
26 |     return [bytes base64EncodedStringWithOptions:0];
27 | }
28 | 
29 | - (NSDictionary *)constantsToExport
30 | {
31 |     return @{
32 |         @"seed": [self randomBytes:4096]
33 |     };
34 | };
35 | 
36 | @end
37 | 
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 | 
2 | 
4 |    
6 |    
7 | 
8 | 
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.xcodeproj/project.xcworkspace/xcuserdata/orhan.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orhan/react-native-openpgp/922da5126c888f8f31e7ca889a6d018a1536fd9a/iOS/RNOpenPGP.xcodeproj/project.xcworkspace/xcuserdata/orhan.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.xcodeproj/project.xcworkspace/xcuserdata/tenaciousmv.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orhan/react-native-openpgp/922da5126c888f8f31e7ca889a6d018a1536fd9a/iOS/RNOpenPGP.xcodeproj/project.xcworkspace/xcuserdata/tenaciousmv.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.xcodeproj/xcuserdata/orhan.xcuserdatad/xcschemes/RNOpenPGP.xcscheme:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 5 |    
 8 |       
 9 |          
15 |             
21 |             
22 |          
23 |       
24 |    
25 |    
30 |       
31 |       
32 |       
33 |       
34 |    
35 |    
45 |       
46 |          
52 |          
53 |       
54 |       
55 |       
56 |    
57 |    
63 |       
64 |          
70 |          
71 |       
72 |    
73 |    
75 |    
76 |    
79 |    
80 | 
81 | 
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.xcodeproj/xcuserdata/orhan.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 | 
 5 | 	SchemeUserState
 6 | 	
 7 | 		RNOpenPGP.xcscheme
 8 | 		
 9 | 			orderHint
10 | 			0
11 | 		
12 | 	
13 | 	SuppressBuildableAutocreation
14 | 	
15 | 		73EEC9381BFE4B1D00D468EB
16 | 		
17 | 			primary
18 | 			
19 | 		
20 | 	
21 | 
22 | 
23 | 
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.xcodeproj/xcuserdata/tenaciousmv.xcuserdatad/xcschemes/RNRandomBytes.xcscheme:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  5 |    
  8 |       
  9 |          
 15 |             
 21 |             
 22 |          
 23 |          
 29 |             
 35 |             
 36 |          
 37 |       
 38 |    
 39 |    
 44 |       
 45 |          
 47 |             
 53 |             
 54 |          
 55 |       
 56 |       
 57 |          
 63 |          
 64 |       
 65 |    
 66 |    
 75 |       
 76 |          
 82 |          
 83 |       
 84 |       
 85 |       
 86 |    
 87 |    
 93 |       
 94 |          
100 |          
101 |       
102 |    
103 |    
105 |    
106 |    
109 |    
110 | 
111 | 
--------------------------------------------------------------------------------
/iOS/RNOpenPGP.xcodeproj/xcuserdata/tenaciousmv.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 | 
 5 | 	SchemeUserState
 6 | 	
 7 | 		RNRandomBytes.xcscheme
 8 | 		
 9 | 			orderHint
10 | 			1
11 | 		
12 | 	
13 | 	SuppressBuildableAutocreation
14 | 	
15 | 		73EEC9381BFE4B1D00D468EB
16 | 		
17 | 			primary
18 | 			
19 | 		
20 | 		73EEC9431BFE4B1D00D468EB
21 | 		
22 | 			primary
23 | 			
24 | 		
25 | 	
26 | 
27 | 
28 | 
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "react-native-openpgp",
 3 |   "description": "React-Native OpenPGP is an OpenPGP.js implementation made to work under React-Native.",
 4 |   "version": "1.0.4",
 5 |   "license": "MIT",
 6 |   "engines": {
 7 |     "node": ">=0.8"
 8 |   },
 9 |   "keywords": [
10 |     "crypto",
11 |     "pgp",
12 |     "gpg",
13 |     "openpgp",
14 |     "react-component",
15 |     "react-native",
16 |     "randomBytes",
17 |     "rng",
18 |     "ios",
19 |     "android"
20 |   ],
21 |   "main": "src/openpgp.js",
22 |   "directories": {
23 |     "lib": "src"
24 |   },
25 |   "dependencies": {
26 |     "asmcrypto-lite": "^1.0.1",
27 |     "buffer": "^4.5.0",
28 |     "es6-promise": "3.1.2",
29 |     "node-fetch": "^1.3.3",
30 |     "node-localstorage": "~1.1.2",
31 |     "rusha": "^0.8.3"
32 |   },
33 |   "repository": {
34 |     "type": "git",
35 |     "url": "https://github.com/orhan/react-native-openpgp"
36 |   }
37 | }
38 | 
--------------------------------------------------------------------------------
/src/cleartext.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * @requires config
 20 |  * @requires encoding/armor
 21 |  * @requires enums
 22 |  * @requires packet
 23 |  * @module cleartext
 24 |  */
 25 | 
 26 | 'use strict';
 27 | 
 28 | import config from './config';
 29 | import packet from './packet';
 30 | import enums from './enums.js';
 31 | import armor from './encoding/armor.js';
 32 | 
 33 | /**
 34 |  * @class
 35 |  * @classdesc Class that represents an OpenPGP cleartext signed message.
 36 |  * See {@link http://tools.ietf.org/html/rfc4880#section-7}
 37 |  * @param  {String}     text       The cleartext of the signed message
 38 |  * @param  {module:packet/packetlist} packetlist The packetlist with signature packets or undefined
 39 |  *                                 if message not yet signed
 40 |  */
 41 | 
 42 | export function CleartextMessage(text, packetlist) {
 43 |   if (!(this instanceof CleartextMessage)) {
 44 |     return new CleartextMessage(text, packetlist);
 45 |   }
 46 |   // normalize EOL to canonical form 
 47 |   this.text = text.replace(/\r/g, '').replace(/[\t ]+\n/g, "\n").replace(/\n/g,"\r\n");
 48 |   this.packets = packetlist || new packet.List();
 49 | }
 50 | 
 51 | /**
 52 |  * Returns the key IDs of the keys that signed the cleartext message
 53 |  * @return {Array} array of keyid objects
 54 |  */
 55 | CleartextMessage.prototype.getSigningKeyIds = function() {
 56 |   var keyIds = [];
 57 |   var signatureList = this.packets.filterByTag(enums.packet.signature);
 58 |   signatureList.forEach(function(packet) {
 59 |     keyIds.push(packet.issuerKeyId);
 60 |   });
 61 |   return keyIds;
 62 | };
 63 | 
 64 | /**
 65 |  * Sign the cleartext message
 66 |  * @param  {Array} privateKeys private keys with decrypted secret key data for signing
 67 |  */
 68 | CleartextMessage.prototype.sign = function(privateKeys) {
 69 |   var packetlist = new packet.List();
 70 |   var literalDataPacket = new packet.Literal();
 71 |   literalDataPacket.setText(this.text);
 72 |   for (var i = 0; i < privateKeys.length; i++) {
 73 |     if (privateKeys[i].isPublic()) {
 74 |       throw new Error('Need private key for signing');
 75 |     }
 76 |     var signaturePacket = new packet.Signature();
 77 |     signaturePacket.signatureType = enums.signature.text;
 78 |     signaturePacket.hashAlgorithm = config.prefer_hash_algorithm;
 79 |     var signingKeyPacket = privateKeys[i].getSigningKeyPacket();
 80 |     signaturePacket.publicKeyAlgorithm = signingKeyPacket.algorithm;
 81 |     if (!signingKeyPacket.isDecrypted) {
 82 |       throw new Error('Private key is not decrypted.');
 83 |     }
 84 |     signaturePacket.sign(signingKeyPacket, literalDataPacket);
 85 |     packetlist.push(signaturePacket);
 86 |   }
 87 |   this.packets = packetlist;
 88 | };
 89 | 
 90 | /**
 91 |  * Verify signatures of cleartext signed message
 92 |  * @param {Array} keys array of keys to verify signatures
 93 |  * @return {Array<{keyid: module:type/keyid, valid: Boolean}>} list of signer's keyid and validity of signature
 94 |  */
 95 | CleartextMessage.prototype.verify = function(keys) {
 96 |   var result = [];
 97 |   var signatureList = this.packets.filterByTag(enums.packet.signature);
 98 |   var literalDataPacket = new packet.Literal();
 99 |   // we assume that cleartext signature is generated based on UTF8 cleartext
100 |   literalDataPacket.setText(this.text);
101 |   for (var i = 0; i < signatureList.length; i++) {
102 |     var keyPacket = null;
103 |     for (var j = 0; j < keys.length; j++) {
104 |       keyPacket = keys[j].getSigningKeyPacket(signatureList[i].issuerKeyId);
105 |       if (keyPacket) {
106 |         break;
107 |       }
108 |     }
109 | 
110 |     var verifiedSig = {};
111 |     if (keyPacket) {
112 |       verifiedSig.keyid = signatureList[i].issuerKeyId;
113 |       verifiedSig.valid = signatureList[i].verify(keyPacket, literalDataPacket);
114 |     } else {
115 |       verifiedSig.keyid = signatureList[i].issuerKeyId;
116 |       verifiedSig.valid = null;
117 |     }
118 |     result.push(verifiedSig);
119 |   }
120 |   return result;
121 | };
122 | 
123 | /**
124 |  * Get cleartext
125 |  * @return {String} cleartext of message
126 |  */
127 | CleartextMessage.prototype.getText = function() {
128 |   // normalize end of line to \n
129 |   return this.text.replace(/\r\n/g,"\n");
130 | };
131 | 
132 | /**
133 |  * Returns ASCII armored text of cleartext signed message
134 |  * @return {String} ASCII armor
135 |  */
136 | CleartextMessage.prototype.armor = function() {
137 |   var body = {
138 |     hash: enums.read(enums.hash, config.prefer_hash_algorithm).toUpperCase(),
139 |     text: this.text,
140 |     data: this.packets.write()
141 |   };
142 |   return armor.encode(enums.armor.signed, body);
143 | };
144 | 
145 | 
146 | /**
147 |  * reads an OpenPGP cleartext signed message and returns a CleartextMessage object
148 |  * @param {String} armoredText text to be parsed
149 |  * @return {module:cleartext~CleartextMessage} new cleartext message object
150 |  * @static
151 |  */
152 | export function readArmored(armoredText) {
153 |   var input = armor.decode(armoredText);
154 |   if (input.type !== enums.armor.signed) {
155 |     throw new Error('No cleartext signed message.');
156 |   }
157 |   var packetlist = new packet.List();
158 |   packetlist.read(input.data);
159 |   verifyHeaders(input.headers, packetlist);
160 |   var newMessage = new CleartextMessage(input.text, packetlist);
161 |   return newMessage;
162 | }
163 | 
164 | /**
165 |  * Compare hash algorithm specified in the armor header with signatures
166 |  * @private
167 |  * @param  {Array} headers    Armor headers
168 |  * @param  {module:packet/packetlist} packetlist The packetlist with signature packets
169 |  */
170 | function verifyHeaders(headers, packetlist) {
171 |   var checkHashAlgos = function(hashAlgos) {
172 |     function check(algo) {
173 |       return packetlist[i].hashAlgorithm === algo;
174 |     }
175 |     for (var i = 0; i < packetlist.length; i++) {
176 |       if (packetlist[i].tag === enums.packet.signature && !hashAlgos.some(check)) {
177 |         return false;
178 |       }
179 |     }
180 |     return true;
181 |   };
182 |   var oneHeader = null;
183 |   var hashAlgos = [];
184 |   headers.forEach(function(header) {
185 |     oneHeader = header.match(/Hash: (.+)/); // get header value
186 |     if (oneHeader) {
187 |       oneHeader = oneHeader[1].replace(/\s/g, '');  // remove whitespace
188 |       oneHeader = oneHeader.split(',');
189 |       oneHeader = oneHeader.map(function(hash) {
190 |         hash = hash.toLowerCase();
191 |         try {
192 |           return enums.write(enums.hash, hash);
193 |         } catch (e) {
194 |           throw new Error('Unknown hash algorithm in armor header: ' + hash);
195 |         }
196 |       });
197 |       hashAlgos = hashAlgos.concat(oneHeader);
198 |     } else {
199 |       throw new Error('Only "Hash" header allowed in cleartext signed message');
200 |     }
201 |   });
202 |   if (!hashAlgos.length && !checkHashAlgos([enums.hash.md5])) {
203 |     throw new Error('If no "Hash" header in cleartext signed message, then only MD5 signatures allowed');
204 |   } else if (!checkHashAlgos(hashAlgos)) {
205 |     throw new Error('Hash algorithm mismatch in armor header and signature');
206 |   }
207 | }
208 | 
--------------------------------------------------------------------------------
/src/compression/huffman.js:
--------------------------------------------------------------------------------
 1 | 
 2 | /**
 3 |  * build huffman table from length list.
 4 |  * @param {!(Array.|Uint8Array)} lengths length list.
 5 |  * @return {!Array} huffman table.
 6 |  */
 7 | export function buildHuffmanTable(lengths) {
 8 |     /** @type {number} length list size. */
 9 |     var listSize = lengths.length;
10 |     /** @type {number} max code length for table size. */
11 |     var maxCodeLength = 0;
12 |     /** @type {number} min code length for table size. */
13 |     var minCodeLength = Number.POSITIVE_INFINITY;
14 |     /** @type {number} table size. */
15 |     var size;
16 |     /** @type {!(Array|Uint8Array)} huffman code table. */
17 |     var table;
18 |     /** @type {number} bit length. */
19 |     var bitLength;
20 |     /** @type {number} huffman code. */
21 |     var code;
22 |     /**
23 |      * サイズが 2^maxlength 個のテーブルを埋めるためのスキップ長.
24 |      * @type {number} skip length for table filling.
25 |      */
26 |     var skip;
27 |     /** @type {number} reversed code. */
28 |     var reversed;
29 |     /** @type {number} reverse temp. */
30 |     var rtemp;
31 |     /** @type {number} loop counter. */
32 |     var i;
33 |     /** @type {number} loop limit. */
34 |     var il;
35 |     /** @type {number} loop counter. */
36 |     var j;
37 |     /** @type {number} table value. */
38 |     var value;
39 | 
40 |     // Math.max は遅いので最長の値は for-loop で取得する
41 |     for (i = 0, il = listSize; i < il; ++i) {
42 |       if (lengths[i] > maxCodeLength) {
43 |         maxCodeLength = lengths[i];
44 |       }
45 |       if (lengths[i] < minCodeLength) {
46 |         minCodeLength = lengths[i];
47 |       }
48 |     }
49 | 
50 |     size = 1 << maxCodeLength;
51 |     table = new (Uint32Array)(size);
52 | 
53 |     // ビット長の短い順からハフマン符号を割り当てる
54 |     for (bitLength = 1, code = 0, skip = 2; bitLength <= maxCodeLength;) {
55 |       for (i = 0; i < listSize; ++i) {
56 |         if (lengths[i] === bitLength) {
57 |           // ビットオーダーが逆になるためビット長分並びを反転する
58 |           for (reversed = 0, rtemp = code, j = 0; j < bitLength; ++j) {
59 |             reversed = (reversed << 1) | (rtemp & 1);
60 |             rtemp >>= 1;
61 |           }
62 | 
63 |           // 最大ビット長をもとにテーブルを作るため、
64 |           // 最大ビット長以外では 0 / 1 どちらでも良い箇所ができる
65 |           // そのどちらでも良い場所は同じ値で埋めることで
66 |           // 本来のビット長以上のビット数取得しても問題が起こらないようにする
67 |           value = (bitLength << 16) | i;
68 |           for (j = reversed; j < size; j += skip) {
69 |             table[j] = value;
70 |           }
71 | 
72 |           ++code;
73 |         }
74 |       }
75 | 
76 |       // 次のビット長へ
77 |       ++bitLength;
78 |       code <<= 1;
79 |       skip <<= 1;
80 |     }
81 | 
82 |     return [table, maxCodeLength, minCodeLength];
83 | }
84 | 
85 | /* vim:set expandtab ts=2 sw=2 tw=80: */
86 | 
--------------------------------------------------------------------------------
/src/config/config.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /**
19 |  * This object contains configuration values.
20 |  * @requires enums
21 |  * @property {Integer} prefer_hash_algorithm
22 |  * @property {Integer} encryption_cipher
23 |  * @property {Integer} compression
24 |  * @property {Boolean} show_version
25 |  * @property {Boolean} show_comment
26 |  * @property {Boolean} integrity_protect
27 |  * @property {String} keyserver
28 |  * @property {Boolean} debug If enabled, debug messages will be printed
29 |  * @module config/config
30 |  */
31 | 
32 | 'use strict';
33 | 
34 | import enums from '../enums.js';
35 | 
36 | export default {
37 |   prefer_hash_algorithm: enums.hash.sha256,
38 |   encryption_cipher: enums.symmetric.aes256,
39 |   compression: enums.compression.zip,
40 |   integrity_protect: true, // use integrity protection for symmetric encryption
41 |   ignore_mdc_error: false, // fail on decrypt if message is not integrity protected
42 |   rsa_blinding: true,
43 |   useNative: true, // use native node.js crypto and Web Crypto apis (if available)
44 |   zeroCopy: false, // use transferable objects between the Web Worker and main thread
45 |   debug: false,
46 |   show_version: true,
47 |   show_comment: true,
48 |   versionstring: "React-Native-OpenPGP.js 0.1",
49 |   commentstring: "http://openpgpjs.org",
50 |   keyserver: "https://keyserver.ubuntu.com",
51 |   node_store: './openpgp.store'
52 | };
53 | 
--------------------------------------------------------------------------------
/src/config/index.js:
--------------------------------------------------------------------------------
1 | /**
2 |  * @see module:config/config
3 |  * @module config
4 |  */
5 | 
6 | 'use strict';
7 | 
8 | export { default } from './config.js';
--------------------------------------------------------------------------------
/src/config/localStorage.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * This object storing and retrieving configuration from HTML5 local storage.
 3 |  * @module config/localStorage
 4 |  */
 5 | 
 6 | 'use strict';
 7 | 
 8 | /**
 9 |  * @constructor
10 |  */
11 | export default function LocalStorage() {}
12 | 
13 | /**
14 |  * Reads the config out of the HTML5 local storage
15 |  * and initializes the object config.
16 |  * if config is null the default config will be used
17 |  */
18 | LocalStorage.prototype.read = function () {
19 |   var raw = window.localStorage.getItem("config");
20 |   var cf = (raw === null ? null : JSON.parse(raw));
21 |   if (cf === null) {
22 |     this.config = this.default_config;
23 |     this.write();
24 |   } else {
25 |     this.config = cf;
26 |   }
27 | };
28 | 
29 | /**
30 |  * Writes the config to HTML5 local storage
31 |  */
32 | LocalStorage.prototype.write = function () {
33 |   window.localStorage.setItem("config", JSON.stringify(this.config));
34 | };
35 | 
--------------------------------------------------------------------------------
/src/crypto/cipher/index.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @requires crypto/cipher/aes
 3 |  * @requires crypto/cipher/blowfish
 4 |  * @requires crypto/cipher/cast5
 5 |  * @requires crypto/cipher/twofish
 6 |  * @module crypto/cipher
 7 |  */
 8 | 
 9 | 'use strict';
10 | 
11 | import desModule from './des.js';
12 | import aes from './aes.js';
13 | import cast5 from './cast5.js';
14 | import twofish from './twofish.js';
15 | import blowfish from './blowfish.js';
16 | 
17 | export default {
18 |   /** @see module:crypto/cipher/aes */
19 |   aes128: aes[128],
20 |   aes192: aes[192],
21 |   aes256: aes[256],
22 |   /** @see module:crypto/cipher/des.originalDes */
23 |   des: desModule.originalDes,
24 |   /** @see module:crypto/cipher/des.des */
25 |   tripledes: desModule.des,
26 |   /** @see module:crypto/cipher/cast5 */
27 |   cast5: cast5,
28 |   /** @see module:crypto/cipher/twofish */
29 |   twofish: twofish,
30 |   /** @see module:crypto/cipher/blowfish */
31 |   blowfish: blowfish,
32 |   /** Not implemented */
33 |   idea: function() {
34 |     throw new Error('IDEA symmetric-key algorithm not implemented');
35 |   }
36 | };
37 | 
--------------------------------------------------------------------------------
/src/crypto/hash/index.js:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @requires crypto/hash/sha
  3 |  * @requires crypto/hash/md5
  4 |  * @requires crypto/hash/ripe-md
  5 |  * @requires util
  6 |  * @module crypto/hash
  7 |  */
  8 | 
  9 | 'use strict';
 10 | 
 11 | import sha from './sha.js';
 12 | import asmCrypto from 'asmcrypto-lite';
 13 | import Rusha from 'rusha';
 14 | import md5 from './md5.js';
 15 | import ripemd from './ripe-md.js';
 16 | import util from '../../util.js';
 17 | 
 18 | const rusha = new Rusha(),
 19 |   nodeCrypto = util.getNodeCrypto(),
 20 |   Buffer = util.getNodeBuffer();
 21 | 
 22 | function node_hash(type) {
 23 |   return function (data) {
 24 |     var shasum = nodeCrypto.createHash(type);
 25 |     shasum.update(new Buffer(data));
 26 |     return new Uint8Array(shasum.digest());
 27 |   };
 28 | }
 29 | 
 30 | var hash_fns;
 31 | if(nodeCrypto) { // Use Node native crypto for all hash functions
 32 | 
 33 |   hash_fns = {
 34 |     md5: node_hash('md5'),
 35 |     sha1: node_hash('sha1'),
 36 |     sha224: node_hash('sha224'),
 37 |     sha256: node_hash('sha256'),
 38 |     sha384: node_hash('sha384'),
 39 |     sha512: node_hash('sha512'),
 40 |     ripemd: node_hash('ripemd160')
 41 |   };
 42 | 
 43 | } else { // Use JS fallbacks
 44 | 
 45 |   hash_fns = {
 46 |     /** @see module:crypto/hash/md5 */
 47 |     md5: md5,
 48 |     /** @see module:rusha */
 49 |     sha1: function(data) {
 50 |       return util.str2Uint8Array(util.hex2bin(rusha.digest(data)));
 51 |     },
 52 |     /** @see module:crypto/hash/sha.sha224 */
 53 |     sha224: sha.sha224,
 54 |     /** @see module:asmcrypto */
 55 |     sha256: asmCrypto.SHA256.bytes,
 56 |     /** @see module:crypto/hash/sha.sha384 */
 57 |     sha384: sha.sha384,
 58 |     /** @see module:crypto/hash/sha.sha512 */
 59 |     sha512: sha.sha512,
 60 |     /** @see module:crypto/hash/ripe-md */
 61 |     ripemd: ripemd
 62 |   };
 63 | }
 64 | 
 65 | export default {
 66 | 
 67 |   md5: hash_fns.md5,
 68 |   sha1: hash_fns.sha1,
 69 |   sha224: hash_fns.sha224,
 70 |   sha256: hash_fns.sha256,
 71 |   sha384: hash_fns.sha384,
 72 |   sha512: hash_fns.sha512,
 73 |   ripemd: hash_fns.ripemd,
 74 | 
 75 |   /**
 76 |    * Create a hash on the specified data using the specified algorithm
 77 |    * @param {module:enums.hash} algo Hash algorithm type (see {@link http://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4})
 78 |    * @param {Uint8Array} data Data to be hashed
 79 |    * @return {Uint8Array} hash value
 80 |    */
 81 |   digest: function(algo, data) {
 82 |     switch (algo) {
 83 |       case 1:
 84 |         // - MD5 [HAC]
 85 |         return this.md5(data);
 86 |       case 2:
 87 |         // - SHA-1 [FIPS180]
 88 |         return this.sha1(data);
 89 |       case 3:
 90 |         // - RIPE-MD/160 [HAC]
 91 |         return this.ripemd(data);
 92 |       case 8:
 93 |         // - SHA256 [FIPS180]
 94 |         return this.sha256(data);
 95 |       case 9:
 96 |         // - SHA384 [FIPS180]
 97 |         return this.sha384(data);
 98 |       case 10:
 99 |         // - SHA512 [FIPS180]
100 |         return this.sha512(data);
101 |       case 11:
102 |         // - SHA224 [FIPS180]
103 |         return this.sha224(data);
104 |       default:
105 |         throw new Error('Invalid hash function.');
106 |     }
107 |   },
108 | 
109 |   /**
110 |    * Returns the hash size in bytes of the specified hash algorithm type
111 |    * @param {module:enums.hash} algo Hash algorithm type (See {@link http://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4})
112 |    * @return {Integer} Size in bytes of the resulting hash
113 |    */
114 |   getHashByteLength: function(algo) {
115 |     switch (algo) {
116 |       case 1:
117 |         // - MD5 [HAC]
118 |         return 16;
119 |       case 2:
120 |         // - SHA-1 [FIPS180]
121 |       case 3:
122 |         // - RIPE-MD/160 [HAC]
123 |         return 20;
124 |       case 8:
125 |         // - SHA256 [FIPS180]
126 |         return 32;
127 |       case 9:
128 |         // - SHA384 [FIPS180]
129 |         return 48;
130 |       case 10:
131 |         // - SHA512 [FIPS180]
132 |         return 64;
133 |       case 11:
134 |         // - SHA224 [FIPS180]
135 |         return 28;
136 |       default:
137 |         throw new Error('Invalid hash algorithm.');
138 |     }
139 |   }
140 | };
141 | 
--------------------------------------------------------------------------------
/src/crypto/hash/md5.js:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * A fast MD5 JavaScript implementation
  3 |  * Copyright (c) 2012 Joseph Myers
  4 |  * http://www.myersdaily.org/joseph/javascript/md5-text.html
  5 |  *
  6 |  * Permission to use, copy, modify, and distribute this software
  7 |  * and its documentation for any purposes and without
  8 |  * fee is hereby granted provided that this copyright notice
  9 |  * appears in all copies.
 10 |  *
 11 |  * Of course, this soft is provided "as is" without express or implied
 12 |  * warranty of any kind.
 13 |  */
 14 | 
 15 | /**
 16 |  * @requires util
 17 |  * @module crypto/hash/md5
 18 |  */
 19 | 
 20 | 'use strict';
 21 | 
 22 | import util from '../../util.js';
 23 | 
 24 | /**
 25 |  * MD5 hash
 26 |  * @param {String} entree string to hash
 27 |  */
 28 | export default function(entree) {
 29 |   var hex = md5(util.Uint8Array2str(entree));
 30 |   var bin = util.str2Uint8Array(util.hex2bin(hex));
 31 |   return bin;
 32 | }
 33 | 
 34 | function md5cycle(x, k) {
 35 |   var a = x[0],
 36 |     b = x[1],
 37 |     c = x[2],
 38 |     d = x[3];
 39 | 
 40 |   a = ff(a, b, c, d, k[0], 7, -680876936);
 41 |   d = ff(d, a, b, c, k[1], 12, -389564586);
 42 |   c = ff(c, d, a, b, k[2], 17, 606105819);
 43 |   b = ff(b, c, d, a, k[3], 22, -1044525330);
 44 |   a = ff(a, b, c, d, k[4], 7, -176418897);
 45 |   d = ff(d, a, b, c, k[5], 12, 1200080426);
 46 |   c = ff(c, d, a, b, k[6], 17, -1473231341);
 47 |   b = ff(b, c, d, a, k[7], 22, -45705983);
 48 |   a = ff(a, b, c, d, k[8], 7, 1770035416);
 49 |   d = ff(d, a, b, c, k[9], 12, -1958414417);
 50 |   c = ff(c, d, a, b, k[10], 17, -42063);
 51 |   b = ff(b, c, d, a, k[11], 22, -1990404162);
 52 |   a = ff(a, b, c, d, k[12], 7, 1804603682);
 53 |   d = ff(d, a, b, c, k[13], 12, -40341101);
 54 |   c = ff(c, d, a, b, k[14], 17, -1502002290);
 55 |   b = ff(b, c, d, a, k[15], 22, 1236535329);
 56 | 
 57 |   a = gg(a, b, c, d, k[1], 5, -165796510);
 58 |   d = gg(d, a, b, c, k[6], 9, -1069501632);
 59 |   c = gg(c, d, a, b, k[11], 14, 643717713);
 60 |   b = gg(b, c, d, a, k[0], 20, -373897302);
 61 |   a = gg(a, b, c, d, k[5], 5, -701558691);
 62 |   d = gg(d, a, b, c, k[10], 9, 38016083);
 63 |   c = gg(c, d, a, b, k[15], 14, -660478335);
 64 |   b = gg(b, c, d, a, k[4], 20, -405537848);
 65 |   a = gg(a, b, c, d, k[9], 5, 568446438);
 66 |   d = gg(d, a, b, c, k[14], 9, -1019803690);
 67 |   c = gg(c, d, a, b, k[3], 14, -187363961);
 68 |   b = gg(b, c, d, a, k[8], 20, 1163531501);
 69 |   a = gg(a, b, c, d, k[13], 5, -1444681467);
 70 |   d = gg(d, a, b, c, k[2], 9, -51403784);
 71 |   c = gg(c, d, a, b, k[7], 14, 1735328473);
 72 |   b = gg(b, c, d, a, k[12], 20, -1926607734);
 73 | 
 74 |   a = hh(a, b, c, d, k[5], 4, -378558);
 75 |   d = hh(d, a, b, c, k[8], 11, -2022574463);
 76 |   c = hh(c, d, a, b, k[11], 16, 1839030562);
 77 |   b = hh(b, c, d, a, k[14], 23, -35309556);
 78 |   a = hh(a, b, c, d, k[1], 4, -1530992060);
 79 |   d = hh(d, a, b, c, k[4], 11, 1272893353);
 80 |   c = hh(c, d, a, b, k[7], 16, -155497632);
 81 |   b = hh(b, c, d, a, k[10], 23, -1094730640);
 82 |   a = hh(a, b, c, d, k[13], 4, 681279174);
 83 |   d = hh(d, a, b, c, k[0], 11, -358537222);
 84 |   c = hh(c, d, a, b, k[3], 16, -722521979);
 85 |   b = hh(b, c, d, a, k[6], 23, 76029189);
 86 |   a = hh(a, b, c, d, k[9], 4, -640364487);
 87 |   d = hh(d, a, b, c, k[12], 11, -421815835);
 88 |   c = hh(c, d, a, b, k[15], 16, 530742520);
 89 |   b = hh(b, c, d, a, k[2], 23, -995338651);
 90 | 
 91 |   a = ii(a, b, c, d, k[0], 6, -198630844);
 92 |   d = ii(d, a, b, c, k[7], 10, 1126891415);
 93 |   c = ii(c, d, a, b, k[14], 15, -1416354905);
 94 |   b = ii(b, c, d, a, k[5], 21, -57434055);
 95 |   a = ii(a, b, c, d, k[12], 6, 1700485571);
 96 |   d = ii(d, a, b, c, k[3], 10, -1894986606);
 97 |   c = ii(c, d, a, b, k[10], 15, -1051523);
 98 |   b = ii(b, c, d, a, k[1], 21, -2054922799);
 99 |   a = ii(a, b, c, d, k[8], 6, 1873313359);
100 |   d = ii(d, a, b, c, k[15], 10, -30611744);
101 |   c = ii(c, d, a, b, k[6], 15, -1560198380);
102 |   b = ii(b, c, d, a, k[13], 21, 1309151649);
103 |   a = ii(a, b, c, d, k[4], 6, -145523070);
104 |   d = ii(d, a, b, c, k[11], 10, -1120210379);
105 |   c = ii(c, d, a, b, k[2], 15, 718787259);
106 |   b = ii(b, c, d, a, k[9], 21, -343485551);
107 | 
108 |   x[0] = add32(a, x[0]);
109 |   x[1] = add32(b, x[1]);
110 |   x[2] = add32(c, x[2]);
111 |   x[3] = add32(d, x[3]);
112 | 
113 | }
114 | 
115 | function cmn(q, a, b, x, s, t) {
116 |   a = add32(add32(a, q), add32(x, t));
117 |   return add32((a << s) | (a >>> (32 - s)), b);
118 | }
119 | 
120 | function ff(a, b, c, d, x, s, t) {
121 |   return cmn((b & c) | ((~b) & d), a, b, x, s, t);
122 | }
123 | 
124 | function gg(a, b, c, d, x, s, t) {
125 |   return cmn((b & d) | (c & (~d)), a, b, x, s, t);
126 | }
127 | 
128 | function hh(a, b, c, d, x, s, t) {
129 |   return cmn(b ^ c ^ d, a, b, x, s, t);
130 | }
131 | 
132 | function ii(a, b, c, d, x, s, t) {
133 |   return cmn(c ^ (b | (~d)), a, b, x, s, t);
134 | }
135 | 
136 | function md51(s) {
137 |   var n = s.length,
138 |     state = [1732584193, -271733879, -1732584194, 271733878],
139 |     i;
140 |   for (i = 64; i <= s.length; i += 64) {
141 |     md5cycle(state, md5blk(s.substring(i - 64, i)));
142 |   }
143 |   s = s.substring(i - 64);
144 |   var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
145 |   for (i = 0; i < s.length; i++) {
146 |     tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
147 |   }
148 |   tail[i >> 2] |= 0x80 << ((i % 4) << 3);
149 |   if (i > 55) {
150 |     md5cycle(state, tail);
151 |     for (i = 0; i < 16; i++) {
152 |       tail[i] = 0;
153 |     }
154 |   }
155 |   tail[14] = n * 8;
156 |   md5cycle(state, tail);
157 |   return state;
158 | }
159 | 
160 | /* there needs to be support for Unicode here,
161 |  * unless we pretend that we can redefine the MD-5
162 |  * algorithm for multi-byte characters (perhaps
163 |  * by adding every four 16-bit characters and
164 |  * shortening the sum to 32 bits). Otherwise
165 |  * I suggest performing MD-5 as if every character
166 |  * was two bytes--e.g., 0040 0025 = @%--but then
167 |  * how will an ordinary MD-5 sum be matched?
168 |  * There is no way to standardize text to something
169 |  * like UTF-8 before transformation; speed cost is
170 |  * utterly prohibitive. The JavaScript standard
171 |  * itself needs to look at this: it should start
172 |  * providing access to strings as preformed UTF-8
173 |  * 8-bit unsigned value arrays.
174 |  */
175 | function md5blk(s) { /* I figured global was faster.   */
176 |   var md5blks = [],
177 |     i; /* Andy King said do it this way. */
178 |   for (i = 0; i < 64; i += 4) {
179 |     md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) <<
180 |       24);
181 |   }
182 |   return md5blks;
183 | }
184 | 
185 | var hex_chr = '0123456789abcdef'.split('');
186 | 
187 | function rhex(n) {
188 |   var s = '',
189 |     j = 0;
190 |   for (; j < 4; j++) {
191 |     s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
192 |   }
193 |   return s;
194 | }
195 | 
196 | function hex(x) {
197 |   for (var i = 0; i < x.length; i++) {
198 |     x[i] = rhex(x[i]);
199 |   }
200 |   return x.join('');
201 | }
202 | 
203 | function md5(s) {
204 |   return hex(md51(s));
205 | }
206 | 
207 | /* this function is much faster,
208 | so if possible we use it. Some IEs
209 | are the only ones I know of that
210 | need the idiotic second function,
211 | generated by an if clause.  */
212 | 
213 | function add32(a, b) {
214 |   return (a + b) & 0xFFFFFFFF;
215 | }
216 | 
--------------------------------------------------------------------------------
/src/crypto/hash/ripe-md.js:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * CryptoMX Tools
  3 |  * Copyright (C) 2004 - 2006 Derek Buitenhuis
  4 |  *
  5 |  * This program is free software; you can redistribute it and/or
  6 |  * modify it under the terms of the GNU General Public License
  7 |  * as published by the Free Software Foundation; either version 2
  8 |  * of the License, or (at your option) any later version.
  9 |  *
 10 |  * This program is distributed in the hope that it will be useful,
 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 |  * GNU General Public License for more details.
 14 |  *
 15 |  * You should have received a copy of the GNU General Public License
 16 |  * along with this program; if not, write to the Free Software
 17 |  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 18 |  */
 19 | 
 20 | /* Modified by Recurity Labs GmbH
 21 |  */
 22 | 
 23 | /* Modified by ProtonTech AG
 24 |  */
 25 | 
 26 | /**
 27 |  * @requires util
 28 |  * @module crypto/hash/ripe-md
 29 |  */
 30 | 
 31 | import util from '../../util.js';
 32 | 
 33 | var RMDsize = 160;
 34 | var X = [];
 35 | 
 36 | function ROL(x, n) {
 37 |   return new Number((x << n) | (x >>> (32 - n)));
 38 | }
 39 | 
 40 | function F(x, y, z) {
 41 |   return new Number(x ^ y ^ z);
 42 | }
 43 | 
 44 | function G(x, y, z) {
 45 |   return new Number((x & y) | (~x & z));
 46 | }
 47 | 
 48 | function H(x, y, z) {
 49 |   return new Number((x | ~y) ^ z);
 50 | }
 51 | 
 52 | function I(x, y, z) {
 53 |   return new Number((x & z) | (y & ~z));
 54 | }
 55 | 
 56 | function J(x, y, z) {
 57 |   return new Number(x ^ (y | ~z));
 58 | }
 59 | 
 60 | function mixOneRound(a, b, c, d, e, x, s, roundNumber) {
 61 |   switch (roundNumber) {
 62 |     case 0:
 63 |       a += F(b, c, d) + x + 0x00000000;
 64 |       break;
 65 |     case 1:
 66 |       a += G(b, c, d) + x + 0x5a827999;
 67 |       break;
 68 |     case 2:
 69 |       a += H(b, c, d) + x + 0x6ed9eba1;
 70 |       break;
 71 |     case 3:
 72 |       a += I(b, c, d) + x + 0x8f1bbcdc;
 73 |       break;
 74 |     case 4:
 75 |       a += J(b, c, d) + x + 0xa953fd4e;
 76 |       break;
 77 |     case 5:
 78 |       a += J(b, c, d) + x + 0x50a28be6;
 79 |       break;
 80 |     case 6:
 81 |       a += I(b, c, d) + x + 0x5c4dd124;
 82 |       break;
 83 |     case 7:
 84 |       a += H(b, c, d) + x + 0x6d703ef3;
 85 |       break;
 86 |     case 8:
 87 |       a += G(b, c, d) + x + 0x7a6d76e9;
 88 |       break;
 89 |     case 9:
 90 |       a += F(b, c, d) + x + 0x00000000;
 91 |       break;
 92 | 
 93 |     default:
 94 |       throw new Error("Bogus round number");
 95 |       break;
 96 |   }
 97 | 
 98 |   a = ROL(a, s) + e;
 99 |   c = ROL(c, 10);
100 | 
101 |   a &= 0xffffffff;
102 |   b &= 0xffffffff;
103 |   c &= 0xffffffff;
104 |   d &= 0xffffffff;
105 |   e &= 0xffffffff;
106 | 
107 |   var retBlock = [];
108 |   retBlock[0] = a;
109 |   retBlock[1] = b;
110 |   retBlock[2] = c;
111 |   retBlock[3] = d;
112 |   retBlock[4] = e;
113 |   retBlock[5] = x;
114 |   retBlock[6] = s;
115 | 
116 |   return retBlock;
117 | }
118 | 
119 | function MDinit(MDbuf) {
120 |   MDbuf[0] = 0x67452301;
121 |   MDbuf[1] = 0xefcdab89;
122 |   MDbuf[2] = 0x98badcfe;
123 |   MDbuf[3] = 0x10325476;
124 |   MDbuf[4] = 0xc3d2e1f0;
125 | }
126 | 
127 | var ROLs = [
128 |   [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
129 |   [7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12],
130 |   [11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5],
131 |   [11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12],
132 |   [9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6],
133 |   [8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6],
134 |   [9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11],
135 |   [9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5],
136 |   [15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8],
137 |   [8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]
138 | ];
139 | 
140 | var indexes = [
141 |   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
142 |   [7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8],
143 |   [3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12],
144 |   [1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2],
145 |   [4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13],
146 |   [5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12],
147 |   [6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2],
148 |   [15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13],
149 |   [8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14],
150 |   [12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]
151 | ];
152 | 
153 | function compress(MDbuf, X) {
154 |   var blockA = [];
155 |   var blockB = [];
156 | 
157 |   var retBlock;
158 | 
159 |   var i, j;
160 | 
161 |   for (i = 0; i < 5; i++) {
162 |     blockA[i] = new Number(MDbuf[i]);
163 |     blockB[i] = new Number(MDbuf[i]);
164 |   }
165 | 
166 |   var step = 0;
167 |   for (j = 0; j < 5; j++) {
168 |     for (i = 0; i < 16; i++) {
169 |       retBlock = mixOneRound(
170 |         blockA[(step + 0) % 5],
171 |         blockA[(step + 1) % 5],
172 |         blockA[(step + 2) % 5],
173 |         blockA[(step + 3) % 5],
174 |         blockA[(step + 4) % 5],
175 |         X[indexes[j][i]],
176 |         ROLs[j][i],
177 |         j);
178 | 
179 |       blockA[(step + 0) % 5] = retBlock[0];
180 |       blockA[(step + 1) % 5] = retBlock[1];
181 |       blockA[(step + 2) % 5] = retBlock[2];
182 |       blockA[(step + 3) % 5] = retBlock[3];
183 |       blockA[(step + 4) % 5] = retBlock[4];
184 | 
185 |       step += 4;
186 |     }
187 |   }
188 | 
189 |   step = 0;
190 |   for (j = 5; j < 10; j++) {
191 |     for (i = 0; i < 16; i++) {
192 |       retBlock = mixOneRound(
193 |         blockB[(step + 0) % 5],
194 |         blockB[(step + 1) % 5],
195 |         blockB[(step + 2) % 5],
196 |         blockB[(step + 3) % 5],
197 |         blockB[(step + 4) % 5],
198 |         X[indexes[j][i]],
199 |         ROLs[j][i],
200 |         j);
201 | 
202 |       blockB[(step + 0) % 5] = retBlock[0];
203 |       blockB[(step + 1) % 5] = retBlock[1];
204 |       blockB[(step + 2) % 5] = retBlock[2];
205 |       blockB[(step + 3) % 5] = retBlock[3];
206 |       blockB[(step + 4) % 5] = retBlock[4];
207 | 
208 |       step += 4;
209 |     }
210 |   }
211 | 
212 |   blockB[3] += blockA[2] + MDbuf[1];
213 |   MDbuf[1] = MDbuf[2] + blockA[3] + blockB[4];
214 |   MDbuf[2] = MDbuf[3] + blockA[4] + blockB[0];
215 |   MDbuf[3] = MDbuf[4] + blockA[0] + blockB[1];
216 |   MDbuf[4] = MDbuf[0] + blockA[1] + blockB[2];
217 |   MDbuf[0] = blockB[3];
218 | }
219 | 
220 | function zeroX(X) {
221 |   for (var i = 0; i < 16; i++) {
222 |     X[i] = 0;
223 |   }
224 | }
225 | 
226 | function MDfinish(MDbuf, strptr, lswlen, mswlen) {
227 |   var X = new Array(16);
228 |   zeroX(X);
229 | 
230 |   var j = 0;
231 |   for (var i = 0; i < (lswlen & 63); i++) {
232 |     X[i >>> 2] ^= (strptr.charCodeAt(j++) & 255) << (8 * (i & 3));
233 |   }
234 | 
235 |   X[(lswlen >>> 2) & 15] ^= 1 << (8 * (lswlen & 3) + 7);
236 | 
237 |   if ((lswlen & 63) > 55) {
238 |     compress(MDbuf, X);
239 |     X = new Array(16);
240 |     zeroX(X);
241 |   }
242 | 
243 |   X[14] = lswlen << 3;
244 |   X[15] = (lswlen >>> 29) | (mswlen << 3);
245 | 
246 |   compress(MDbuf, X);
247 | }
248 | 
249 | function BYTES_TO_DWORD(fourChars) {
250 |   var tmp = (fourChars.charCodeAt(3) & 255) << 24;
251 |   tmp |= (fourChars.charCodeAt(2) & 255) << 16;
252 |   tmp |= (fourChars.charCodeAt(1) & 255) << 8;
253 |   tmp |= (fourChars.charCodeAt(0) & 255);
254 | 
255 |   return tmp;
256 | }
257 | 
258 | function RMD(message) {
259 |   var MDbuf = new Array(RMDsize / 32);
260 |   var hashcode = new Array(RMDsize / 8);
261 |   var length;
262 |   var nbytes;
263 | 
264 |   MDinit(MDbuf);
265 |   length = message.length;
266 | 
267 |   var X = new Array(16);
268 |   zeroX(X);
269 | 
270 |   var i, j = 0;
271 |   for (nbytes = length; nbytes > 63; nbytes -= 64) {
272 |     for (i = 0; i < 16; i++) {
273 |       X[i] = BYTES_TO_DWORD(message.substr(j, 4));
274 |       j += 4;
275 |     }
276 |     compress(MDbuf, X);
277 |   }
278 | 
279 |   MDfinish(MDbuf, message.substr(j), length, 0);
280 | 
281 |   for (i = 0; i < RMDsize / 8; i += 4) {
282 |     hashcode[i] = MDbuf[i >>> 2] & 255;
283 |     hashcode[i + 1] = (MDbuf[i >>> 2] >>> 8) & 255;
284 |     hashcode[i + 2] = (MDbuf[i >>> 2] >>> 16) & 255;
285 |     hashcode[i + 3] = (MDbuf[i >>> 2] >>> 24) & 255;
286 |   }
287 | 
288 |   return hashcode;
289 | }
290 | 
291 | 
292 | export default function RMDstring(message) {
293 |   var hashcode = RMD(util.Uint8Array2str(message));
294 |   var retString = "";
295 | 
296 |   for (var i = 0; i < RMDsize / 8; i++) {
297 |     retString += String.fromCharCode(hashcode[i]);
298 |   }
299 | 
300 |   return util.str2Uint8Array(retString);
301 | }
302 | 
--------------------------------------------------------------------------------
/src/crypto/index.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @see module:crypto/crypto
 3 |  * @module crypto
 4 |  */
 5 | 
 6 | 'use strict';
 7 | 
 8 | import cipher from './cipher';
 9 | import hash from './hash';
10 | import cfb from './cfb';
11 | import publicKey from './public_key';
12 | import signature from './signature';
13 | import random from './random';
14 | import pkcs1 from './pkcs1';
15 | import crypto from './crypto.js';
16 | 
17 | const mod = {
18 |   /** @see module:crypto/cipher */
19 |   cipher: cipher,
20 |   /** @see module:crypto/hash */
21 |   hash: hash,
22 |   /** @see module:crypto/cfb */
23 |   cfb: cfb,
24 |   /** @see module:crypto/public_key */
25 |   publicKey: publicKey,
26 |   /** @see module:crypto/signature */
27 |   signature: signature,
28 |   /** @see module:crypto/random */
29 |   random: random,
30 |   /** @see module:crypto/pkcs1 */
31 |   pkcs1: pkcs1,
32 | };
33 | 
34 | for (var i in crypto) {
35 |   mod[i] = crypto[i];
36 | }
37 | 
38 | export default mod;
39 | 
--------------------------------------------------------------------------------
/src/crypto/isaac.js:
--------------------------------------------------------------------------------
  1 | /* ----------------------------------------------------------------------
  2 |  * Copyright (c) 2012 Yves-Marie K. Rinquin
  3 |  *
  4 |  * Permission is hereby granted, free of charge, to any person obtaining
  5 |  * a copy of this software and associated documentation files (the
  6 |  * "Software"), to deal in the Software without restriction, including
  7 |  * without limitation the rights to use, copy, modify, merge, publish,
  8 |  * distribute, sublicense, and/or sell copies of the Software, and to
  9 |  * permit persons to whom the Software is furnished to do so, subject to
 10 |  * the following conditions:
 11 |  *
 12 |  * The above copyright notice and this permission notice shall be
 13 |  * included in all copies or substantial portions of the Software.
 14 |  *
 15 |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 16 |  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 17 |  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 18 |  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 19 |  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 20 |  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 21 |  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 22 |  *
 23 |  * ----------------------------------------------------------------------
 24 |  *
 25 |  * ISAAC is a cryptographically secure pseudo-random number generator
 26 |  * (or CSPRNG for short) designed by Robert J. Jenkins Jr. in 1996 and
 27 |  * based on RC4. It is designed for speed and security.
 28 |  *
 29 |  * ISAAC's informations & analysis:
 30 |  *   http://burtleburtle.net/bob/rand/isaac.html
 31 |  * ISAAC's implementation details:
 32 |  *   http://burtleburtle.net/bob/rand/isaacafa.html
 33 |  *
 34 |  * ISAAC succesfully passed TestU01
 35 |  *
 36 |  * ----------------------------------------------------------------------
 37 |  *
 38 |  * Usage:
 39 |  *   
 40 |  *   var random_number = isaac.random();
 41 |  *
 42 |  * Output: [ 0x00000000; 0xffffffff]
 43 |  *         [-2147483648; 2147483647]
 44 |  *
 45 |  */
 46 | 
 47 |  /* private: internal states */
 48 |  var m = Array(256), // internal memory
 49 |      acc = 0,        // accumulator
 50 |      brs = 0,        // last result
 51 |      cnt = 0,        // counter
 52 |      r = Array(256), // result array
 53 |      gnt = 0;        // generation counter
 54 | 
 55 | 
 56 | /* isaac module pattern */
 57 | export function Isaac() {
 58 |   this.seed(Math.random() * 0xffffffff);
 59 | }
 60 | 
 61 | /* private: 32-bit integer safe adder */
 62 | function add(x, y) {
 63 |   var lsb = (x & 0xffff) + (y & 0xffff);
 64 |   var msb = (x >>>   16) + (y >>>   16) + (lsb >>> 16);
 65 |   return (msb << 16) | (lsb & 0xffff);
 66 | }
 67 | 
 68 | /* public: initialisation */
 69 | Isaac.prototype.reset = function() {
 70 |   acc = brs = cnt = 0;
 71 |   for(var i = 0; i < 256; ++i) {
 72 |     m[i] = r[i] = 0;
 73 |   }
 74 |   gnt = 0;
 75 | };
 76 | 
 77 | /* public: seeding function */
 78 | Isaac.prototype.seed = function(s) {
 79 |   var a, b, c, d, e, f, g, h, i;
 80 | 
 81 |   /* seeding the seeds of love */
 82 |   a = b = c = d =
 83 |   e = f = g = h = 0x9e3779b9; /* the golden ratio */
 84 | 
 85 |   if(s && typeof(s) === 'string') {
 86 |     s = s.toIntArray();
 87 |   }
 88 | 
 89 |   if(s && typeof(s) === 'number') {
 90 |     s = [s];
 91 |   }
 92 | 
 93 |   if(s instanceof Array) {
 94 |     this.reset();
 95 |     for(i = 0; i < s.length; i++) {
 96 |       r[i & 0xff] += (typeof(s[i]) === 'number') ? s[i] : 0;
 97 |     }
 98 |   }
 99 | 
100 |   /* private: seed mixer */
101 |   function seed_mix() {
102 |     a ^= b <<  11; d = add(d, a); b = add(b, c);
103 |     b ^= c >>>  2; e = add(e, b); c = add(c, d);
104 |     c ^= d <<   8; f = add(f, c); d = add(d, e);
105 |     d ^= e >>> 16; g = add(g, d); e = add(e, f);
106 |     e ^= f <<  10; h = add(h, e); f = add(f, g);
107 |     f ^= g >>>  4; a = add(a, f); g = add(g, h);
108 |     g ^= h <<   8; b = add(b, g); h = add(h, a);
109 |     h ^= a >>>  9; c = add(c, h); a = add(a, b);
110 |   }
111 | 
112 |   for(i = 0; i < 4; i++) { /* scramble it */
113 |     seed_mix();
114 |   }
115 | 
116 |   for(i = 0; i < 256; i += 8) {
117 |     if(s) { /* use all the information in the seed */
118 |       a = add(a, r[i + 0]); b = add(b, r[i + 1]);
119 |       c = add(c, r[i + 2]); d = add(d, r[i + 3]);
120 |       e = add(e, r[i + 4]); f = add(f, r[i + 5]);
121 |       g = add(g, r[i + 6]); h = add(h, r[i + 7]);
122 |     }
123 |     seed_mix();
124 |     /* fill in m[] with messy stuff */
125 |     m[i + 0] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
126 |     m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
127 |   }
128 |   if(s) {
129 |     /* do a second pass to make all of the seed affect all of m[] */
130 |     for(i = 0; i < 256; i += 8) {
131 |       a = add(a, m[i + 0]); b = add(b, m[i + 1]);
132 |       c = add(c, m[i + 2]); d = add(d, m[i + 3]);
133 |       e = add(e, m[i + 4]); f = add(f, m[i + 5]);
134 |       g = add(g, m[i + 6]); h = add(h, m[i + 7]);
135 |       seed_mix();
136 |       /* fill in m[] with messy stuff (again) */
137 |       m[i + 0] = a; m[i + 1] = b; m[i + 2] = c; m[i + 3] = d;
138 |       m[i + 4] = e; m[i + 5] = f; m[i + 6] = g; m[i + 7] = h;
139 |     }
140 |   }
141 | 
142 |   this.prng(); /* fill in the first set of results */
143 |   gnt = 256  /* prepare to use the first set of results */;
144 | };
145 | 
146 | /* public: isaac generator, n = number of run */
147 | Isaac.prototype.prng = function(n) {
148 |   var i, x, y;
149 | 
150 |   n = (n && typeof(n) === 'number') ? Math.abs(Math.floor(n)) : 1;
151 | 
152 |   while(n--) {
153 |     cnt = add(cnt,   1);
154 |     brs = add(brs, cnt);
155 | 
156 |     for(i = 0; i < 256; i++) {
157 |       switch(i & 3) {
158 |         case 0: acc ^= acc <<  13; break;
159 |         case 1: acc ^= acc >>>  6; break;
160 |         case 2: acc ^= acc <<   2; break;
161 |         case 3: acc ^= acc >>> 16; break;
162 |       }
163 |       acc        = add(m[(i +  128) & 0xff], acc); x = m[i];
164 |       m[i] =   y = add(m[(x >>>  2) & 0xff], add(acc, brs));
165 |       r[i] = brs = add(m[(y >>> 10) & 0xff], x);
166 |     }
167 |   }
168 | };
169 | 
170 | /* public: return a random number between */
171 | Isaac.prototype.rand = function() {
172 |   if(!gnt--) {
173 |     this.prng(); gnt = 255;
174 |   }
175 |   return r[gnt];
176 | };
177 | 
178 | /* public: return internals in an object*/
179 | Isaac.prototype.internals = function() {
180 |   return {a: acc, b: brs, c: cnt, m: m, r: r};
181 | };
182 | 
183 | /* public: output*/
184 | Isaac.prototype.random = function() {
185 |   return 0.5 + this.rand() * 2.3283064365386963e-10; // 2^-32
186 | };
187 | 
188 | 
189 | /* js string (ucs-2/utf16) to a 32-bit integer (utf-8 chars, little-endian) array */
190 | String.prototype.toIntArray = function() {
191 |   var w1, w2, u, r4 = [], r = [], i = 0;
192 |   var s = this + '\0\0\0'; // pad string to avoid discarding last chars
193 |   var l = s.length - 1;
194 | 
195 |   while(i < l) {
196 |     w1 = s.charCodeAt(i++);
197 |     w2 = s.charCodeAt(i+1);
198 |     if       (w1 < 0x0080) {
199 |       // 0x0000 - 0x007f code point: basic ascii
200 |       r4.push(w1);
201 |     } else if(w1 < 0x0800) {
202 |       // 0x0080 - 0x07ff code point
203 |       r4.push(((w1 >>>  6) & 0x1f) | 0xc0);
204 |       r4.push(((w1 >>>  0) & 0x3f) | 0x80);
205 |     } else if((w1 & 0xf800) !== 0xd800) {
206 |       // 0x0800 - 0xd7ff / 0xe000 - 0xffff code point
207 |       r4.push(((w1 >>> 12) & 0x0f) | 0xe0);
208 |       r4.push(((w1 >>>  6) & 0x3f) | 0x80);
209 |       r4.push(((w1 >>>  0) & 0x3f) | 0x80);
210 |     } else if(((w1 & 0xfc00) === 0xd800) &&
211 |               ((w2 & 0xfc00) === 0xdc00)) {
212 |       // 0xd800 - 0xdfff surrogate / 0x10ffff - 0x10000 code point
213 |       u = ((w2 & 0x3f) | ((w1 & 0x3f) << 10)) + 0x10000;
214 |       r4.push(((u >>> 18) & 0x07) | 0xf0);
215 |       r4.push(((u >>> 12) & 0x3f) | 0x80);
216 |       r4.push(((u >>>  6) & 0x3f) | 0x80);
217 |       r4.push(((u >>>  0) & 0x3f) | 0x80);
218 |       i++;
219 |     } else {
220 |       // invalid char
221 |     }
222 |     /* add integer (four utf-8 value) to array */
223 |     if(r4.length > 3) {
224 |       // little endian
225 |       r.push((r4.shift() <<  0) | (r4.shift() <<  8) |
226 |              (r4.shift() << 16) | (r4.shift() << 24));
227 |     }
228 |   }
229 | 
230 |   return r;
231 | };
232 | 
--------------------------------------------------------------------------------
/src/crypto/pkcs1.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * PKCS1 encoding
 20 |  * @requires crypto/crypto
 21 |  * @requires crypto/hash
 22 |  * @requires crypto/public_key/jsbn
 23 |  * @requires crypto/random
 24 |  * @requires util
 25 |  * @module crypto/pkcs1
 26 |  */
 27 | 
 28 | 'use strict';
 29 | 
 30 | import random from './random.js';
 31 | import util from '../util.js';
 32 | import BigInteger from './public_key/jsbn.js';
 33 | import hash from './hash';
 34 | 
 35 | /**
 36 |  * ASN1 object identifiers for hashes (See {@link http://tools.ietf.org/html/rfc4880#section-5.2.2})
 37 |  */
 38 | var hash_headers = [];
 39 | hash_headers[1] = [0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04,
 40 |     0x10
 41 | ];
 42 | hash_headers[2] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14];
 43 | hash_headers[3] = [0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02, 0x01, 0x05, 0x00, 0x04, 0x14];
 44 | hash_headers[8] = [0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
 45 |     0x04, 0x20
 46 | ];
 47 | hash_headers[9] = [0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00,
 48 |     0x04, 0x30
 49 | ];
 50 | hash_headers[10] = [0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
 51 |     0x00, 0x04, 0x40
 52 | ];
 53 | hash_headers[11] = [0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05,
 54 |     0x00, 0x04, 0x1C
 55 | ];
 56 | 
 57 | /**
 58 |  * Create padding with secure random data
 59 |  * @private
 60 |  * @param  {Integer} length Length of the padding in bytes
 61 |  * @return {String}        Padding as string
 62 |  */
 63 | function getPkcs1Padding(length) {
 64 |   var result = '';
 65 |   var randomByte;
 66 |   while (result.length < length) {
 67 |     randomByte = random.getSecureRandomOctet();
 68 |     if (randomByte !== 0) {
 69 |       result += String.fromCharCode(randomByte);
 70 |     }
 71 |   }
 72 |   return result;
 73 | }
 74 | 
 75 | 
 76 | export default {
 77 |   eme: {
 78 |     /**
 79 |      * create a EME-PKCS1-v1_5 padding (See {@link http://tools.ietf.org/html/rfc4880#section-13.1.1|RFC 4880 13.1.1})
 80 |      * @param {String} M message to be encoded
 81 |      * @param {Integer} k the length in octets of the key modulus
 82 |      * @return {String} EME-PKCS1 padded message
 83 |      */
 84 |     encode: function(M, k) {
 85 |       var mLen = M.length;
 86 |       // length checking
 87 |       if (mLen > k - 11) {
 88 |         throw new Error('Message too long');
 89 |       }
 90 |       // Generate an octet string PS of length k - mLen - 3 consisting of
 91 |       // pseudo-randomly generated nonzero octets
 92 |       var PS = getPkcs1Padding(k - mLen - 3);
 93 |       // Concatenate PS, the message M, and other padding to form an
 94 |       // encoded message EM of length k octets as EM = 0x00 || 0x02 || PS || 0x00 || M.
 95 |       var EM = String.fromCharCode(0) +
 96 |                String.fromCharCode(2) +
 97 |                PS +
 98 |                String.fromCharCode(0) +
 99 |                M;
100 |       return EM;
101 |     },
102 |     /**
103 |      * decodes a EME-PKCS1-v1_5 padding (See {@link http://tools.ietf.org/html/rfc4880#section-13.1.2|RFC 4880 13.1.2})
104 |      * @param {String} EM encoded message, an octet string
105 |      * @return {String} message, an octet string
106 |      */
107 |     decode: function(EM) {
108 |       // leading zeros truncated by jsbn
109 |       if (EM.charCodeAt(0) !== 0) {
110 |         EM = String.fromCharCode(0) + EM;
111 |       }
112 |       var firstOct = EM.charCodeAt(0);
113 |       var secondOct = EM.charCodeAt(1);
114 |       var i = 2;
115 |       while (EM.charCodeAt(i) !== 0 && i < EM.length) {
116 |         i++;
117 |       }
118 |       var psLen = i - 2;
119 |       var separator = EM.charCodeAt(i++);
120 |       if (firstOct === 0 && secondOct === 2 && psLen >= 8 && separator === 0) {
121 |         return EM.substr(i);
122 |       } else {
123 |         throw new Error('Decryption error');
124 |       }
125 |     }
126 |   },
127 | 
128 |   emsa: {
129 |     /**
130 |      * create a EMSA-PKCS1-v1_5 padding (See {@link http://tools.ietf.org/html/rfc4880#section-13.1.3|RFC 4880 13.1.3})
131 |      * @param {Integer} algo Hash algorithm type used
132 |      * @param {String} M message to be encoded
133 |      * @param {Integer} emLen intended length in octets of the encoded message
134 |      * @returns {String} encoded message
135 |      */
136 |     encode: function(algo, M, emLen) {
137 |       var i;
138 |       // Apply the hash function to the message M to produce a hash value H
139 |       var H = util.Uint8Array2str(hash.digest(algo, util.str2Uint8Array(M)));
140 |       if (H.length !== hash.getHashByteLength(algo)) {
141 |         throw new Error('Invalid hash length');
142 |       }
143 |       // produce an ASN.1 DER value for the hash function used.
144 |       // Let T be the full hash prefix
145 |       var T = '';
146 |       for (i = 0; i < hash_headers[algo].length; i++) {
147 |         T += String.fromCharCode(hash_headers[algo][i]);
148 |       }
149 |       // add hash value to prefix
150 |       T += H;
151 |       // and let tLen be the length in octets of T
152 |       var tLen = T.length;
153 |       if (emLen < tLen + 11) {
154 |         throw new Error('Intended encoded message length too short');
155 |       }
156 |       // an octet string PS consisting of emLen - tLen - 3 octets with hexadecimal value 0xFF
157 |       // The length of PS will be at least 8 octets
158 |       var PS = '';
159 |       for (i = 0; i < (emLen - tLen - 3); i++) {
160 |         PS += String.fromCharCode(0xff);
161 |       }
162 |       // Concatenate PS, the hash prefix T, and other padding to form the
163 |       // encoded message EM as EM = 0x00 || 0x01 || PS || 0x00 || T.
164 |       var EM = String.fromCharCode(0x00) +
165 |                String.fromCharCode(0x01) +
166 |                PS +
167 |                String.fromCharCode(0x00) +
168 |                T;
169 |       return new BigInteger(util.hexstrdump(EM), 16);
170 |     }
171 |   }
172 | };
173 | 
--------------------------------------------------------------------------------
/src/crypto/public_key/dsa.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | //
 18 | // A Digital signature algorithm implementation
 19 | 
 20 | /**
 21 |  * @requires crypto/hash
 22 |  * @requires crypto/public_key/jsbn
 23 |  * @requires crypto/random
 24 |  * @requires util
 25 |  * @module crypto/public_key/dsa
 26 |  */
 27 | 
 28 | 'use strict';
 29 | 
 30 | import BigInteger from './jsbn.js';
 31 | import random from '../random.js';
 32 | import hashModule from '../hash';
 33 | import util from '../../util.js';
 34 | import config from '../../config';
 35 | 
 36 | export default function DSA() {
 37 |   // s1 = ((g**s) mod p) mod q
 38 |   // s1 = ((s**-1)*(sha-1(m)+(s1*x) mod q)
 39 |   function sign(hashalgo, m, g, p, q, x) {
 40 |     // If the output size of the chosen hash is larger than the number of
 41 |     // bits of q, the hash result is truncated to fit by taking the number
 42 |     // of leftmost bits equal to the number of bits of q.  This (possibly
 43 |     // truncated) hash function result is treated as a number and used
 44 |     // directly in the DSA signature algorithm.
 45 |     var hashed_data = util.getLeftNBits(util.Uint8Array2str(hashModule.digest(hashalgo, util.str2Uint8Array(m))), q.bitLength());
 46 |     var hash = new BigInteger(util.hexstrdump(hashed_data), 16);
 47 |     // FIPS-186-4, section 4.6:
 48 |     // The values of r and s shall be checked to determine if r = 0 or s = 0.
 49 |     // If either r = 0 or s = 0, a new value of k shall be generated, and the
 50 |     // signature shall be recalculated. It is extremely unlikely that r = 0
 51 |     // or s = 0 if signatures are generated properly.
 52 |     var k, s1, s2;
 53 |     while (true) {
 54 |       k = random.getRandomBigIntegerInRange(BigInteger.ONE, q.subtract(BigInteger.ONE));
 55 |       s1 = (g.modPow(k, p)).mod(q);
 56 |       s2 = (k.modInverse(q).multiply(hash.add(x.multiply(s1)))).mod(q);
 57 |       if (s1 !== 0 && s2 !== 0) {
 58 |         break;
 59 |       }
 60 |     }
 61 |     var result = [];
 62 |     result[0] = s1.toMPI();
 63 |     result[1] = s2.toMPI();
 64 |     return result;
 65 |   }
 66 | 
 67 |   function select_hash_algorithm(q) {
 68 |     var usersetting = config.prefer_hash_algorithm;
 69 |     /*
 70 |      * 1024-bit key, 160-bit q, SHA-1, SHA-224, SHA-256, SHA-384, or SHA-512 hash
 71 |      * 2048-bit key, 224-bit q, SHA-224, SHA-256, SHA-384, or SHA-512 hash
 72 |      * 2048-bit key, 256-bit q, SHA-256, SHA-384, or SHA-512 hash
 73 |      * 3072-bit key, 256-bit q, SHA-256, SHA-384, or SHA-512 hash
 74 |      */
 75 |     switch (Math.round(q.bitLength() / 8)) {
 76 |       case 20:
 77 |         // 1024 bit
 78 |         if (usersetting !== 2 &&
 79 |           usersetting > 11 &&
 80 |           usersetting !== 10 &&
 81 |           usersetting < 8) {
 82 |           return 2; // prefer sha1
 83 |         }
 84 |         return usersetting;
 85 |       case 28:
 86 |         // 2048 bit
 87 |         if (usersetting > 11 &&
 88 |           usersetting < 8) {
 89 |           return 11;
 90 |         }
 91 |         return usersetting;
 92 |       case 32:
 93 |         // 4096 bit // prefer sha224
 94 |         if (usersetting > 10 &&
 95 |           usersetting < 8) {
 96 |           return 8; // prefer sha256
 97 |         }
 98 |         return usersetting;
 99 |       default:
100 |         util.print_debug("DSA select hash algorithm: returning null for an unknown length of q");
101 |         return null;
102 |     }
103 |   }
104 |   this.select_hash_algorithm = select_hash_algorithm;
105 | 
106 |   function verify(hashalgo, s1, s2, m, p, q, g, y) {
107 |     var hashed_data = util.getLeftNBits(util.Uint8Array2str(hashModule.digest(hashalgo, util.str2Uint8Array(m))), q.bitLength());
108 |     var hash = new BigInteger(util.hexstrdump(hashed_data), 16);
109 |     if (BigInteger.ZERO.compareTo(s1) >= 0 ||
110 |       s1.compareTo(q) >= 0 ||
111 |       BigInteger.ZERO.compareTo(s2) >= 0 ||
112 |       s2.compareTo(q) >= 0) {
113 |       util.print_debug("invalid DSA Signature");
114 |       return null;
115 |     }
116 |     var w = s2.modInverse(q);
117 |     if (BigInteger.ZERO.compareTo(w) === 0) {
118 |       util.print_debug("invalid DSA Signature");
119 |       return null;
120 |     }
121 |     var u1 = hash.multiply(w).mod(q);
122 |     var u2 = s1.multiply(w).mod(q);
123 |     return g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
124 |   }
125 | 
126 |   this.sign = sign;
127 |   this.verify = verify;
128 | }
129 | 
--------------------------------------------------------------------------------
/src/crypto/public_key/elgamal.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | //
18 | // ElGamal implementation
19 | 
20 | /**
21 |  * @requires crypto/public_key/jsbn
22 |  * @requires crypto/random
23 |  * @requires util
24 |  * @module crypto/public_key/elgamal
25 |  */
26 | 
27 | 'use strict';
28 | 
29 | import BigInteger from './jsbn.js';
30 | import random from '../random.js';
31 | import util from '../../util.js';
32 | 
33 | export default function Elgamal() {
34 | 
35 |   function encrypt(m, g, p, y) {
36 |     //  choose k in {2,...,p-2}
37 |     var pMinus2 = p.subtract(BigInteger.TWO);
38 |     var k = random.getRandomBigIntegerInRange(BigInteger.ONE, pMinus2);
39 |     k = k.mod(pMinus2).add(BigInteger.ONE);
40 |     var c = [];
41 |     c[0] = g.modPow(k, p);
42 |     c[1] = y.modPow(k, p).multiply(m).mod(p);
43 |     return c;
44 |   }
45 | 
46 |   function decrypt(c1, c2, p, x) {
47 |     util.print_debug("Elgamal Decrypt:\nc1:" + util.hexstrdump(c1.toMPI()) + "\n" +
48 |       "c2:" + util.hexstrdump(c2.toMPI()) + "\n" +
49 |       "p:" + util.hexstrdump(p.toMPI()) + "\n" +
50 |       "x:" + util.hexstrdump(x.toMPI()));
51 |     return (c1.modPow(x, p).modInverse(p)).multiply(c2).mod(p);
52 |     //var c = c1.pow(x).modInverse(p); // c0^-a mod p
53 |     //return c.multiply(c2).mod(p);
54 |   }
55 | 
56 |   // signing and signature verification using Elgamal is not required by OpenPGP.
57 |   this.encrypt = encrypt;
58 |   this.decrypt = decrypt;
59 | }
60 | 
--------------------------------------------------------------------------------
/src/crypto/public_key/index.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @requires crypto/public_key/dsa
 3 |  * @requires crypto/public_key/elgamal
 4 |  * @requires crypto/public_key/rsa
 5 |  * @module crypto/public_key
 6 |  */
 7 | 
 8 | 'use strict';
 9 | 
10 | /** @see module:crypto/public_key/rsa */
11 | import rsa from './rsa.js';
12 | /** @see module:crypto/public_key/elgamal */
13 | import elgamal from './elgamal.js';
14 | /** @see module:crypto/public_key/dsa */
15 | import dsa from './dsa.js';
16 | 
17 | export default {
18 |   rsa: rsa,
19 |   elgamal: elgamal,
20 |   dsa: dsa
21 | };
22 | 
--------------------------------------------------------------------------------
/src/crypto/random.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | // The GPG4Browsers crypto interface
 19 | 
 20 | /**
 21 |  * @requires type/mpi
 22 |  * @requires util
 23 |  * @module crypto/random
 24 |  */
 25 | 
 26 | 'use strict';
 27 | 
 28 | import type_mpi from '../type/mpi.js';
 29 | import util from '../util.js';
 30 | import * as Isaac from './isaac.js';
 31 | const nodeCrypto = null;
 32 | 
 33 | var randomizer = require('./randomBytes');
 34 | var isaacson = new Isaac.Isaac();
 35 | 
 36 | export default {
 37 |   /**
 38 |    * Generates random values
 39 |    */
 40 |   generateRandomValues: function () {
 41 |     var promise = new Promise(function(success, failed) {
 42 |       try {
 43 |         randomizer.randomBytes(4096, (err, bytes) => {
 44 |           if (bytes) {
 45 |             isaacson.seed(bytes);
 46 |             success();
 47 |           } else {
 48 |             failed();
 49 |           }
 50 |         });
 51 |       } catch(error) {
 52 |         failed();
 53 |       }
 54 |     });
 55 | 
 56 |     return promise;
 57 |   },
 58 | 
 59 |   /**
 60 |    * Retrieve secure random byte array of the specified length
 61 |    * @param {Integer} length Length in bytes to generate
 62 |    * @return {Uint8Array} Random byte array
 63 |    */
 64 |   getRandomBytes: function(length) {
 65 |     var result = new Uint8Array(length);
 66 |     for (var i = 0; i < length; i++) {
 67 |       result[i] = this.getSecureRandomOctet();
 68 |     }
 69 |     return result;
 70 |   },
 71 | 
 72 |   /**
 73 |    * Return a secure random number in the specified range
 74 |    * @param {Integer} from Min of the random number
 75 |    * @param {Integer} to Max of the random number (max 32bit)
 76 |    * @return {Integer} A secure random number
 77 |    */
 78 |   getSecureRandom: function(from, to) {
 79 |     var randUint = this.getSecureRandomUint();
 80 |     var bits = ((to - from)).toString(2).length;
 81 |     while ((randUint & (Math.pow(2, bits) - 1)) > (to - from)) {
 82 |       randUint = this.getSecureRandomUint();
 83 |     }
 84 |     return from + (Math.abs(randUint & (Math.pow(2, bits) - 1)));
 85 |   },
 86 | 
 87 |   getSecureRandomOctet: function() {
 88 |     var buf = new Uint8Array(1);
 89 |     this.getRandomValues(buf);
 90 |     return buf[0];
 91 |   },
 92 | 
 93 |   getSecureRandomUint: function() {
 94 |     var buf = new Uint8Array(4);
 95 |     var dv = new DataView(buf.buffer);
 96 |     this.getRandomValues(buf);
 97 |     return dv.getUint32(0);
 98 |   },
 99 | 
100 |   /**
101 |    * Helper routine which calls platform specific crypto random generator
102 |    * @param {Uint8Array} buf
103 |    */
104 |   getRandomValues: function(buf) {
105 |     if (!(buf instanceof Uint8Array)) {
106 |       throw new Error('Invalid type: buf not an Uint8Array');
107 |     }
108 |     if (typeof window !== 'undefined' && window.crypto && window.crypto.getRandomValues) {
109 |       window.crypto.getRandomValues(buf);
110 |     } else if (typeof window !== 'undefined' && typeof window.msCrypto === 'object' && typeof window.msCrypto.getRandomValues === 'function') {
111 |       window.msCrypto.getRandomValues(buf);
112 |     } else if (nodeCrypto) {
113 |       var bytes = nodeCrypto.randomBytes(buf.length);
114 |       buf.set(bytes);
115 |     } else if (this.randomBuffer.buffer) {
116 |       this.randomBuffer.get(buf);
117 |     } else {
118 |       for (var i = 0; i < buf.length; i++) {
119 |         buf[i] = Math.floor((isaacson.random() * 255));
120 |       }
121 |     }
122 |   },
123 | 
124 |   /**
125 |    * Create a secure random big integer of bits length
126 |    * @param {Integer} bits Bit length of the MPI to create
127 |    * @return {BigInteger} Resulting big integer
128 |    */
129 |   getRandomBigInteger: function(bits) {
130 |     if (bits < 1) {
131 |       throw new Error('Illegal parameter value: bits < 1');
132 |     }
133 |     var numBytes = Math.floor((bits + 7) / 8);
134 | 
135 |     var randomBits = util.Uint8Array2str(this.getRandomBytes(numBytes));
136 |     if (bits % 8 > 0) {
137 | 
138 |       randomBits = String.fromCharCode(
139 |       (Math.pow(2, bits % 8) - 1) &
140 |         randomBits.charCodeAt(0)) +
141 |         randomBits.substring(1);
142 |     }
143 |     var mpi = new type_mpi();
144 |     mpi.fromBytes(randomBits);
145 |     return mpi.toBigInteger();
146 |   },
147 | 
148 |   getRandomBigIntegerInRange: function(min, max) {
149 |     if (max.compareTo(min) <= 0) {
150 |       throw new Error('Illegal parameter value: max <= min');
151 |     }
152 | 
153 |     var range = max.subtract(min);
154 |     var r = this.getRandomBigInteger(range.bitLength());
155 |     while (r.compareTo(range) > 0) {
156 |       r = this.getRandomBigInteger(range.bitLength());
157 |     }
158 |     return min.add(r);
159 |   },
160 | 
161 |   randomBuffer: new RandomBuffer()
162 | 
163 | };
164 | 
165 | /**
166 |  * Buffer for secure random numbers
167 |  */
168 | function RandomBuffer() {
169 |   this.buffer = null;
170 |   this.size = null;
171 | }
172 | 
173 | /**
174 |  * Initialize buffer
175 |  * @param  {Integer} size size of buffer
176 |  */
177 | RandomBuffer.prototype.init = function(size) {
178 |   this.buffer = new Uint8Array(size);
179 |   this.size = 0;
180 | };
181 | 
182 | /**
183 |  * Concat array of secure random numbers to buffer
184 |  * @param {Uint8Array} buf
185 |  */
186 | RandomBuffer.prototype.set = function(buf) {
187 |   if (!this.buffer) {
188 |     throw new Error('RandomBuffer is not initialized');
189 |   }
190 |   if (!(buf instanceof Uint8Array)) {
191 |     throw new Error('Invalid type: buf not an Uint8Array');
192 |   }
193 |   var freeSpace = this.buffer.length - this.size;
194 |   if (buf.length > freeSpace) {
195 |     buf = buf.subarray(0, freeSpace);
196 |   }
197 |   // set buf with offset old size of buffer
198 |   this.buffer.set(buf, this.size);
199 |   this.size += buf.length;
200 | };
201 | 
202 | /**
203 |  * Take numbers out of buffer and copy to array
204 |  * @param {Uint8Array} buf the destination array
205 |  */
206 | RandomBuffer.prototype.get = function(buf) {
207 |   if (!this.buffer) {
208 |     throw new Error('RandomBuffer is not initialized');
209 |   }
210 |   if (!(buf instanceof Uint8Array)) {
211 |     throw new Error('Invalid type: buf not an Uint8Array');
212 |   }
213 |   if (this.size < buf.length) {
214 |     throw new Error('Random number buffer depleted');
215 |   }
216 |   for (var i = 0; i < buf.length; i++) {
217 |     buf[i] = this.buffer[--this.size];
218 |     // clear buffer value
219 |     this.buffer[this.size] = 0;
220 |   }
221 | };
222 | 
--------------------------------------------------------------------------------
/src/crypto/randomBytes.js:
--------------------------------------------------------------------------------
 1 | if (typeof Buffer === 'undefined') {
 2 |   global.Buffer = require('buffer').Buffer
 3 | }
 4 | 
 5 | let RNOpenPGP = require('react-native').NativeModules.RNOpenPGP
 6 | 
 7 | function noop () {}
 8 | 
 9 | function toBuffer (nativeStr) {
10 |   return new Buffer(nativeStr, 'base64')
11 | }
12 | 
13 | export function randomBytes (length, cb) {
14 |   if (!cb) {
15 |     cb("Error: No callback function defined");
16 |   }
17 | 
18 |   RNOpenPGP.randomBytes(length, function(err, base64String) {
19 |     if (err) {
20 |       cb(err)
21 |     } else {
22 |       cb(null, toBuffer(base64String))
23 |     }
24 |   })
25 | }
26 | 
--------------------------------------------------------------------------------
/src/crypto/signature.js:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * @requires util
  3 |  * @requires crypto/hash
  4 |  * @requires crypto/pkcs1
  5 |  * @requires crypto/public_key
  6 |  * @module crypto/signature */
  7 | 
  8 | 'use strict';
  9 | 
 10 | import util from '../util';
 11 | import publicKey from './public_key';
 12 | import pkcs1 from './pkcs1.js';
 13 | 
 14 | export default {
 15 |   /**
 16 |    *
 17 |    * @param {module:enums.publicKey} algo public Key algorithm
 18 |    * @param {module:enums.hash} hash_algo Hash algorithm
 19 |    * @param {Array} msg_MPIs Signature multiprecision integers
 20 |    * @param {Array} publickey_MPIs Public key multiprecision integers
 21 |    * @param {Uint8Array} data Data on where the signature was computed on.
 22 |    * @return {Boolean} true if signature (sig_data was equal to data over hash)
 23 |    */
 24 |   verify: function(algo, hash_algo, msg_MPIs, publickey_MPIs, data) {
 25 |     var m;
 26 | 
 27 |     data = util.Uint8Array2str(data);
 28 | 
 29 |     switch (algo) {
 30 |       case 1:
 31 |         // RSA (Encrypt or Sign) [HAC]
 32 |       case 2:
 33 |         // RSA Encrypt-Only [HAC]
 34 |       case 3:
 35 |         // RSA Sign-Only [HAC]
 36 |         var rsa = new publicKey.rsa();
 37 |         var n = publickey_MPIs[0].toBigInteger();
 38 |         var k = publickey_MPIs[0].byteLength();
 39 |         var e = publickey_MPIs[1].toBigInteger();
 40 |         m = msg_MPIs[0].toBigInteger();
 41 |         var EM = rsa.verify(m, e, n);
 42 |         var EM2 = pkcs1.emsa.encode(hash_algo, data, k);
 43 |         return EM.compareTo(EM2) === 0;
 44 |       case 16:
 45 |         // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
 46 |         throw new Error("signing with Elgamal is not defined in the OpenPGP standard.");
 47 |       case 17:
 48 |         // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
 49 |         var dsa = new publicKey.dsa();
 50 |         var s1 = msg_MPIs[0].toBigInteger();
 51 |         var s2 = msg_MPIs[1].toBigInteger();
 52 |         var p = publickey_MPIs[0].toBigInteger();
 53 |         var q = publickey_MPIs[1].toBigInteger();
 54 |         var g = publickey_MPIs[2].toBigInteger();
 55 |         var y = publickey_MPIs[3].toBigInteger();
 56 |         m = data;
 57 |         var dopublic = dsa.verify(hash_algo, s1, s2, m, p, q, g, y);
 58 |         return dopublic.compareTo(s1) === 0;
 59 |       default:
 60 |         throw new Error('Invalid signature algorithm.');
 61 |     }
 62 |   },
 63 | 
 64 |   /**
 65 |    * Create a signature on data using the specified algorithm
 66 |    * @param {module:enums.hash} hash_algo hash Algorithm to use (See {@link http://tools.ietf.org/html/rfc4880#section-9.4|RFC 4880 9.4})
 67 |    * @param {module:enums.publicKey} algo Asymmetric cipher algorithm to use (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC 4880 9.1})
 68 |    * @param {Array} publicMPIs Public key multiprecision integers
 69 |    * of the private key
 70 |    * @param {Array} secretMPIs Private key multiprecision
 71 |    * integers which is used to sign the data
 72 |    * @param {Uint8Array} data Data to be signed
 73 |    * @return {Array}
 74 |    */
 75 |   sign: function(hash_algo, algo, keyIntegers, data) {
 76 | 
 77 |     data = util.Uint8Array2str(data);
 78 | 
 79 |     var m;
 80 | 
 81 |     switch (algo) {
 82 |       case 1:
 83 |         // RSA (Encrypt or Sign) [HAC]
 84 |       case 2:
 85 |         // RSA Encrypt-Only [HAC]
 86 |       case 3:
 87 |         // RSA Sign-Only [HAC]
 88 |         var rsa = new publicKey.rsa();
 89 |         var d = keyIntegers[2].toBigInteger();
 90 |         var n = keyIntegers[0].toBigInteger();
 91 |         m = pkcs1.emsa.encode(hash_algo,
 92 |           data, keyIntegers[0].byteLength());
 93 |         return util.str2Uint8Array(rsa.sign(m, d, n).toMPI());
 94 | 
 95 |       case 17:
 96 |         // DSA (Digital Signature Algorithm) [FIPS186] [HAC]
 97 |         var dsa = new publicKey.dsa();
 98 | 
 99 |         var p = keyIntegers[0].toBigInteger();
100 |         var q = keyIntegers[1].toBigInteger();
101 |         var g = keyIntegers[2].toBigInteger();
102 |         var x = keyIntegers[4].toBigInteger();
103 |         m = data;
104 |         var result = dsa.sign(hash_algo, m, g, p, q, x);
105 | 
106 |         return util.str2Uint8Array(result[0].toString() + result[1].toString());
107 |       case 16:
108 |         // Elgamal (Encrypt-Only) [ELGAMAL] [HAC]
109 |         throw new Error('Signing with Elgamal is not defined in the OpenPGP standard.');
110 |       default:
111 |         throw new Error('Invalid signature algorithm.');
112 |     }
113 |   }
114 | };
115 | 
--------------------------------------------------------------------------------
/src/encoding/base64.js:
--------------------------------------------------------------------------------
  1 | /* OpenPGP radix-64/base64 string encoding/decoding
  2 |  * Copyright 2005 Herbert Hanewinkel, www.haneWIN.de
  3 |  * version 1.0, check www.haneWIN.de for the latest version
  4 |  *
  5 |  * This software is provided as-is, without express or implied warranty.
  6 |  * Permission to use, copy, modify, distribute or sell this software, with or
  7 |  * without fee, for any purpose and by any individual or organization, is hereby
  8 |  * granted, provided that the above copyright notice and this paragraph appear
  9 |  * in all copies. Distribution as a part of an application or binary must
 10 |  * include the above copyright notice in the documentation and/or other materials
 11 |  * provided with the application or distribution.
 12 |  */
 13 | 
 14 | /**
 15 |  * @module encoding/base64
 16 |  */
 17 | 
 18 | 'use strict';
 19 | 
 20 | var b64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
 21 | 
 22 | /**
 23 |  * Convert binary array to radix-64
 24 |  * @param {Uint8Array} t Uint8Array to convert
 25 |  * @returns {string} radix-64 version of input string
 26 |  * @static
 27 |  */
 28 | function s2r(t, o) {
 29 |   // TODO check btoa alternative
 30 |   var a, c, n;
 31 |   var r = o ? o : [],
 32 |       l = 0,
 33 |       s = 0;
 34 |   var tl = t.length;
 35 | 
 36 |   for (n = 0; n < tl; n++) {
 37 |     c = t[n];
 38 |     if (s === 0) {
 39 |       r.push(b64s.charAt((c >> 2) & 63));
 40 |       a = (c & 3) << 4;
 41 |     } else if (s === 1) {
 42 |       r.push(b64s.charAt((a | (c >> 4) & 15)));
 43 |       a = (c & 15) << 2;
 44 |     } else if (s === 2) {
 45 |       r.push(b64s.charAt(a | ((c >> 6) & 3)));
 46 |       l += 1;
 47 |       if ((l % 60) === 0) {
 48 |         r.push("\n");
 49 |       }
 50 |       r.push(b64s.charAt(c & 63));
 51 |     }
 52 |     l += 1;
 53 |     if ((l % 60) === 0) {
 54 |       r.push("\n");
 55 |     }
 56 | 
 57 |     s += 1;
 58 |     if (s === 3) {
 59 |       s = 0;
 60 |     }
 61 |   }
 62 |   if (s > 0) {
 63 |     r.push(b64s.charAt(a));
 64 |     l += 1;
 65 |     if ((l % 60) === 0) {
 66 |       r.push("\n");
 67 |     }
 68 |     r.push('=');
 69 |     l += 1;
 70 |   }
 71 |   if (s === 1) {
 72 |     if ((l % 60) === 0) {
 73 |       r.push("\n");
 74 |     }
 75 |     r.push('=');
 76 |   }
 77 |   if (o)
 78 |   {
 79 |     return;
 80 |   }
 81 |   return r.join('');
 82 | }
 83 | 
 84 | /**
 85 |  * Convert radix-64 to binary array
 86 |  * @param {String} t radix-64 string to convert
 87 |  * @returns {Uint8Array} binary array version of input string
 88 |  * @static
 89 |  */
 90 | function r2s(t) {
 91 |   // TODO check atob alternative
 92 |   var c, n;
 93 |   var r = [],
 94 |     s = 0,
 95 |     a = 0;
 96 |   var tl = t.length;
 97 | 
 98 |   for (n = 0; n < tl; n++) {
 99 |     c = b64s.indexOf(t.charAt(n));
100 |     if (c >= 0) {
101 |       if (s) {
102 |         r.push(a | (c >> (6 - s)) & 255);
103 |       }
104 |       s = (s + 2) & 7;
105 |       a = (c << s) & 255;
106 |     }
107 |   }
108 |   return new Uint8Array(r);
109 | }
110 | 
111 | export default {
112 |   encode: s2r,
113 |   decode: r2s
114 | };
115 | 
--------------------------------------------------------------------------------
/src/hkp.js:
--------------------------------------------------------------------------------
 1 | // OpenPGP.js - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2015 Tankred Hase
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /**
19 |  * @fileoverview This class implements a client for the OpenPGP HTTP Keyserver Protocol (HKP)
20 |  * in order to lookup and upload keys on standard public key servers.
21 |  */
22 | 
23 | 'use strict';
24 | 
25 | import config from './config';
26 | 
27 | /**
28 |  * Initialize the HKP client and configure it with the key server url and fetch function.
29 |  * @constructor
30 |  * @param {String}    keyServerBaseUrl  (optional) The HKP key server base url including
31 |  *   the protocol to use e.g. https://pgp.mit.edu
32 |  */
33 | export default function HKP(keyServerBaseUrl) {
34 |   this._baseUrl = keyServerBaseUrl ? keyServerBaseUrl : config.keyserver;
35 |   this._fetch = typeof window !== 'undefined' ? window.fetch : require('node-fetch');
36 | }
37 | 
38 | /**
39 |  * Search for a public key on the key server either by key ID or part of the user ID.
40 |  * @param  {String}   options.keyID   The long public key ID.
41 |  * @param  {String}   options.query   This can be any part of the key user ID such as name
42 |  *   or email address.
43 |  * @return {Promise}          The ascii armored public key.
44 |  */
45 | HKP.prototype.lookup = function(options) {
46 |   var uri = this._baseUrl + '/pks/lookup?op=get&options=mr&search=',
47 |     fetch = this._fetch;
48 | 
49 |   if (options.keyId) {
50 |     uri += '0x' + encodeURIComponent(options.keyId);
51 |   } else if (options.query) {
52 |     uri += encodeURIComponent(options.query);
53 |   } else {
54 |     throw new Error('You must provide a query parameter!');
55 |   }
56 | 
57 |   return fetch(uri).then(function(response) {
58 |     if (response.status === 200) {
59 |       return response.text();
60 |     }
61 | 
62 |   }).then(function(publicKeyArmored) {
63 |     if (!publicKeyArmored || publicKeyArmored.indexOf('-----END PGP PUBLIC KEY BLOCK-----') < 0) {
64 |       return;
65 |     }
66 |     return publicKeyArmored.trim();
67 |   });
68 | };
69 | 
70 | /**
71 |  * Upload a public key to the server.
72 |  * @param  {String}   publicKeyArmored  An ascii armored public key to be uploaded.
73 |  * @return {Promise}
74 |  */
75 | HKP.prototype.upload = function(publicKeyArmored) {
76 |   var uri = this._baseUrl + '/pks/add',
77 |     fetch = this._fetch;
78 | 
79 |   return fetch(uri, {
80 |     method: 'post',
81 |     headers: {
82 |       'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
83 |     },
84 |     body: 'keytext=' + encodeURIComponent(publicKeyArmored)
85 |   });
86 | };
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
  1 | 'use strict';
  2 | 
  3 | /**
  4 |  * Export high level api as default.
  5 |  * Usage:
  6 |  *
  7 |  *   import openpgp from 'openpgp.js'
  8 |  *   openpgp.encryptMessage(keys, text)
  9 |  */
 10 | import * as openpgp from './openpgp';
 11 | export default openpgp;
 12 | 
 13 | /**
 14 |  * Export each high level api function seperately.
 15 |  * Usage:
 16 |  *
 17 |  *   import { encryptMessage } from 'openpgp.js'
 18 |  *   encryptMessage(keys, text)
 19 |  */
 20 | export * from './openpgp';
 21 | 
 22 | /**
 23 |  * @see module:key
 24 |  * @name module:openpgp.key
 25 |  */
 26 | import * as keyMod from './key';
 27 | export const key = keyMod;
 28 | 
 29 | /**
 30 |  * @see module:message
 31 |  * @name module:openpgp.message
 32 |  */
 33 | import * as messageMod from './message';
 34 | export const message = messageMod;
 35 | 
 36 | /**
 37 |  * @see module:cleartext
 38 |  * @name module:openpgp.cleartext
 39 |  */
 40 | import * as cleartextMod from './cleartext';
 41 | export const cleartext = cleartextMod;
 42 | 
 43 | /**
 44 |  * @see module:util
 45 |  * @name module:openpgp.util
 46 |  */
 47 | export { default as util } from './util';
 48 | 
 49 | /**
 50 |  * @see module:packet
 51 |  * @name module:openpgp.packet
 52 |  */
 53 | export { default as packet } from './packet';
 54 | 
 55 | /**
 56 |  * @see module:type/mpi
 57 |  * @name module:openpgp.MPI
 58 |  */
 59 | export { default as MPI } from './type/mpi';
 60 | 
 61 | /**
 62 |  * @see module:type/s2k
 63 |  * @name module:openpgp.S2K
 64 |  */
 65 | export { default as S2K } from './type/s2k';
 66 | 
 67 | /**
 68 |  * @see module:type/keyid
 69 |  * @name module:openpgp.Keyid
 70 |  */
 71 | export { default as Keyid } from './type/keyid';
 72 | 
 73 | /**
 74 |  * @see module:encoding/armor
 75 |  * @name module:openpgp.armor
 76 |  */
 77 | export { default as armor } from './encoding/armor';
 78 | 
 79 | /**
 80 |  * @see module:enums
 81 |  * @name module:openpgp.enums
 82 |  */
 83 | export { default as enums } from './enums';
 84 | 
 85 | /**
 86 |  * @see module:config/config
 87 |  * @name module:openpgp.config
 88 |  */
 89 | export { default as config } from './config/config';
 90 | 
 91 | /**
 92 |  * @see module:crypto
 93 |  * @name module:openpgp.crypto
 94 |  */
 95 | export { default as crypto } from './crypto';
 96 | 
 97 | /**
 98 |  * @see module:keyring
 99 |  * @name module:openpgp.Keyring
100 |  */
101 | export { default as Keyring } from './keyring';
102 | 
103 | /**
104 |  * @see module:worker/async_proxy
105 |  * @name module:openpgp.AsyncProxy
106 |  */
107 | export { default as AsyncProxy } from './worker/async_proxy';
108 | 
109 | /**
110 |  * @see module:hkp
111 |  * @name module:openpgp.HKP
112 |  */
113 | export { default as HKP } from './hkp';
--------------------------------------------------------------------------------
/src/keyring/index.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | /**
 4 |  * @see module:keyring/keyring
 5 |  * @module keyring
 6 |  */
 7 | import Keyring from './keyring.js';
 8 | 
 9 | import localstore from './localstore.js';
10 | Keyring.localstore = localstore;
11 | 
12 | export default Keyring;
13 | 
--------------------------------------------------------------------------------
/src/keyring/keyring.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * The class that deals with storage of the keyring. Currently the only option is to use HTML5 local storage.
 20 |  * @requires enums
 21 |  * @requires key
 22 |  * @requires util
 23 |  * @module keyring/keyring
 24 |  */
 25 | 
 26 | 'use strict';
 27 | 
 28 | import * as keyModule from '../key.js';
 29 | import LocalStore from './localstore.js';
 30 | 
 31 | /**
 32 |  * Initialization routine for the keyring. This method reads the
 33 |  * keyring from HTML5 local storage and initializes this instance.
 34 |  * @constructor
 35 |  * @param {class} [storeHandler] class implementing load() and store() methods
 36 |  */
 37 | export default function Keyring(storeHandler) {
 38 |   this.storeHandler = storeHandler || new LocalStore();
 39 |   this.publicKeys = new KeyArray(this.storeHandler.loadPublic());
 40 |   this.privateKeys = new KeyArray(this.storeHandler.loadPrivate());
 41 | }
 42 | 
 43 | /**
 44 |  * Calls the storeHandler to save the keys
 45 |  */
 46 | Keyring.prototype.store = function () {
 47 |   this.storeHandler.storePublic(this.publicKeys.keys);
 48 |   this.storeHandler.storePrivate(this.privateKeys.keys);
 49 | };
 50 | 
 51 | /**
 52 |  * Clear the keyring - erase all the keys
 53 |  */
 54 | Keyring.prototype.clear = function() {
 55 |   this.publicKeys.keys = [];
 56 |   this.privateKeys.keys = [];
 57 | };
 58 | 
 59 | /**
 60 |  * Searches the keyring for keys having the specified key id
 61 |  * @param {String} keyId provided as string of lowercase hex number
 62 |  * withouth 0x prefix (can be 16-character key ID or fingerprint)
 63 |  * @param  {Boolean} deep if true search also in subkeys
 64 |  * @return {Array|null} keys found or null
 65 |  */
 66 | Keyring.prototype.getKeysForId = function (keyId, deep) {
 67 |   var result = [];
 68 |   result = result.concat(this.publicKeys.getForId(keyId, deep) || []);
 69 |   result = result.concat(this.privateKeys.getForId(keyId, deep) || []);
 70 |   return result.length ? result : null;
 71 | };
 72 | 
 73 | /**
 74 |  * Removes keys having the specified key id from the keyring
 75 |  * @param {String} keyId provided as string of lowercase hex number
 76 |  * withouth 0x prefix (can be 16-character key ID or fingerprint)
 77 |  * @return {Array|null} keys found or null
 78 |  */
 79 | Keyring.prototype.removeKeysForId = function (keyId) {
 80 |   var result = [];
 81 |   result = result.concat(this.publicKeys.removeForId(keyId) || []);
 82 |   result = result.concat(this.privateKeys.removeForId(keyId) || []);
 83 |   return result.length ? result : null;
 84 | };
 85 | 
 86 | /**
 87 |  * Get all public and private keys
 88 |  * @return {Array} all keys
 89 |  */
 90 | Keyring.prototype.getAllKeys = function () {
 91 |   return this.publicKeys.keys.concat(this.privateKeys.keys);
 92 | };
 93 | 
 94 | /**
 95 |  * Array of keys
 96 |  * @param {Array} keys The keys to store in this array
 97 |  */
 98 | function KeyArray(keys) {
 99 |   this.keys = keys;
100 | }
101 | 
102 | /**
103 |  * Searches all keys in the KeyArray matching the address or address part of the user ids
104 |  * @param {String} email email address to search for
105 |  * @return {Array} The public keys associated with provided email address.
106 |  */
107 | KeyArray.prototype.getForAddress = function(email) {
108 |   var results = [];
109 |   for (var i = 0; i < this.keys.length; i++) {
110 |     if (emailCheck(email, this.keys[i])) {
111 |       results.push(this.keys[i]);
112 |     }
113 |   }
114 |   return results;
115 | };
116 | 
117 | /**
118 |  * Checks a key to see if it matches the specified email address
119 |  * @private
120 |  * @param {String} email email address to search for
121 |  * @param {module:key~Key} key The key to be checked.
122 |  * @return {Boolean} True if the email address is defined in the specified key
123 |  */
124 | function emailCheck(email, key) {
125 |   email = email.toLowerCase();
126 |   // escape email before using in regular expression
127 |   var emailEsc = email.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
128 |   var emailRegex = new RegExp('<' + emailEsc + '>');
129 |   var userIds = key.getUserIds();
130 |   for (var i = 0; i < userIds.length; i++) {
131 |     var userId = userIds[i].toLowerCase();
132 |     if (email === userId || emailRegex.test(userId)) {
133 |       return true;
134 |     }
135 |   }
136 |   return false;
137 | }
138 | 
139 | /**
140 |  * Checks a key to see if it matches the specified keyid
141 |  * @private
142 |  * @param {String} keyId provided as string of lowercase hex number
143 |  * withouth 0x prefix (can be 16-character key ID or fingerprint)
144 |  * @param {module:packet/secret_key|public_key|public_subkey|secret_subkey} keypacket The keypacket to be checked
145 |  * @return {Boolean} True if keypacket has the specified keyid
146 |  */
147 | function keyIdCheck(keyId, keypacket) {
148 |   if (keyId.length === 16) {
149 |     return keyId === keypacket.getKeyId().toHex();
150 |   } else {
151 |     return keyId === keypacket.getFingerprint();
152 |   }
153 | }
154 | 
155 | /**
156 |  * Searches the KeyArray for a key having the specified key id
157 |  * @param {String} keyId provided as string of lowercase hex number
158 |  * withouth 0x prefix (can be 16-character key ID or fingerprint)
159 |  * @param  {Boolean} deep if true search also in subkeys
160 |  * @return {module:key~Key|null} key found or null
161 |  */
162 | KeyArray.prototype.getForId = function (keyId, deep) {
163 |   for (var i = 0; i < this.keys.length; i++) {
164 |     if (keyIdCheck(keyId, this.keys[i].primaryKey)) {
165 |       return this.keys[i];
166 |     }
167 |     if (deep && this.keys[i].subKeys) {
168 |       for (var j = 0; j < this.keys[i].subKeys.length; j++) {
169 |         if (keyIdCheck(keyId, this.keys[i].subKeys[j].subKey)) {
170 |           return this.keys[i];
171 |         }
172 |       }
173 |     }
174 |   }
175 |   return null;
176 | };
177 | 
178 | /**
179 |  * Imports a key from an ascii armored message
180 |  * @param {String} armored message to read the keys/key from
181 |  * @return {Array|null} array of error objects or null
182 |  */
183 | KeyArray.prototype.importKey = function (armored) {
184 |   var imported = keyModule.readArmored(armored);
185 |   var that = this;
186 |   imported.keys.forEach(function(key) {
187 |     // check if key already in key array
188 |     var keyidHex = key.primaryKey.getKeyId().toHex();
189 |     var keyFound = that.getForId(keyidHex);
190 |     if (keyFound) {
191 |       keyFound.update(key);
192 |     } else {
193 |       that.push(key);
194 |     }
195 |   });
196 |   return imported.err ? imported.err : null;
197 | };
198 | 
199 | /**
200 |  * Add key to KeyArray
201 |  * @param {module:key~Key} key The key that will be added to the keyring
202 |  * @return {Number} The new length of the KeyArray
203 |  */
204 | KeyArray.prototype.push = function (key) {
205 |   return this.keys.push(key);
206 | };
207 | 
208 | /**
209 |  * Removes a key with the specified keyid from the keyring
210 |  * @param {String} keyId provided as string of lowercase hex number
211 |  * withouth 0x prefix (can be 16-character key ID or fingerprint)
212 |  * @return {module:key~Key|null} The key object which has been removed or null
213 |  */
214 | KeyArray.prototype.removeForId = function (keyId) {
215 |   for (var i = 0; i < this.keys.length; i++) {
216 |     if (keyIdCheck(keyId, this.keys[i].primaryKey)) {
217 |       return this.keys.splice(i, 1)[0];
218 |     }
219 |   }
220 |   return null;
221 | };
222 | 
--------------------------------------------------------------------------------
/src/keyring/localstore.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * The class that deals with storage of the keyring. Currently the only option is to use HTML5 local storage.
 20 |  * @requires config
 21 |  * @module keyring/localstore
 22 |  * @param {String} prefix prefix for itemnames in localstore
 23 |  */
 24 | 
 25 | 'use strict';
 26 | 
 27 | import config from '../config';
 28 | import * as keyModule from '../key.js';
 29 | import util from '../util.js';
 30 | 
 31 | export default function LocalStore(prefix) {
 32 |   prefix = prefix || 'openpgp-';
 33 |   this.publicKeysItem = prefix + this.publicKeysItem;
 34 |   this.privateKeysItem = prefix + this.privateKeysItem;
 35 |   if (typeof window !== 'undefined' && window.localStorage) {
 36 |     this.storage = window.localStorage;
 37 |   } else {
 38 |     this.storage = new (require('node-localstorage').LocalStorage)(config.node_store);
 39 |   }
 40 | }
 41 | 
 42 | /*
 43 |  * Declare the localstore itemnames
 44 |  */
 45 | LocalStore.prototype.publicKeysItem = 'public-keys';
 46 | LocalStore.prototype.privateKeysItem = 'private-keys';
 47 | 
 48 | /**
 49 |  * Load the public keys from HTML5 local storage.
 50 |  * @return {Array} array of keys retrieved from localstore
 51 |  */
 52 | LocalStore.prototype.loadPublic = function () {
 53 |   return loadKeys(this.storage, this.publicKeysItem);
 54 | };
 55 | 
 56 | /**
 57 |  * Load the private keys from HTML5 local storage.
 58 |  * @return {Array} array of keys retrieved from localstore
 59 |  */
 60 | LocalStore.prototype.loadPrivate = function () {
 61 |   return loadKeys(this.storage, this.privateKeysItem);
 62 | };
 63 | 
 64 | function loadKeys(storage, itemname) {
 65 |   var armoredKeys = JSON.parse(storage.getItem(itemname));
 66 |   var keys = [];
 67 |   if (armoredKeys !== null && armoredKeys.length !== 0) {
 68 |     var key;
 69 |     for (var i = 0; i < armoredKeys.length; i++) {
 70 |       key = keyModule.readArmored(armoredKeys[i]);
 71 |       if (!key.err) {
 72 |         keys.push(key.keys[0]);
 73 |       } else {
 74 |         util.print_debug("Error reading armored key from keyring index: " + i);
 75 |       }
 76 |     }
 77 |   }
 78 |   return keys;
 79 | }
 80 | 
 81 | /**
 82 |  * Saves the current state of the public keys to HTML5 local storage.
 83 |  * The key array gets stringified using JSON
 84 |  * @param {Array} keys array of keys to save in localstore
 85 |  */
 86 | LocalStore.prototype.storePublic = function (keys) {
 87 |   storeKeys(this.storage, this.publicKeysItem, keys);
 88 | };
 89 | 
 90 | /**
 91 |  * Saves the current state of the private keys to HTML5 local storage.
 92 |  * The key array gets stringified using JSON
 93 |  * @param {Array} keys array of keys to save in localstore
 94 |  */
 95 | LocalStore.prototype.storePrivate = function (keys) {
 96 |   storeKeys(this.storage, this.privateKeysItem, keys);
 97 | };
 98 | 
 99 | function storeKeys(storage, itemname, keys) {
100 |   var armoredKeys = [];
101 |   if (keys.length) {
102 |     for (var i = 0; i < keys.length; i++) {
103 |       armoredKeys.push(keys[i].armor());
104 |     }
105 |     storage.setItem(itemname, JSON.stringify(armoredKeys));
106 |   } else {
107 |     storage.removeItem(itemname);
108 |   }
109 | }
110 | 
--------------------------------------------------------------------------------
/src/packet/all_packets.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @requires enums
 3 |  * @module packet
 4 |  */
 5 | 
 6 | 'use strict';
 7 | 
 8 | import enums from '../enums.js';
 9 | import * as packets from './all_packets.js'; // re-import module to parse packets from tag
10 | 
11 | /** @see module:packet/compressed */
12 | export { default as Compressed } from './compressed.js';
13 | /** @see module:packet/sym_encrypted_integrity_protected */
14 | export { default as SymEncryptedIntegrityProtected } from './sym_encrypted_integrity_protected.js';
15 | /** @see module:packet/public_key_encrypted_session_key */
16 | export { default as PublicKeyEncryptedSessionKey } from './public_key_encrypted_session_key.js';
17 | /** @see module:packet/sym_encrypted_session_key */
18 | export { default as SymEncryptedSessionKey } from './sym_encrypted_session_key.js';
19 | /** @see module:packet/literal */
20 | export { default as Literal } from './literal.js';
21 | /** @see module:packet/public_key */
22 | export { default as PublicKey } from './public_key.js';
23 | /** @see module:packet/symmetrically_encrypted */
24 | export { default as SymmetricallyEncrypted } from './symmetrically_encrypted.js';
25 | /** @see module:packet/marker */
26 | export { default as Marker } from './marker.js';
27 | /** @see module:packet/public_subkey */
28 | export { default as PublicSubkey } from './public_subkey.js';
29 | /** @see module:packet/user_attribute */
30 | export { default as UserAttribute } from './user_attribute.js';
31 | /** @see module:packet/one_pass_signature */
32 | export { default as OnePassSignature } from './one_pass_signature.js';
33 | /** @see module:packet/secret_key */
34 | export { default as SecretKey } from './secret_key.js';
35 | /** @see module:packet/userid */
36 | export { default as Userid } from './userid.js';
37 | /** @see module:packet/secret_subkey */
38 | export { default as SecretSubkey } from './secret_subkey.js';
39 | /** @see module:packet/signature */
40 | export { default as Signature } from './signature.js';
41 | /** @see module:packet/trust */
42 | export { default as Trust } from './trust.js';
43 | 
44 | /**
45 |  * Allocate a new packet
46 |  * @param {String} tag property name from {@link module:enums.packet}
47 |  * @returns {Object} new packet object with type based on tag
48 |  */
49 | export function newPacketFromTag(tag) {
50 |   return new packets[packetClassFromTagName(tag)]();
51 | }
52 | 
53 | /**
54 |  * Allocate a new packet from structured packet clone
55 |  * See {@link http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#safe-passing-of-structured-data}
56 |  * @param {Object} packetClone packet clone
57 |  * @returns {Object} new packet object with data from packet clone
58 |  */
59 | export function fromStructuredClone(packetClone) {
60 |   var tagName = enums.read(enums.packet, packetClone.tag);
61 |   var packet = newPacketFromTag(tagName);
62 |   for (var attr in packetClone) {
63 |     if (packetClone.hasOwnProperty(attr)) {
64 |       packet[attr] = packetClone[attr];
65 |     }
66 |   }
67 |   if (packet.postCloneTypeFix) {
68 |     packet.postCloneTypeFix();
69 |   }
70 |   return packet;
71 | }
72 | 
73 | /**
74 |  * Convert tag name to class name
75 |  * @param {String} tag property name from {@link module:enums.packet}
76 |  * @returns {String}
77 |  */
78 | function packetClassFromTagName(tag) {
79 |   return tag.substr(0, 1).toUpperCase() + tag.substr(1);
80 | }
81 | 
--------------------------------------------------------------------------------
/src/packet/clone.js:
--------------------------------------------------------------------------------
  1 | // OpenPGP.js - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2015 Tankred Hase
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * @fileoverview This module implements packet list cloning required to
 20 |  * pass certain object types beteen the web worker and main thread using
 21 |  * the structured cloning algorithm.
 22 |  */
 23 | 
 24 | 'use strict';
 25 | 
 26 | import * as key from '../key.js';
 27 | import * as message from '../message.js';
 28 | import * as cleartext from '../cleartext.js';
 29 | import Packetlist from './packetlist.js';
 30 | import type_keyid from '../type/keyid.js';
 31 | 
 32 | 
 33 | //////////////////////////////
 34 | //                          //
 35 | //   Packetlist --> Clone   //
 36 | //                          //
 37 | //////////////////////////////
 38 | 
 39 | 
 40 | /**
 41 |  * Create a packetlist from the correspoding object types.
 42 |  * @param  {Object} options   the object passed to and from the web worker
 43 |  * @return {Object}           a mutated version of the options optject
 44 |  */
 45 | export function clonePackets(options) {
 46 |   if(options.publicKeys) {
 47 |     options.publicKeys = options.publicKeys.map(key => key.toPacketlist());
 48 |   }
 49 |   if(options.privateKeys) {
 50 |     options.privateKeys = options.privateKeys.map(key => key.toPacketlist());
 51 |   }
 52 |   if(options.privateKey) {
 53 |     options.privateKey = options.privateKey.toPacketlist();
 54 |   }
 55 |   if (options.key) {
 56 |     options.key = options.key.toPacketlist();
 57 |   }
 58 |   return options;
 59 | }
 60 | 
 61 | 
 62 | //////////////////////////////
 63 | //                          //
 64 | //   Clone --> Packetlist   //
 65 | //                          //
 66 | //////////////////////////////
 67 | 
 68 | 
 69 | /**
 70 |  * Creates an object with the correct prototype from a corresponding packetlist.
 71 |  * @param  {Object} options   the object passed to and from the web worker
 72 |  * @param  {String} method    the public api function name to be delegated to the worker
 73 |  * @return {Object}           a mutated version of the options optject
 74 |  */
 75 | export function parseClonedPackets(options, method) {
 76 |   if(options.publicKeys) {
 77 |     options.publicKeys = options.publicKeys.map(packetlistCloneToKey);
 78 |   }
 79 |   if(options.privateKeys) {
 80 |     options.privateKeys = options.privateKeys.map(packetlistCloneToKey);
 81 |   }
 82 |   if(options.privateKey) {
 83 |     options.privateKey = packetlistCloneToKey(options.privateKey);
 84 |   }
 85 |   if (options.key) {
 86 |     options.key = packetlistCloneToKey(options.key);
 87 |   }
 88 |   if (options.message && (method === 'sign' || method === 'verify')) { // sign and verify support only CleartextMessage
 89 |     options.message = packetlistCloneToCleartextMessage(options.message);
 90 |   } else if (options.message) {
 91 |     options.message = packetlistCloneToMessage(options.message);
 92 |   }
 93 |   if (options.signatures) {
 94 |     options.signatures = options.signatures.map(packetlistCloneToSignature);
 95 |   }
 96 |   return options;
 97 | }
 98 | 
 99 | function packetlistCloneToKey(clone) {
100 |   const packetlist = Packetlist.fromStructuredClone(clone);
101 |   return new key.Key(packetlist);
102 | }
103 | 
104 | function packetlistCloneToMessage(clone) {
105 |   const packetlist = Packetlist.fromStructuredClone(clone.packets);
106 |   return new message.Message(packetlist);
107 | }
108 | 
109 | function packetlistCloneToCleartextMessage(clone) {
110 |   var packetlist = Packetlist.fromStructuredClone(clone.packets);
111 |   return new cleartext.CleartextMessage(clone.text, packetlist);
112 | }
113 | 
114 | function packetlistCloneToSignature(clone) {
115 |   clone.keyid = type_keyid.fromClone(clone.keyid);
116 |   return clone;
117 | }
118 | 
--------------------------------------------------------------------------------
/src/packet/compressed.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * Implementation of the Compressed Data Packet (Tag 8)
 20 |  * 
 21 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.6|RFC4880 5.6}: The Compressed Data packet contains compressed data.  Typically,
 22 |  * this packet is found as the contents of an encrypted packet, or following
 23 |  * a Signature or One-Pass Signature packet, and contains a literal data packet.
 24 |  * @requires compression/zlib
 25 |  * @requires compression/rawinflate
 26 |  * @requires compression/rawdeflate
 27 |  * @requires enums
 28 |  * @requires util
 29 |  * @module packet/compressed
 30 |  */
 31 | 
 32 | 'use strict';
 33 | 
 34 | import enums from '../enums.js';
 35 | import util from '../util.js';
 36 | import Zlib from '../compression/zlib.min.js';
 37 | import * as Inflater from '../compression/rawinflate.js';
 38 | import * as Deflater from '../compression/rawdeflate.js';
 39 | 
 40 | /**
 41 |  * @constructor
 42 |  */
 43 | export default function Compressed() {
 44 |   /**
 45 |    * Packet type
 46 |    * @type {module:enums.packet}
 47 |    */
 48 |   this.tag = enums.packet.compressed;
 49 |   /**
 50 |    * List of packets
 51 |    * @type {module:packet/packetlist}
 52 |    */
 53 |   this.packets = null;
 54 |   /**
 55 |    * Compression algorithm
 56 |    * @type {compression}
 57 |    */
 58 |   this.algorithm = 'zip';
 59 | 
 60 |   /**
 61 |    * Compressed packet data
 62 |    * @type {String}
 63 |    */
 64 |   this.compressed = null;
 65 | }
 66 | 
 67 | /**
 68 |  * Parsing function for the packet.
 69 |  * @param {String} bytes Payload of a tag 8 packet
 70 |  */
 71 | Compressed.prototype.read = function (bytes) {
 72 |   // One octet that gives the algorithm used to compress the packet.
 73 |   this.algorithm = enums.read(enums.compression, bytes[0]);
 74 | 
 75 |   // Compressed data, which makes up the remainder of the packet.
 76 |   this.compressed = bytes.subarray(1, bytes.length);
 77 | 
 78 |   this.decompress();
 79 | };
 80 | 
 81 | 
 82 | 
 83 | /**
 84 |  * Return the compressed packet.
 85 |  * @return {String} binary compressed packet
 86 |  */
 87 | Compressed.prototype.write = function () {
 88 |   if (this.compressed === null) {
 89 |     this.compress();
 90 |   }
 91 | 
 92 |   return util.concatUint8Array(new Uint8Array([enums.write(enums.compression, this.algorithm)]), this.compressed);
 93 | };
 94 | 
 95 | 
 96 | /**
 97 |  * Decompression method for decompressing the compressed data
 98 |  * read by read_packet
 99 |  */
100 | Compressed.prototype.decompress = function () {
101 |   var decompressed, inflate;
102 | 
103 |   switch (this.algorithm) {
104 |     case 'uncompressed':
105 |       decompressed = this.compressed;
106 |       break;
107 | 
108 |     case 'zip':
109 |       inflate = new Inflater.RawInflate(this.compressed);
110 |       decompressed = inflate.decompress();
111 |       break;
112 | 
113 |     case 'zlib':
114 |       inflate = new Zlib.Zlib.Inflate(this.compressed);
115 |       decompressed = inflate.decompress();
116 |       break;
117 | 
118 |     case 'bzip2':
119 |       // TODO: need to implement this
120 |       throw new Error('Compression algorithm BZip2 [BZ2] is not implemented.');
121 | 
122 |     default:
123 |       throw new Error("Compression algorithm unknown :" + this.alogrithm);
124 |   }
125 | 
126 |   this.packets.read(decompressed);
127 | };
128 | 
129 | /**
130 |  * Compress the packet data (member decompressedData)
131 |  */
132 | Compressed.prototype.compress = function () {
133 |   var uncompressed, deflate;
134 |   uncompressed = this.packets.write();
135 | 
136 |   switch (this.algorithm) {
137 | 
138 |     case 'uncompressed':
139 |       // - Uncompressed
140 |       this.compressed = uncompressed;
141 |       break;
142 | 
143 |     case 'zip':
144 |       // - ZIP [RFC1951]
145 |       deflate = new Deflater.RawDeflate(uncompressed);
146 |       this.compressed = deflate.compress();
147 |       break;
148 | 
149 |     case 'zlib':
150 |       // - ZLIB [RFC1950]
151 |       deflate = new Zlib.Zlib.Deflate(uncompressed);
152 |       this.compressed = deflate.compress();
153 |       break;
154 | 
155 |     case 'bzip2':
156 |       //  - BZip2 [BZ2]
157 |       // TODO: need to implement this
158 |       throw new Error("Compression algorithm BZip2 [BZ2] is not implemented.");
159 | 
160 |     default:
161 |       throw new Error("Compression algorithm unknown :" + this.type);
162 |   }
163 | };
164 | 
--------------------------------------------------------------------------------
/src/packet/index.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | import * as packets from './all_packets.js';
 4 | import * as clone from './clone.js';
 5 | import List from './packetlist.js';
 6 | 
 7 | const mod = {
 8 |   /** @see module:packet/packetlist */
 9 |   List: List,
10 |   /** @see module:packet/clone */
11 |   clone: clone
12 | };
13 | 
14 | for (let i in packets) {
15 |   mod[i] = packets[i];
16 | }
17 | 
18 | export default mod;
19 | 
--------------------------------------------------------------------------------
/src/packet/literal.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * Implementation of the Literal Data Packet (Tag 11)
 20 |  * 
 21 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.9|RFC4880 5.9}: A Literal Data packet contains the body of a message; data that
 22 |  * is not to be further interpreted.
 23 |  * @requires enums
 24 |  * @requires util
 25 |  * @module packet/literal
 26 |  */
 27 | 
 28 | 'use strict';
 29 | 
 30 | import util from '../util.js';
 31 | import enums from '../enums.js';
 32 | 
 33 | /**
 34 |  * @constructor
 35 |  */
 36 | export default function Literal() {
 37 |   this.tag = enums.packet.literal;
 38 |   this.format = 'utf8'; // default format for literal data packets
 39 |   this.date = new Date();
 40 |   this.data = new Uint8Array(0); // literal data representation
 41 |   this.filename = 'msg.txt';
 42 | }
 43 | 
 44 | /**
 45 |  * Set the packet data to a javascript native string, end of line
 46 |  * will be normalized to \r\n and by default text is converted to UTF8
 47 |  * @param {String} text Any native javascript string
 48 |  */
 49 | Literal.prototype.setText = function(text) {
 50 |   // normalize EOL to \r\n
 51 |   text = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').replace(/\n/g, '\r\n');
 52 |   // encode UTF8
 53 |   this.data = this.format === 'utf8' ? util.str2Uint8Array(util.encode_utf8(text)) : util.str2Uint8Array(text);
 54 | };
 55 | 
 56 | /**
 57 |  * Returns literal data packets as native JavaScript string
 58 |  * with normalized end of line to \n
 59 |  * @return {String} literal data as text
 60 |  */
 61 | Literal.prototype.getText = function() {
 62 |   // decode UTF8
 63 |   var text = util.decode_utf8(util.Uint8Array2str(this.data));
 64 |   // normalize EOL to \n
 65 |   return text.replace(/\r\n/g, '\n');
 66 | };
 67 | 
 68 | /**
 69 |  * Set the packet data to value represented by the provided string of bytes.
 70 |  * @param {Uint8Array} bytes The string of bytes
 71 |  * @param {utf8|binary|text} format The format of the string of bytes
 72 |  */
 73 | Literal.prototype.setBytes = function(bytes, format) {
 74 |   this.format = format;
 75 |   this.data = bytes;
 76 | };
 77 | 
 78 | 
 79 | /**
 80 |  * Get the byte sequence representing the literal packet data
 81 |  * @returns {Uint8Array} A sequence of bytes
 82 |  */
 83 | Literal.prototype.getBytes = function() {
 84 |   return this.data;
 85 | };
 86 | 
 87 | 
 88 | /**
 89 |  * Sets the filename of the literal packet data
 90 |  * @param {String} filename Any native javascript string
 91 |  */
 92 | Literal.prototype.setFilename = function(filename) {
 93 |   this.filename = filename;
 94 | };
 95 | 
 96 | 
 97 | /**
 98 |  * Get the filename of the literal packet data
 99 |  * @returns {String} filename
100 |  */
101 | Literal.prototype.getFilename = function() {
102 |   return this.filename;
103 | };
104 | 
105 | 
106 | /**
107 |  * Parsing function for a literal data packet (tag 11).
108 |  *
109 |  * @param {Uint8Array} input Payload of a tag 11 packet
110 |  * @return {module:packet/literal} object representation
111 |  */
112 | Literal.prototype.read = function(bytes) {
113 |   // - A one-octet field that describes how the data is formatted.
114 |   var format = enums.read(enums.literal, bytes[0]);
115 | 
116 |   var filename_len = bytes[1];
117 |   this.filename = util.decode_utf8(util.Uint8Array2str(bytes.subarray(2, 2 + filename_len)));
118 | 
119 |   this.date = util.readDate(bytes.subarray(2 + filename_len, 2 + filename_len + 4));
120 | 
121 |   var data = bytes.subarray(6 + filename_len, bytes.length);
122 | 
123 |   this.setBytes(data, format);
124 | };
125 | 
126 | /**
127 |  * Creates a string representation of the packet
128 |  *
129 |  * @return {Uint8Array} Uint8Array representation of the packet
130 |  */
131 | Literal.prototype.write = function() {
132 |   var filename = util.str2Uint8Array(util.encode_utf8(this.filename));
133 |   var filename_length = new Uint8Array([filename.length]);
134 | 
135 |   var format = new Uint8Array([enums.write(enums.literal, this.format)]);
136 |   var date = util.writeDate(this.date);
137 |   var data = this.getBytes();
138 | 
139 |   return util.concatUint8Array([format, filename_length, filename, date, data]);
140 | };
141 | 
--------------------------------------------------------------------------------
/src/packet/marker.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | 
19 | /**
20 |  * Implementation of the strange "Marker packet" (Tag 10)
21 |  * 
22 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.8|RFC4880 5.8}: An experimental version of PGP used this packet as the Literal
23 |  * packet, but no released version of PGP generated Literal packets with this
24 |  * tag. With PGP 5.x, this packet has been reassigned and is reserved for use as
25 |  * the Marker packet.
26 |  * 
27 |  * Such a packet MUST be ignored when received.
28 |  * @requires enums
29 |  * @module packet/marker
30 |  */
31 | 
32 | 'use strict';
33 | 
34 | import enums from '../enums.js';
35 | 
36 | /**
37 |  * @constructor
38 |  */
39 | export default function Marker() {
40 |   this.tag = enums.packet.marker;
41 | }
42 | 
43 | /**
44 |  * Parsing function for a literal data packet (tag 10).
45 |  *
46 |  * @param {String} input Payload of a tag 10 packet
47 |  * @param {Integer} position
48 |  *            Position to start reading from the input string
49 |  * @param {Integer} len
50 |  *            Length of the packet or the remaining length of
51 |  *            input at position
52 |  * @return {module:packet/marker} Object representation
53 |  */
54 | Marker.prototype.read = function (bytes) {
55 |   if (bytes[0] === 0x50 && // P
56 |       bytes[1] === 0x47 && // G
57 |       bytes[2] === 0x50) { // P
58 |     return true;
59 |   }
60 |   // marker packet does not contain "PGP"
61 |   return false;
62 | };
63 | 
--------------------------------------------------------------------------------
/src/packet/one_pass_signature.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * Implementation of the One-Pass Signature Packets (Tag 4)
 20 |  * 
 21 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.4|RFC4880 5.4}: The One-Pass Signature packet precedes the signed data and contains
 22 |  * enough information to allow the receiver to begin calculating any
 23 |  * hashes needed to verify the signature.  It allows the Signature
 24 |  * packet to be placed at the end of the message, so that the signer
 25 |  * can compute the entire signed message in one pass.
 26 | * @requires util
 27 |  * @requires enums
 28 |  * @requires type/keyid
 29 |  * @module packet/one_pass_signature
 30 | */
 31 | 
 32 | 'use strict';
 33 | 
 34 | import util from '../util.js';
 35 | import enums from '../enums.js';
 36 | import type_keyid from '../type/keyid.js';
 37 | 
 38 | /**
 39 |  * @constructor
 40 |  */
 41 | export default function OnePassSignature() {
 42 |   this.tag = enums.packet.onePassSignature; // The packet type
 43 |   this.version = null; // A one-octet version number.  The current version is 3.
 44 |   this.type = null; // A one-octet signature type.  Signature types are described in {@link http://tools.ietf.org/html/rfc4880#section-5.2.1|RFC4880 Section 5.2.1}.
 45 |   this.hashAlgorithm = null; // A one-octet number describing the hash algorithm used. (See {@link http://tools.ietf.org/html/rfc4880#section-9.4|RFC4880 9.4})
 46 |   this.publicKeyAlgorithm = null; // A one-octet number describing the public-key algorithm used. (See {@link http://tools.ietf.org/html/rfc4880#section-9.1|RFC4880 9.1})
 47 |   this.signingKeyId = null; // An eight-octet number holding the Key ID of the signing key.
 48 |   this.flags = null; //  A one-octet number holding a flag showing whether the signature is nested.  A zero value indicates that the next packet is another One-Pass Signature packet that describes another signature to be applied to the same message data.
 49 | }
 50 | 
 51 | /**
 52 |  * parsing function for a one-pass signature packet (tag 4).
 53 |  * @param {Uint8Array} bytes payload of a tag 4 packet
 54 |  * @return {module:packet/one_pass_signature} object representation
 55 |  */
 56 | OnePassSignature.prototype.read = function (bytes) {
 57 |   var mypos = 0;
 58 |   // A one-octet version number.  The current version is 3.
 59 |   this.version = bytes[mypos++];
 60 | 
 61 |   // A one-octet signature type.  Signature types are described in
 62 |   //   Section 5.2.1.
 63 |   this.type = enums.read(enums.signature, bytes[mypos++]);
 64 | 
 65 |   // A one-octet number describing the hash algorithm used.
 66 |   this.hashAlgorithm = enums.read(enums.hash, bytes[mypos++]);
 67 | 
 68 |   // A one-octet number describing the public-key algorithm used.
 69 |   this.publicKeyAlgorithm = enums.read(enums.publicKey, bytes[mypos++]);
 70 | 
 71 |   // An eight-octet number holding the Key ID of the signing key.
 72 |   this.signingKeyId = new type_keyid();
 73 |   this.signingKeyId.read(bytes.subarray(mypos, mypos + 8));
 74 |   mypos += 8;
 75 | 
 76 |   // A one-octet number holding a flag showing whether the signature
 77 |   //   is nested.  A zero value indicates that the next packet is
 78 |   //   another One-Pass Signature packet that describes another
 79 |   //   signature to be applied to the same message data.
 80 |   this.flags = bytes[mypos++];
 81 |   return this;
 82 | };
 83 | 
 84 | /**
 85 |  * creates a string representation of a one-pass signature packet
 86 |  * @return {Uint8Array} a Uint8Array representation of a one-pass signature packet
 87 |  */
 88 | OnePassSignature.prototype.write = function () {
 89 | 
 90 |   var start = new Uint8Array([3, enums.write(enums.signature, this.type),
 91 |     enums.write(enums.hash, this.hashAlgorithm),
 92 |     enums.write(enums.publicKey, this.publicKeyAlgorithm)]);
 93 | 
 94 |   var end = new Uint8Array([this.flags]);
 95 | 
 96 |   return util.concatUint8Array([start, this.signingKeyId.write(), end]);
 97 | };
 98 | 
 99 | /**
100 |  * Fix custom types after cloning
101 |  */
102 | OnePassSignature.prototype.postCloneTypeFix = function() {
103 |   this.signingKeyId = type_keyid.fromClone(this.signingKeyId);
104 | };
105 | 
--------------------------------------------------------------------------------
/src/packet/packetlist.js:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * This class represents a list of openpgp packets.
  3 |  * Take care when iterating over it - the packets themselves
  4 |  * are stored as numerical indices.
  5 |  * @requires util
  6 |  * @requires enums
  7 |  * @requires packet
  8 |  * @requires packet/packet
  9 |  * @module packet/packetlist
 10 |  */
 11 | 
 12 | 'use strict';
 13 | 
 14 | import util from '../util';
 15 | import packetParser from './packet.js';
 16 | import * as packets from './all_packets.js';
 17 | import enums from '../enums.js';
 18 | 
 19 | /**
 20 |  * @constructor
 21 |  */
 22 | export default function Packetlist() {
 23 |   /** The number of packets contained within the list.
 24 |    * @readonly
 25 |    * @type {Integer} */
 26 |   this.length = 0;
 27 | }
 28 | /**
 29 |  * Reads a stream of binary data and interprents it as a list of packets.
 30 |  * @param {Uint8Array} A Uint8Array of bytes.
 31 |  */
 32 | Packetlist.prototype.read = function (bytes) {
 33 |   var i = 0;
 34 | 
 35 |   while (i < bytes.length) {
 36 |     var parsed = packetParser.read(bytes, i, bytes.length - i);
 37 |     i = parsed.offset;
 38 | 
 39 |     var tag = enums.read(enums.packet, parsed.tag);
 40 |     var packet = packets.newPacketFromTag(tag);
 41 | 
 42 |     this.push(packet);
 43 |     packet.read(parsed.packet);
 44 |   }
 45 | };
 46 | 
 47 | /**
 48 |  * Creates a binary representation of openpgp objects contained within the
 49 |  * class instance.
 50 |  * @returns {Uint8Array} A Uint8Array containing valid openpgp packets.
 51 |  */
 52 | Packetlist.prototype.write = function () {
 53 |   var arr = [];
 54 | 
 55 |   for (var i = 0; i < this.length; i++) {
 56 |     var packetbytes = this[i].write();
 57 |     arr.push(packetParser.writeHeader(this[i].tag, packetbytes.length));
 58 |     arr.push(packetbytes);
 59 |   }
 60 | 
 61 |   return util.concatUint8Array(arr);
 62 | };
 63 | 
 64 | /**
 65 |  * Adds a packet to the list. This is the only supported method of doing so;
 66 |  * writing to packetlist[i] directly will result in an error.
 67 |  */
 68 | Packetlist.prototype.push = function (packet) {
 69 |   if (!packet) {
 70 |     return;
 71 |   }
 72 | 
 73 |   packet.packets = packet.packets || new Packetlist();
 74 | 
 75 |   this[this.length] = packet;
 76 |   this.length++;
 77 | };
 78 | 
 79 | /**
 80 | * Creates a new PacketList with all packets that pass the test implemented by the provided function.
 81 | */
 82 | Packetlist.prototype.filter = function (callback) {
 83 | 
 84 |   var filtered = new Packetlist();
 85 | 
 86 |   for (var i = 0; i < this.length; i++) {
 87 |     if (callback(this[i], i, this)) {
 88 |       filtered.push(this[i]);
 89 |     }
 90 |   }
 91 | 
 92 |   return filtered;
 93 | };
 94 | 
 95 | /**
 96 | * Creates a new PacketList with all packets from the given types
 97 | */
 98 | Packetlist.prototype.filterByTag = function () {
 99 |   var args = Array.prototype.slice.call(arguments);
100 |   var filtered = new Packetlist();
101 |   var that = this;
102 | 
103 |   function handle(packetType) {return that[i].tag === packetType;}
104 |   for (var i = 0; i < this.length; i++) {
105 |     if (args.some(handle)) {
106 |       filtered.push(this[i]);
107 |     }
108 |   }
109 |   return filtered;
110 | };
111 | 
112 | /**
113 | * Executes the provided callback once for each element
114 | */
115 | Packetlist.prototype.forEach = function (callback) {
116 |   for (var i = 0; i < this.length; i++) {
117 |     callback(this[i]);
118 |   }
119 | };
120 | 
121 | /**
122 |  * Traverses packet tree and returns first matching packet
123 |  * @param  {module:enums.packet} type The packet type
124 |  * @return {module:packet/packet|null}
125 |  */
126 | Packetlist.prototype.findPacket = function (type) {
127 |   var packetlist = this.filterByTag(type);
128 |   if (packetlist.length) {
129 |     return packetlist[0];
130 |   } else {
131 |     var found = null;
132 |     for (var i = 0; i < this.length; i++) {
133 |       if (this[i].packets.length) {
134 |         found = this[i].packets.findPacket(type);
135 |         if (found) {
136 |           return found;
137 |         }
138 |       }
139 |     }
140 |   }
141 |   return null;
142 | };
143 | 
144 | /**
145 |  * Returns array of found indices by tag
146 |  */
147 | Packetlist.prototype.indexOfTag = function () {
148 |   var args = Array.prototype.slice.call(arguments);
149 |   var tagIndex = [];
150 |   var that = this;
151 | 
152 |   function handle(packetType) {return that[i].tag === packetType;}
153 |   for (var i = 0; i < this.length; i++) {
154 |     if (args.some(handle)) {
155 |       tagIndex.push(i);
156 |     }
157 |   }
158 |   return tagIndex;
159 | };
160 | 
161 | /**
162 |  * Returns slice of packetlist
163 |  */
164 | Packetlist.prototype.slice = function (begin, end) {
165 |   if (!end) {
166 |     end = this.length;
167 |   }
168 |   var part = new Packetlist();
169 |   for (var i = begin; i < end; i++) {
170 |     part.push(this[i]);
171 |   }
172 |   return part;
173 | };
174 | 
175 | /**
176 |  * Concatenates packetlist or array of packets
177 |  */
178 | Packetlist.prototype.concat = function (packetlist) {
179 |   if (packetlist) {
180 |     for (var i = 0; i < packetlist.length; i++) {
181 |       this.push(packetlist[i]);
182 |     }
183 |   }
184 | };
185 | 
186 | /**
187 |  * Allocate a new packetlist from structured packetlist clone
188 |  * See {@link http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#safe-passing-of-structured-data}
189 |  * @param {Object} packetClone packetlist clone
190 |  * @returns {Object} new packetlist object with data from packetlist clone
191 |  */
192 | Packetlist.fromStructuredClone = function(packetlistClone) {
193 |   var packetlist = new Packetlist();
194 |   for (var i = 0; i < packetlistClone.length; i++) {
195 |     packetlist.push(packets.fromStructuredClone(packetlistClone[i]));
196 |     if (packetlist[i].packets.length !== 0) {
197 |       packetlist[i].packets = this.fromStructuredClone(packetlist[i].packets);
198 |     } else {
199 |       packetlist[i].packets = new Packetlist();
200 |     }
201 |   }
202 |   return packetlist;
203 | };
204 | 
--------------------------------------------------------------------------------
/src/packet/public_key.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * Implementation of the Key Material Packet (Tag 5,6,7,14)
 20 |  * 
 21 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.5|RFC4480 5.5}:
 22 |  * A key material packet contains all the information about a public or
 23 |  * private key.  There are four variants of this packet type, and two
 24 |  * major versions.  Consequently, this section is complex.
 25 |  * @requires crypto
 26 |  * @requires enums
 27 |  * @requires type/keyid
 28 |  * @requires type/mpi
 29 |  * @requires util
 30 |  * @module packet/public_key
 31 |  */
 32 | 
 33 | 'use strict';
 34 | 
 35 | import util from '../util.js';
 36 | import type_mpi from '../type/mpi.js';
 37 | import type_keyid from '../type/keyid.js';
 38 | import enums from '../enums.js';
 39 | import crypto from '../crypto';
 40 | 
 41 | /**
 42 |  * @constructor
 43 |  */
 44 | export default function PublicKey() {
 45 |   this.tag = enums.packet.publicKey;
 46 |   this.version = 4;
 47 |   /** Key creation date.
 48 |    * @type {Date} */
 49 |   this.created = new Date();
 50 |   /** A list of multiprecision integers
 51 |    * @type {module:type/mpi} */
 52 |   this.mpi = [];
 53 |   /** Public key algorithm
 54 |    * @type {module:enums.publicKey} */
 55 |   this.algorithm = 'rsa_sign';
 56 |   // time in days (V3 only)
 57 |   this.expirationTimeV3 = 0;
 58 |   /**
 59 |    * Fingerprint in lowercase hex
 60 |    * @type {String}
 61 |    */
 62 |   this.fingerprint = null;
 63 |   /**
 64 |    * Keyid
 65 |    * @type {module:type/keyid}
 66 |    */
 67 |   this.keyid = null;
 68 | }
 69 | 
 70 | /**
 71 |  * Internal Parser for public keys as specified in {@link http://tools.ietf.org/html/rfc4880#section-5.5.2|RFC 4880 section 5.5.2 Public-Key Packet Formats}
 72 |  * called by read_tag<num>
 73 |  * @param {Uint8Array} bytes Input array to read the packet from
 74 |  * @return {Object} This object with attributes set by the parser
 75 |  */
 76 | PublicKey.prototype.read = function (bytes) {
 77 |   var pos = 0;
 78 |   // A one-octet version number (3 or 4).
 79 |   this.version = bytes[pos++];
 80 | 
 81 |   if (this.version === 3 || this.version === 4) {
 82 |     // - A four-octet number denoting the time that the key was created.
 83 |     this.created = util.readDate(bytes.subarray(pos, pos + 4));
 84 |     pos += 4;
 85 | 
 86 |     if (this.version === 3) {
 87 |       // - A two-octet number denoting the time in days that this key is
 88 |       //   valid.  If this number is zero, then it does not expire.
 89 |       this.expirationTimeV3 = util.readNumber(bytes.subarray(pos, pos + 2));
 90 |       pos += 2;
 91 |     }
 92 | 
 93 |     // - A one-octet number denoting the public-key algorithm of this key.
 94 |     this.algorithm = enums.read(enums.publicKey, bytes[pos++]);
 95 | 
 96 |     var mpicount = crypto.getPublicMpiCount(this.algorithm);
 97 |     this.mpi = [];
 98 | 
 99 |     var bmpi = bytes.subarray(pos, bytes.length);
100 |     var p = 0;
101 | 
102 |     for (var i = 0; i < mpicount && p < bmpi.length; i++) {
103 | 
104 |       this.mpi[i] = new type_mpi();
105 | 
106 |       p += this.mpi[i].read(bmpi.subarray(p, bmpi.length));
107 | 
108 |       if (p > bmpi.length) {
109 |         throw new Error('Error reading MPI @:' + p);
110 |       }
111 |     }
112 | 
113 |     return p + 6;
114 |   } else {
115 |     throw new Error('Version ' + this.version + ' of the key packet is unsupported.');
116 |   }
117 | };
118 | 
119 | /**
120 |  * Alias of read()
121 |  * @see module:packet/public_key~PublicKey#read
122 |  */
123 | PublicKey.prototype.readPublicKey = PublicKey.prototype.read;
124 | 
125 | /**
126 |  * Same as write_private_key, but has less information because of
127 |  * public key.
128 |  * @return {Uint8Array} OpenPGP packet body contents,
129 |  */
130 | PublicKey.prototype.write = function () {
131 | 
132 |   var arr = [];
133 |   // Version
134 |   arr.push(new Uint8Array([this.version]));
135 |   arr.push(util.writeDate(this.created));
136 |   if (this.version === 3) {
137 |     arr.push(util.writeNumber(this.expirationTimeV3, 2));
138 |   }
139 |   arr.push(new Uint8Array([enums.write(enums.publicKey, this.algorithm)]));
140 | 
141 |   var mpicount = crypto.getPublicMpiCount(this.algorithm);
142 | 
143 |   for (var i = 0; i < mpicount; i++) {
144 |     arr.push(this.mpi[i].write());
145 |   }
146 | 
147 |   return util.concatUint8Array(arr);
148 | };
149 | 
150 | /**
151 |  * Alias of write()
152 |  * @see module:packet/public_key~PublicKey#write
153 |  */
154 | PublicKey.prototype.writePublicKey = PublicKey.prototype.write;
155 | 
156 | /**
157 |  * Write an old version packet - it's used by some of the internal routines.
158 |  */
159 | PublicKey.prototype.writeOld = function () {
160 |   var bytes = this.writePublicKey();
161 | 
162 |   return util.concatUint8Array([new Uint8Array([0x99]), util.writeNumber(bytes.length, 2), bytes]);
163 | };
164 | 
165 | /**
166 |  * Calculates the key id of the key
167 |  * @return {String} A 8 byte key id
168 |  */
169 | PublicKey.prototype.getKeyId = function () {
170 |   if (this.keyid) {
171 |     return this.keyid;
172 |   }
173 |   this.keyid = new type_keyid();
174 |   if (this.version === 4) {
175 |     this.keyid.read(util.str2Uint8Array(util.hex2bin(this.getFingerprint()).substr(12, 8)));
176 |   } else if (this.version === 3) {
177 |     var arr = this.mpi[0].write();
178 |     this.keyid.read(arr.subarray(arr.length - 8, arr.length));
179 |   }
180 |   return this.keyid;
181 | };
182 | 
183 | /**
184 |  * Calculates the fingerprint of the key
185 |  * @return {String} A string containing the fingerprint in lowercase hex
186 |  */
187 | PublicKey.prototype.getFingerprint = function () {
188 |   if (this.fingerprint) {
189 |     return this.fingerprint;
190 |   }
191 |   var toHash = '';
192 |   if (this.version === 4) {
193 |     toHash = this.writeOld();
194 |     this.fingerprint = util.Uint8Array2str(crypto.hash.sha1(toHash));
195 |   } else if (this.version === 3) {
196 |     var mpicount = crypto.getPublicMpiCount(this.algorithm);
197 |     for (var i = 0; i < mpicount; i++) {
198 |       toHash += this.mpi[i].toBytes();
199 |     }
200 |     this.fingerprint = util.Uint8Array2str(crypto.hash.md5(util.str2Uint8Array(toHash)));
201 |   }
202 |   this.fingerprint = util.hexstrdump(this.fingerprint);
203 |   return this.fingerprint;
204 | };
205 | 
206 | /**
207 |  * Returns bit size of key
208 |  * @return {int} Number of bits
209 |  */
210 | PublicKey.prototype.getBitSize = function () {
211 |   return this.mpi[0].byteLength() * 8;
212 | };
213 | 
214 | /**
215 |  * Fix custom types after cloning
216 |  */
217 | PublicKey.prototype.postCloneTypeFix = function() {
218 |   for (var i = 0; i < this.mpi.length; i++) {
219 |     this.mpi[i] = type_mpi.fromClone(this.mpi[i]);
220 |   }
221 |   if (this.keyid) {
222 |     this.keyid = type_keyid.fromClone(this.keyid);
223 |   }
224 | };
225 | 
--------------------------------------------------------------------------------
/src/packet/public_key_encrypted_session_key.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * Public-Key Encrypted Session Key Packets (Tag 1)
 20 |  * 
 21 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: A Public-Key Encrypted Session Key packet holds the session key
 22 |  * used to encrypt a message. Zero or more Public-Key Encrypted Session Key
 23 |  * packets and/or Symmetric-Key Encrypted Session Key packets may precede a
 24 |  * Symmetrically Encrypted Data Packet, which holds an encrypted message. The
 25 |  * message is encrypted with the session key, and the session key is itself
 26 |  * encrypted and stored in the Encrypted Session Key packet(s). The
 27 |  * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted
 28 |  * Session Key packet for each OpenPGP key to which the message is encrypted.
 29 |  * The recipient of the message finds a session key that is encrypted to their
 30 |  * public key, decrypts the session key, and then uses the session key to
 31 |  * decrypt the message.
 32 |  * @requires crypto
 33 |  * @requires enums
 34 |  * @requires type/keyid
 35 |  * @requires type/mpi
 36 |  * @requires util
 37 |  * @module packet/public_key_encrypted_session_key
 38 |  */
 39 | 
 40 | 'use strict';
 41 | 
 42 | import type_keyid from '../type/keyid.js';
 43 | import util from '../util.js';
 44 | import type_mpi from '../type/mpi.js';
 45 | import enums from '../enums.js';
 46 | import crypto from '../crypto';
 47 | 
 48 | /**
 49 |  * @constructor
 50 |  */
 51 | export default function PublicKeyEncryptedSessionKey() {
 52 |   this.tag = enums.packet.publicKeyEncryptedSessionKey;
 53 |   this.version = 3;
 54 | 
 55 |   this.publicKeyId = new type_keyid();
 56 |   this.publicKeyAlgorithm = 'rsa_encrypt';
 57 | 
 58 |   this.sessionKey = null;
 59 |   this.sessionKeyAlgorithm = 'aes256';
 60 | 
 61 |   /** @type {Array} */
 62 |   this.encrypted = [];
 63 | }
 64 | 
 65 | /**
 66 |  * Parsing function for a publickey encrypted session key packet (tag 1).
 67 |  *
 68 |  * @param {Uint8Array} input Payload of a tag 1 packet
 69 |  * @param {Integer} position Position to start reading from the input string
 70 |  * @param {Integer} len Length of the packet or the remaining length of
 71 |  *            input at position
 72 |  * @return {module:packet/public_key_encrypted_session_key} Object representation
 73 |  */
 74 | PublicKeyEncryptedSessionKey.prototype.read = function (bytes) {
 75 | 
 76 |   this.version = bytes[0];
 77 |   this.publicKeyId.read(bytes.subarray(1,bytes.length));
 78 |   this.publicKeyAlgorithm = enums.read(enums.publicKey, bytes[9]);
 79 | 
 80 |   var i = 10;
 81 | 
 82 |   var integerCount = (function(algo) {
 83 |     switch (algo) {
 84 |       case 'rsa_encrypt':
 85 |       case 'rsa_encrypt_sign':
 86 |         return 1;
 87 | 
 88 |       case 'elgamal':
 89 |         return 2;
 90 | 
 91 |       default:
 92 |         throw new Error("Invalid algorithm.");
 93 |     }
 94 |   })(this.publicKeyAlgorithm);
 95 | 
 96 |   this.encrypted = [];
 97 | 
 98 |   for (var j = 0; j < integerCount; j++) {
 99 |     var mpi = new type_mpi();
100 |     i += mpi.read(bytes.subarray(i, bytes.length));
101 |     this.encrypted.push(mpi);
102 |   }
103 | };
104 | 
105 | /**
106 |  * Create a string representation of a tag 1 packet
107 |  *
108 |  * @return {Uint8Array} The Uint8Array representation
109 |  */
110 | PublicKeyEncryptedSessionKey.prototype.write = function () {
111 | 
112 |   var arr = [new Uint8Array([this.version]), this.publicKeyId.write(), new Uint8Array([enums.write(enums.publicKey, this.publicKeyAlgorithm)])];
113 | 
114 |   for (var i = 0; i < this.encrypted.length; i++) {
115 |     arr.push(this.encrypted[i].write());
116 |   }
117 | 
118 |   return util.concatUint8Array(arr);
119 | };
120 | 
121 | PublicKeyEncryptedSessionKey.prototype.encrypt = function (key) {
122 |   var data = String.fromCharCode(
123 |     enums.write(enums.symmetric, this.sessionKeyAlgorithm));
124 | 
125 |   data += util.Uint8Array2str(this.sessionKey);
126 |   var checksum = util.calc_checksum(this.sessionKey);
127 |   data += util.Uint8Array2str(util.writeNumber(checksum, 2));
128 | 
129 |   var mpi = new type_mpi();
130 |   mpi.fromBytes(crypto.pkcs1.eme.encode(
131 |     data,
132 |     key.mpi[0].byteLength()));
133 | 
134 |   this.encrypted = crypto.publicKeyEncrypt(
135 |     this.publicKeyAlgorithm,
136 |     key.mpi,
137 |     mpi);
138 | };
139 | 
140 | /**
141 |  * Decrypts the session key (only for public key encrypted session key
142 |  * packets (tag 1)
143 |  *
144 |  * @param {module:packet/secret_key} key
145 |  *            Private key with secMPIs unlocked
146 |  * @return {String} The unencrypted session key
147 |  */
148 | PublicKeyEncryptedSessionKey.prototype.decrypt = function (key) {
149 |   var result = crypto.publicKeyDecrypt(
150 |     this.publicKeyAlgorithm,
151 |     key.mpi,
152 |     this.encrypted).toBytes();
153 | 
154 |   var checksum = util.readNumber(util.str2Uint8Array(result.substr(result.length - 2)));
155 |   var decoded = crypto.pkcs1.eme.decode(result);
156 | 
157 |   key = util.str2Uint8Array(decoded.substring(1, decoded.length - 2));
158 | 
159 |   if (checksum !== util.calc_checksum(key)) {
160 |     throw new Error('Checksum mismatch');
161 |   } else {
162 |     this.sessionKey = key;
163 |     this.sessionKeyAlgorithm =
164 |       enums.read(enums.symmetric, decoded.charCodeAt(0));
165 |   }
166 | };
167 | 
168 | /**
169 |  * Fix custom types after cloning
170 |  */
171 | PublicKeyEncryptedSessionKey.prototype.postCloneTypeFix = function() {
172 |   this.publicKeyId = type_keyid.fromClone(this.publicKeyId);
173 |   for (var i = 0; i < this.encrypted.length; i++) {
174 |     this.encrypted[i] = type_mpi.fromClone(this.encrypted[i]);
175 |   }
176 | };
177 | 
--------------------------------------------------------------------------------
/src/packet/public_subkey.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /**
19 |  * @requires packet/public_key
20 |  * @requires enums
21 |  * @module packet/public_subkey
22 |  */
23 | 
24 | 'use strict';
25 | 
26 | import publicKey from './public_key.js';
27 | import enums from '../enums.js';
28 | 
29 | /**
30 |  * @constructor
31 |  * @extends module:packet/public_key
32 |  */
33 | export default function PublicSubkey() {
34 |   publicKey.call(this);
35 |   this.tag = enums.packet.publicSubkey;
36 | }
37 | 
38 | PublicSubkey.prototype = new publicKey();
39 | PublicSubkey.prototype.constructor = PublicSubkey;
40 | 
--------------------------------------------------------------------------------
/src/packet/secret_subkey.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /**
19 |  * @requires packet/secret_key
20 |  * @requires enums
21 |  * @module packet/secret_subkey
22 |  */
23 | 
24 | 'use strict';
25 | 
26 | import secretKey from './secret_key.js';
27 | import enums from '../enums.js';
28 | 
29 | /**
30 |  * @constructor
31 |  * @extends module:packet/secret_key
32 |  */
33 | export default function SecretSubkey() {
34 |   secretKey.call(this);
35 |   this.tag = enums.packet.secretSubkey;
36 | }
37 | 
38 | SecretSubkey.prototype = new secretKey();
39 | SecretSubkey.prototype.constructor = SecretSubkey;
40 | 
--------------------------------------------------------------------------------
/src/packet/sym_encrypted_integrity_protected.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * Implementation of the Sym. Encrypted Integrity Protected Data
 20 |  * Packet (Tag 18)
 21 |  * 
 22 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.13|RFC4880 5.13}:
 23 |  * The Symmetrically Encrypted Integrity Protected Data packet is
 24 |  * a variant of the Symmetrically Encrypted Data packet. It is a new feature
 25 |  * created for OpenPGP that addresses the problem of detecting a modification to
 26 |  * encrypted data. It is used in combination with a Modification Detection Code
 27 |  * packet.
 28 |  * @requires crypto
 29 |  * @requires util
 30 |  * @requires enums
 31 |  * @requires config
 32 |  * @module packet/sym_encrypted_integrity_protected
 33 |  */
 34 | 
 35 | 'use strict';
 36 | 
 37 | import util from '../util.js';
 38 | import crypto from '../crypto';
 39 | import enums from '../enums.js';
 40 | import asmCrypto from 'asmcrypto-lite';
 41 | const nodeCrypto = util.getNodeCrypto();
 42 | const Buffer = util.getNodeBuffer();
 43 | 
 44 | /**
 45 |  * @constructor
 46 |  */
 47 | export default function SymEncryptedIntegrityProtected() {
 48 |   this.tag = enums.packet.symEncryptedIntegrityProtected;
 49 |   /** The encrypted payload. */
 50 |   this.encrypted = null; // string
 51 |   /**
 52 |    * If after decrypting the packet this is set to true,
 53 |    * a modification has been detected and thus the contents
 54 |    * should be discarded.
 55 |    * @type {Boolean}
 56 |    */
 57 |   this.modification = false;
 58 |   this.packets = null;
 59 | }
 60 | 
 61 | SymEncryptedIntegrityProtected.prototype.read = function (bytes) {
 62 |   // - A one-octet version number. The only currently defined value is 1.
 63 |   var version = bytes[0];
 64 | 
 65 |   if (version !== 1) {
 66 |     throw new Error('Invalid packet version.');
 67 |   }
 68 | 
 69 |   // - Encrypted data, the output of the selected symmetric-key cipher
 70 |   //   operating in Cipher Feedback mode with shift amount equal to the
 71 |   //   block size of the cipher (CFB-n where n is the block size).
 72 |   this.encrypted = bytes.subarray(1, bytes.length);
 73 | };
 74 | 
 75 | SymEncryptedIntegrityProtected.prototype.write = function () {
 76 |   // 1 = Version
 77 |   return util.concatUint8Array([new Uint8Array([1]), this.encrypted]);
 78 | };
 79 | 
 80 | SymEncryptedIntegrityProtected.prototype.encrypt = function (sessionKeyAlgorithm, key) {
 81 |   var bytes = this.packets.write();
 82 | 
 83 |   var prefixrandom = crypto.getPrefixRandom(sessionKeyAlgorithm);
 84 |   var repeat = new Uint8Array([prefixrandom[prefixrandom.length - 2], prefixrandom[prefixrandom.length - 1]]);
 85 |   var prefix = util.concatUint8Array([prefixrandom, repeat]);
 86 | 
 87 |   // Modification detection code packet.
 88 |   var mdc = new Uint8Array([0xD3, 0x14]);
 89 | 
 90 |   // This could probably be cleaned up to use less memory
 91 |   var tohash = util.concatUint8Array([bytes, mdc]);
 92 |   var hash = crypto.hash.sha1(util.concatUint8Array([prefix, tohash]));
 93 |   tohash = util.concatUint8Array([tohash, hash]);
 94 | 
 95 |   if(sessionKeyAlgorithm.substr(0,3) === 'aes') { // AES optimizations. Native code for node, asmCrypto for browser.
 96 |     var blockSize = crypto.cipher[sessionKeyAlgorithm].blockSize;
 97 | 
 98 |     if(nodeCrypto) { // Node crypto library. Only loaded if config.useNative === true
 99 |       var cipherObj = new nodeCrypto.createCipheriv('aes-' + sessionKeyAlgorithm.substr(3,3) + '-cfb',
100 |         new Buffer(key), new Buffer(new Uint8Array(blockSize)));
101 |       this.encrypted = new Uint8Array(cipherObj.update(new Buffer(util.concatUint8Array([prefix, tohash]))));
102 | 
103 |     } else { // asm.js fallback
104 |       this.encrypted = asmCrypto.AES_CFB.encrypt(util.concatUint8Array([prefix, tohash]), key);
105 |     }
106 | 
107 |   } else {
108 |     this.encrypted = crypto.cfb.encrypt(prefixrandom, sessionKeyAlgorithm, tohash, key, false)
109 |       .subarray(0, prefix.length + tohash.length);
110 |   }
111 | };
112 | 
113 | /**
114 |  * Decrypts the encrypted data contained in this object read_packet must
115 |  * have been called before
116 |  *
117 |  * @param {module:enums.symmetric} sessionKeyAlgorithm
118 |  *            The selected symmetric encryption algorithm to be used
119 |  * @param {Uint8Array} key The key of cipher blocksize length to be used
120 |  * @return {String} The decrypted data of this packet
121 |  */
122 | SymEncryptedIntegrityProtected.prototype.decrypt = function (sessionKeyAlgorithm, key) {
123 |   var decrypted;
124 | 
125 |   if(sessionKeyAlgorithm.substr(0,3) === 'aes') {  // AES optimizations. Native code for node, asmCrypto for browser.
126 |     var blockSize = crypto.cipher[sessionKeyAlgorithm].blockSize;
127 | 
128 |     if(nodeCrypto) { // Node crypto library. Only loaded if config.useNative === true
129 |       var decipherObj = new nodeCrypto.createDecipheriv('aes-' + sessionKeyAlgorithm.substr(3,3) + '-cfb',
130 |         new Buffer(key), new Buffer(new Uint8Array(blockSize)));
131 |       decrypted = new Uint8Array(decipherObj.update(new Buffer(this.encrypted)));
132 | 
133 |     } else { // asm.js fallback
134 |       decrypted = asmCrypto.AES_CFB.decrypt(this.encrypted, key);
135 |     }
136 | 
137 |     // Remove random prefix
138 |     decrypted = decrypted.subarray(blockSize + 2, decrypted.length);
139 | 
140 |   } else {
141 |     decrypted = crypto.cfb.decrypt(sessionKeyAlgorithm, key, this.encrypted, false);
142 |   }
143 | 
144 |   // there must be a modification detection code packet as the
145 |   // last packet and everything gets hashed except the hash itself
146 |   this.hash = util.Uint8Array2str(crypto.hash.sha1(util.concatUint8Array([crypto.cfb.mdc(sessionKeyAlgorithm, key, this.encrypted),
147 |     decrypted.subarray(0, decrypted.length - 20)])));
148 | 
149 |   var mdc = util.Uint8Array2str(decrypted.subarray(decrypted.length - 20, decrypted.length));
150 | 
151 |   if (this.hash !== mdc) {
152 |     throw new Error('Modification detected.');
153 |   } else {
154 |     this.packets.read(decrypted.subarray(0, decrypted.length - 22));
155 |   }
156 | };
157 | 
--------------------------------------------------------------------------------
/src/packet/sym_encrypted_session_key.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * Public-Key Encrypted Session Key Packets (Tag 1)
 20 |  * 
 21 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.1|RFC4880 5.1}: A Public-Key Encrypted Session Key packet holds the session key
 22 |  * used to encrypt a message. Zero or more Public-Key Encrypted Session Key
 23 |  * packets and/or Symmetric-Key Encrypted Session Key packets may precede a
 24 |  * Symmetrically Encrypted Data Packet, which holds an encrypted message. The
 25 |  * message is encrypted with the session key, and the session key is itself
 26 |  * encrypted and stored in the Encrypted Session Key packet(s). The
 27 |  * Symmetrically Encrypted Data Packet is preceded by one Public-Key Encrypted
 28 |  * Session Key packet for each OpenPGP key to which the message is encrypted.
 29 |  * The recipient of the message finds a session key that is encrypted to their
 30 |  * public key, decrypts the session key, and then uses the session key to
 31 |  * decrypt the message.
 32 |  * @requires util
 33 |  * @requires crypto
 34 |  * @requires enums
 35 |  * @requires type/s2k
 36 |  * @module packet/sym_encrypted_session_key
 37 |  */
 38 | 
 39 | 'use strict';
 40 | 
 41 | import util from '../util.js';
 42 | import type_s2k from '../type/s2k.js';
 43 | import enums from '../enums.js';
 44 | import crypto from '../crypto';
 45 | 
 46 | /**
 47 |  * @constructor
 48 |  */
 49 | export default function SymEncryptedSessionKey() {
 50 |   this.tag = enums.packet.symEncryptedSessionKey;
 51 |   this.version = 4;
 52 |   this.sessionKey = null;
 53 |   this.sessionKeyEncryptionAlgorithm = null;
 54 |   this.sessionKeyAlgorithm = 'aes256';
 55 |   this.encrypted = null;
 56 |   this.s2k = new type_s2k();
 57 | }
 58 | 
 59 | /**
 60 |  * Parsing function for a symmetric encrypted session key packet (tag 3).
 61 |  *
 62 |  * @param {Uint8Array} input Payload of a tag 1 packet
 63 |  * @param {Integer} position Position to start reading from the input string
 64 |  * @param {Integer} len
 65 |  *            Length of the packet or the remaining length of
 66 |  *            input at position
 67 |  * @return {module:packet/sym_encrypted_session_key} Object representation
 68 |  */
 69 | SymEncryptedSessionKey.prototype.read = function(bytes) {
 70 |   // A one-octet version number. The only currently defined version is 4.
 71 |   this.version = bytes[0];
 72 | 
 73 |   // A one-octet number describing the symmetric algorithm used.
 74 |   var algo = enums.read(enums.symmetric, bytes[1]);
 75 | 
 76 |   // A string-to-key (S2K) specifier, length as defined above.
 77 |   var s2klength = this.s2k.read(bytes.subarray(2, bytes.length));
 78 | 
 79 |   // Optionally, the encrypted session key itself, which is decrypted
 80 |   // with the string-to-key object.
 81 |   var done = s2klength + 2;
 82 | 
 83 |   if (done < bytes.length) {
 84 |     this.encrypted = bytes.subarray(done, bytes.length);
 85 |     this.sessionKeyEncryptionAlgorithm = algo;
 86 |   } else {
 87 |     this.sessionKeyAlgorithm = algo;
 88 |   }
 89 | };
 90 | 
 91 | SymEncryptedSessionKey.prototype.write = function() {
 92 |   var algo = this.encrypted === null ?
 93 |     this.sessionKeyAlgorithm :
 94 |     this.sessionKeyEncryptionAlgorithm;
 95 | 
 96 |   var bytes = util.concatUint8Array([new Uint8Array([this.version, enums.write(enums.symmetric, algo)]), this.s2k.write()]);
 97 | 
 98 |   if (this.encrypted !== null) {
 99 |     bytes = util.concatUint8Array([bytes, this.encrypted]);
100 |   }
101 |   return bytes;
102 | };
103 | 
104 | /**
105 |  * Decrypts the session key (only for public key encrypted session key
106 |  * packets (tag 1)
107 |  *
108 |  * @return {Uint8Array} The unencrypted session key
109 |  */
110 | SymEncryptedSessionKey.prototype.decrypt = function(passphrase) {
111 |   var algo = this.sessionKeyEncryptionAlgorithm !== null ?
112 |     this.sessionKeyEncryptionAlgorithm :
113 |     this.sessionKeyAlgorithm;
114 | 
115 |   var length = crypto.cipher[algo].keySize;
116 |   var key = this.s2k.produce_key(passphrase, length);
117 | 
118 |   if (this.encrypted === null) {
119 |     this.sessionKey = key;
120 | 
121 |   } else {
122 |     var decrypted = crypto.cfb.normalDecrypt(
123 |       algo, key, this.encrypted, null);
124 | 
125 |     this.sessionKeyAlgorithm = enums.read(enums.symmetric,
126 |       decrypted[0]);
127 | 
128 |     this.sessionKey = decrypted.subarray(1,decrypted.length);
129 |   }
130 | };
131 | 
132 | SymEncryptedSessionKey.prototype.encrypt = function(passphrase) {
133 |   var algo = this.sessionKeyEncryptionAlgorithm !== null ?
134 |     this.sessionKeyEncryptionAlgorithm :
135 |     this.sessionKeyAlgorithm;
136 | 
137 |   this.sessionKeyEncryptionAlgorithm = algo;
138 | 
139 |   var length = crypto.cipher[algo].keySize;
140 |   var key = this.s2k.produce_key(passphrase, length);
141 | 
142 |   var algo_enum = new Uint8Array([
143 |     enums.write(enums.symmetric, this.sessionKeyAlgorithm)]);
144 | 
145 |   var private_key;
146 |   if(this.sessionKey === null) {
147 |     this.sessionKey = crypto.getRandomBytes(crypto.cipher[this.sessionKeyAlgorithm].keySize);
148 |   }
149 |   private_key = util.concatUint8Array([algo_enum, this.sessionKey]);
150 | 
151 |   this.encrypted = crypto.cfb.normalEncrypt(
152 |     algo, key, private_key, null);
153 | };
154 | 
155 | /**
156 |  * Fix custom types after cloning
157 |  */
158 | SymEncryptedSessionKey.prototype.postCloneTypeFix = function() {
159 |   this.s2k = type_s2k.fromClone(this.s2k);
160 | };
161 | 
--------------------------------------------------------------------------------
/src/packet/symmetrically_encrypted.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /**
19 |  * Implementation of the Symmetrically Encrypted Data Packet (Tag 9)
20 |  * 
21 |  * {@link http://tools.ietf.org/html/rfc4880#section-5.7|RFC4880 5.7}: The Symmetrically Encrypted Data packet contains data encrypted
22 |  * with a symmetric-key algorithm. When it has been decrypted, it contains other
23 |  * packets (usually a literal data packet or compressed data packet, but in
24 |  * theory other Symmetrically Encrypted Data packets or sequences of packets
25 |  * that form whole OpenPGP messages).
26 |  * @requires crypto
27 |  * @requires enums
28 |  * @module packet/symmetrically_encrypted
29 |  */
30 | 
31 | 'use strict';
32 | 
33 | import crypto from '../crypto';
34 | import enums from '../enums.js';
35 | import config from '../config';
36 | 
37 | /**
38 |  * @constructor
39 |  */
40 | export default function SymmetricallyEncrypted() {
41 |   this.tag = enums.packet.symmetricallyEncrypted;
42 |   this.encrypted = null;
43 |   /** Decrypted packets contained within.
44 |    * @type {module:packet/packetlist} */
45 |   this.packets =  null;
46 |   this.ignore_mdc_error = config.ignore_mdc_error;
47 | }
48 | 
49 | SymmetricallyEncrypted.prototype.read = function (bytes) {
50 |   this.encrypted = bytes;
51 | };
52 | 
53 | SymmetricallyEncrypted.prototype.write = function () {
54 |   return this.encrypted;
55 | };
56 | 
57 | /**
58 |  * Symmetrically decrypt the packet data
59 |  *
60 |  * @param {module:enums.symmetric} sessionKeyAlgorithm
61 |  *             Symmetric key algorithm to use // See {@link http://tools.ietf.org/html/rfc4880#section-9.2|RFC4880 9.2}
62 |  * @param {String} key
63 |  *             Key as string with the corresponding length to the
64 |  *            algorithm
65 |  */
66 | SymmetricallyEncrypted.prototype.decrypt = function (sessionKeyAlgorithm, key) {
67 |   var decrypted = crypto.cfb.decrypt(sessionKeyAlgorithm, key, this.encrypted, true);
68 | 
69 |   // for modern cipher (blocklength != 64 bit, except for Twofish) MDC is required
70 |   if (!this.ignore_mdc_error &&
71 |       (sessionKeyAlgorithm === 'aes128' ||
72 |        sessionKeyAlgorithm === 'aes192' ||
73 |        sessionKeyAlgorithm === 'aes256')) {
74 |     throw new Error('Decryption failed due to missing MDC in combination with modern cipher.');
75 |   }
76 | 
77 |   this.packets.read(decrypted);
78 | };
79 | 
80 | SymmetricallyEncrypted.prototype.encrypt = function (algo, key) {
81 |   var data = this.packets.write();
82 | 
83 |   this.encrypted = crypto.cfb.encrypt(
84 |     crypto.getPrefixRandom(algo), algo, data, key, true);
85 | };
86 | 
--------------------------------------------------------------------------------
/src/packet/trust.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @requires enums
 3 |  * @module packet/trust
 4 |  */
 5 | 
 6 | 'use strict';
 7 | 
 8 | import enums from '../enums.js';
 9 | 
10 | /**
11 |  * @constructor
12 |  */
13 | export default function Trust() {
14 |   this.tag = enums.packet.trust;
15 | }
16 | 
17 | /**
18 |  * Parsing function for a trust packet (tag 12).
19 |  * Currently empty as we ignore trust packets
20 |  * @param {String} byptes payload of a tag 12 packet
21 |  */
22 | Trust.prototype.read = function () {};
23 | 
--------------------------------------------------------------------------------
/src/packet/user_attribute.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /**
19 |  * Implementation of the User Attribute Packet (Tag 17)
20 |  * 
21 |  * The User Attribute packet is a variation of the User ID packet.  It
22 |  * is capable of storing more types of data than the User ID packet,
23 |  * which is limited to text.  Like the User ID packet, a User Attribute
24 |  * packet may be certified by the key owner ("self-signed") or any other
25 |  * key owner who cares to certify it.  Except as noted, a User Attribute
26 |  * packet may be used anywhere that a User ID packet may be used.
27 |  * 
28 |  * While User Attribute packets are not a required part of the OpenPGP
29 |  * standard, implementations SHOULD provide at least enough
30 |  * compatibility to properly handle a certification signature on the
31 |  * User Attribute packet.  A simple way to do this is by treating the
32 |  * User Attribute packet as a User ID packet with opaque contents, but
33 |  * an implementation may use any method desired.
34 |  * module packet/user_attribute
35 |  * @requires enums
36 |  * @module packet/user_attribute
37 |  */
38 | 
39 | 'use strict';
40 | 
41 | import util from '../util.js';
42 | import packet from './packet.js';
43 | import enums from '../enums.js';
44 | 
45 | /**
46 |  * @constructor
47 |  */
48 | export default function UserAttribute() {
49 |   this.tag = enums.packet.userAttribute;
50 |   this.attributes = [];
51 | }
52 | 
53 | /**
54 |  * parsing function for a user attribute packet (tag 17).
55 |  * @param {Uint8Array} input payload of a tag 17 packet
56 |  */
57 | UserAttribute.prototype.read = function(bytes) {
58 |   var i = 0;
59 |   while (i < bytes.length) {
60 |     var len = packet.readSimpleLength(bytes.subarray(i, bytes.length));
61 |     i += len.offset;
62 | 
63 |     this.attributes.push(util.Uint8Array2str(bytes.subarray(i, i + len.len)));
64 |     i += len.len;
65 |   }
66 | };
67 | 
68 | /**
69 |  * Creates a binary representation of the user attribute packet
70 |  * @return {Uint8Array} string representation
71 |  */
72 | UserAttribute.prototype.write = function() {
73 |   var arr = [];
74 |   for (var i = 0; i < this.attributes.length; i++) {
75 |     arr.push(packet.writeSimpleLength(this.attributes[i].length));
76 |     arr.push(util.str2Uint8Array(this.attributes[i]));
77 |   }
78 |   return util.concatUint8Array(arr);
79 | };
80 | 
81 | /**
82 |  * Compare for equality
83 |  * @param  {module:user_attribute~UserAttribute} usrAttr
84 |  * @return {Boolean}         true if equal
85 |  */
86 | UserAttribute.prototype.equals = function(usrAttr) {
87 |   if (!usrAttr || !(usrAttr instanceof UserAttribute)) {
88 |     return false;
89 |   }
90 |   return this.attributes.every(function(attr, index) {
91 |     return attr === usrAttr.attributes[index];
92 |   });
93 | };
94 | 
--------------------------------------------------------------------------------
/src/packet/userid.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /**
19 |  * Implementation of the User ID Packet (Tag 13)
20 |  * 
21 |  * A User ID packet consists of UTF-8 text that is intended to represent
22 |  * the name and email address of the key holder.  By convention, it
23 |  * includes an RFC 2822 [RFC2822] mail name-addr, but there are no
24 |  * restrictions on its content.  The packet length in the header
25 |  * specifies the length of the User ID.
26 |  * @requires util
27 |  * @requires enums
28 |  * @module packet/userid
29 |  */
30 | 
31 | 'use strict';
32 | 
33 | import util from '../util.js';
34 | import enums from '../enums.js';
35 | 
36 | /**
37 |  * @constructor
38 |  */
39 | export default function Userid() {
40 |   this.tag = enums.packet.userid;
41 |   /** A string containing the user id. Usually in the form
42 |    * John Doe 
43 |    * @type {String}
44 |    */
45 |   this.userid = '';
46 | }
47 | 
48 | /**
49 |  * Parsing function for a user id packet (tag 13).
50 |  * @param {Uint8Array} input payload of a tag 13 packet
51 |  */
52 | Userid.prototype.read = function (bytes) {
53 |   this.userid = util.decode_utf8(util.Uint8Array2str(bytes));
54 | };
55 | 
56 | /**
57 |  * Creates a binary representation of the user id packet
58 |  * @return {Uint8Array} binary representation
59 |  */
60 | Userid.prototype.write = function () {
61 |   return util.str2Uint8Array(util.encode_utf8(this.userid));
62 | };
63 | 
--------------------------------------------------------------------------------
/src/type/keyid.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /**
19 |  * Implementation of type key id ({@link http://tools.ietf.org/html/rfc4880#section-3.3|RFC4880 3.3})
20 |  * 
21 |  * A Key ID is an eight-octet scalar that identifies a key.
22 |  * Implementations SHOULD NOT assume that Key IDs are unique.  The
23 |  * section "Enhanced Key Formats" below describes how Key IDs are
24 |  * formed.
25 |  * @requires util
26 |  * @module type/keyid
27 |  */
28 | 
29 | 'use strict';
30 | 
31 | import util from '../util.js';
32 | 
33 | /**
34 |  * @constructor
35 |  */
36 | export default function Keyid() {
37 |   this.bytes = '';
38 | }
39 | 
40 | /**
41 |  * Parsing method for a key id
42 |  * @param {String} input Input to read the key id from
43 |  */
44 | Keyid.prototype.read = function(bytes) {
45 |   this.bytes = util.Uint8Array2str(bytes.subarray(0, 8));
46 | };
47 | 
48 | Keyid.prototype.write = function() {
49 |   return util.str2Uint8Array(this.bytes);
50 | };
51 | 
52 | Keyid.prototype.toHex = function() {
53 |   return util.hexstrdump(this.bytes);
54 | };
55 | 
56 | Keyid.prototype.equals = function(keyid) {
57 |   return this.bytes === keyid.bytes;
58 | };
59 | 
60 | Keyid.prototype.isNull = function() {
61 |   return this.bytes === '';
62 | };
63 | 
64 | Keyid.mapToHex = function (keyId) {
65 |   return keyId.toHex();
66 | };
67 | 
68 | Keyid.fromClone = function (clone) {
69 |   var keyid = new Keyid();
70 |   keyid.bytes = clone.bytes;
71 |   return keyid;
72 | };
73 | 
74 | Keyid.fromId = function (hex) {
75 |   var keyid = new Keyid();
76 |   keyid.read(util.hex2bin(hex));
77 |   return keyid;
78 | };
79 | 
--------------------------------------------------------------------------------
/src/type/mpi.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | // Hint: We hold our MPIs as an array of octets in big endian format preceeding a two
 19 | // octet scalar: MPI: [a,b,c,d,e,f]
 20 | // - MPI size: (a << 8) | b
 21 | // - MPI = c | d << 8 | e << ((MPI.length -2)*8) | f ((MPI.length -2)*8)
 22 | 
 23 | /**
 24 |  * Implementation of type MPI ({@link http://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2})
 25 |  * 
 26 |  * Multiprecision integers (also called MPIs) are unsigned integers used
 27 |  * to hold large integers such as the ones used in cryptographic
 28 |  * calculations.
 29 |  * An MPI consists of two pieces: a two-octet scalar that is the length
 30 |  * of the MPI in bits followed by a string of octets that contain the
 31 |  * actual integer.
 32 |  * @requires crypto/public_key/jsbn
 33 |  * @requires util
 34 |  * @module type/mpi
 35 |  */
 36 | 
 37 | 'use strict';
 38 | 
 39 | import BigInteger from '../crypto/public_key/jsbn.js';
 40 | import util from '../util.js';
 41 | 
 42 | /**
 43 |  * @constructor
 44 |  */
 45 | export default function MPI() {
 46 |   /** An implementation dependent integer */
 47 |   this.data = null;
 48 | }
 49 | 
 50 | /**
 51 |  * Parsing function for a mpi ({@link http://tools.ietf.org/html/rfc4880#section3.2|RFC 4880 3.2}).
 52 |  * @param {String} input Payload of mpi data
 53 |  * @return {Integer} Length of data read
 54 |  */
 55 | MPI.prototype.read = function (bytes) {
 56 | 
 57 |   if(typeof bytes === 'string' || String.prototype.isPrototypeOf(bytes)) {
 58 |     bytes = util.str2Uint8Array(bytes);
 59 |   }
 60 | 
 61 |   var bits = (bytes[0] << 8) | bytes[1];
 62 | 
 63 |   // Additional rules:
 64 |   //
 65 |   //    The size of an MPI is ((MPI.length + 7) / 8) + 2 octets.
 66 |   //
 67 |   //    The length field of an MPI describes the length starting from its
 68 |   //    most significant non-zero bit.  Thus, the MPI [00 02 01] is not
 69 |   //    formed correctly.  It should be [00 01 01].
 70 | 
 71 |   // TODO: Verification of this size method! This size calculation as
 72 |   //      specified above is not applicable in JavaScript
 73 |   var bytelen = Math.ceil(bits / 8);
 74 | 
 75 |   var raw = util.Uint8Array2str(bytes.subarray(2, 2 + bytelen));
 76 |   this.fromBytes(raw);
 77 | 
 78 |   return 2 + bytelen;
 79 | };
 80 | 
 81 | MPI.prototype.fromBytes = function (bytes) {
 82 |   this.data = new BigInteger(util.hexstrdump(bytes), 16);
 83 | };
 84 | 
 85 | MPI.prototype.toBytes = function () {
 86 |   var bytes = util.Uint8Array2str(this.write());
 87 |   return bytes.substr(2);
 88 | };
 89 | 
 90 | MPI.prototype.byteLength = function () {
 91 |   return this.toBytes().length;
 92 | };
 93 | 
 94 | /**
 95 |  * Converts the mpi object to a bytes as specified in {@link http://tools.ietf.org/html/rfc4880#section-3.2|RFC4880 3.2}
 96 |  * @return {Uint8Aray} mpi Byte representation
 97 |  */
 98 | MPI.prototype.write = function () {
 99 |   return util.str2Uint8Array(this.data.toMPI());
100 | };
101 | 
102 | MPI.prototype.toBigInteger = function () {
103 |   return this.data.clone();
104 | };
105 | 
106 | MPI.prototype.fromBigInteger = function (bn) {
107 |   this.data = bn.clone();
108 | };
109 | 
110 | MPI.fromClone = function (clone) {
111 |   clone.data.copyTo = BigInteger.prototype.copyTo;
112 |   var bn = new BigInteger();
113 |   clone.data.copyTo(bn);
114 |   var mpi = new MPI();
115 |   mpi.data = bn;
116 |   return mpi;
117 | };
118 | 
--------------------------------------------------------------------------------
/src/type/s2k.js:
--------------------------------------------------------------------------------
  1 | // GPG4Browsers - An OpenPGP implementation in javascript
  2 | // Copyright (C) 2011 Recurity Labs GmbH
  3 | //
  4 | // This library is free software; you can redistribute it and/or
  5 | // modify it under the terms of the GNU Lesser General Public
  6 | // License as published by the Free Software Foundation; either
  7 | // version 3.0 of the License, or (at your option) any later version.
  8 | //
  9 | // This library is distributed in the hope that it will be useful,
 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12 | // Lesser General Public License for more details.
 13 | //
 14 | // You should have received a copy of the GNU Lesser General Public
 15 | // License along with this library; if not, write to the Free Software
 16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 17 | 
 18 | /**
 19 |  * Implementation of the String-to-key specifier ({@link http://tools.ietf.org/html/rfc4880#section-3.7|RFC4880 3.7})
 20 |  * 
 21 |  * String-to-key (S2K) specifiers are used to convert passphrase strings
 22 |  * into symmetric-key encryption/decryption keys.  They are used in two
 23 |  * places, currently: to encrypt the secret part of private keys in the
 24 |  * private keyring, and to convert passphrases to encryption keys for
 25 |  * symmetrically encrypted messages.
 26 |  * @requires crypto
 27 |  * @requires enums
 28 |  * @requires util
 29 |  * @module type/s2k
 30 |  */
 31 | 
 32 | 'use strict';
 33 | 
 34 | import enums from '../enums.js';
 35 | import util from '../util.js';
 36 | import crypto from '../crypto';
 37 | 
 38 | /**
 39 |  * @constructor
 40 |  */
 41 | export default function S2K() {
 42 |   /** @type {module:enums.hash} */
 43 |   this.algorithm = 'sha256';
 44 |   /** @type {module:enums.s2k} */
 45 |   this.type = 'iterated';
 46 |   this.c = 96;
 47 |   /** Eight bytes of salt in a binary string.
 48 |    * @type {String}
 49 |    */
 50 |   this.salt = crypto.random.getRandomBytes(8);
 51 | }
 52 | 
 53 | S2K.prototype.get_count = function () {
 54 |   // Exponent bias, defined in RFC4880
 55 |   var expbias = 6;
 56 | 
 57 |   return (16 + (this.c & 15)) << ((this.c >> 4) + expbias);
 58 | };
 59 | 
 60 | /**
 61 |  * Parsing function for a string-to-key specifier ({@link http://tools.ietf.org/html/rfc4880#section-3.7|RFC 4880 3.7}).
 62 |  * @param {String} input Payload of string-to-key specifier
 63 |  * @return {Integer} Actual length of the object
 64 |  */
 65 | S2K.prototype.read = function (bytes) {
 66 |   var i = 0;
 67 |   this.type = enums.read(enums.s2k, bytes[i++]);
 68 |   this.algorithm = enums.read(enums.hash, bytes[i++]);
 69 | 
 70 |   switch (this.type) {
 71 |     case 'simple':
 72 |       break;
 73 | 
 74 |     case 'salted':
 75 |       this.salt = bytes.subarray(i, i + 8);
 76 |       i += 8;
 77 |       break;
 78 | 
 79 |     case 'iterated':
 80 |       this.salt = bytes.subarray(i, i + 8);
 81 |       i += 8;
 82 | 
 83 |       // Octet 10: count, a one-octet, coded value
 84 |       this.c = bytes[i++];
 85 |       break;
 86 | 
 87 |     case 'gnu':
 88 |       if (util.Uint8Array2str(bytes.subarray(i, 3)) === "GNU") {
 89 |         i += 3; // GNU
 90 |         var gnuExtType = 1000 + bytes[i++];
 91 |         if (gnuExtType === 1001) {
 92 |           this.type = gnuExtType;
 93 |           // GnuPG extension mode 1001 -- don't write secret key at all
 94 |         } else {
 95 |           throw new Error("Unknown s2k gnu protection mode.");
 96 |         }
 97 |       } else {
 98 |         throw new Error("Unknown s2k type.");
 99 |       }
100 |       break;
101 | 
102 |     default:
103 |       throw new Error("Unknown s2k type.");
104 |   }
105 | 
106 |   return i;
107 | };
108 | 
109 | 
110 | /**
111 |  * Serializes s2k information
112 |  * @return {Uint8Array} binary representation of s2k
113 |  */
114 | S2K.prototype.write = function () {
115 | 
116 |   var arr = [new Uint8Array([enums.write(enums.s2k, this.type), enums.write(enums.hash, this.algorithm)])];
117 | 
118 |   switch (this.type) {
119 |     case 'simple':
120 |       break;
121 |     case 'salted':
122 |       arr.push(this.salt);
123 |       break;
124 |     case 'iterated':
125 |       arr.push(this.salt);
126 |       arr.push(new Uint8Array([this.c]));
127 |       break;
128 |     case 'gnu':
129 |       throw new Error("GNU s2k type not supported.");
130 |     default:
131 |       throw new Error("Unknown s2k type.");
132 |   }
133 | 
134 |   return util.concatUint8Array(arr);
135 | };
136 | 
137 | /**
138 |  * Produces a key using the specified passphrase and the defined
139 |  * hashAlgorithm
140 |  * @param {String} passphrase Passphrase containing user input
141 |  * @return {Uint8Array} Produced key with a length corresponding to
142 |  * hashAlgorithm hash length
143 |  */
144 | S2K.prototype.produce_key = function (passphrase, numBytes) {
145 |   passphrase = util.str2Uint8Array(util.encode_utf8(passphrase));
146 | 
147 |   function round(prefix, s2k) {
148 |     var algorithm = enums.write(enums.hash, s2k.algorithm);
149 | 
150 |     switch (s2k.type) {
151 |       case 'simple':
152 |         return crypto.hash.digest(algorithm, util.concatUint8Array([prefix,passphrase]));
153 | 
154 |       case 'salted':
155 |         return crypto.hash.digest(algorithm,
156 |           util.concatUint8Array([prefix, s2k.salt, passphrase]));
157 | 
158 |       case 'iterated':
159 |         var isp = [],
160 |           count = s2k.get_count(),
161 |           data = util.concatUint8Array([s2k.salt,passphrase]);
162 | 
163 |         while (isp.length * data.length < count) {
164 |           isp.push(data);
165 |         }
166 | 
167 |         isp = util.concatUint8Array(isp);
168 | 
169 |         if (isp.length > count) {
170 |           isp = isp.subarray(0, count);
171 |         }
172 | 
173 |         return crypto.hash.digest(algorithm, util.concatUint8Array([prefix,isp]));
174 | 
175 |       case 'gnu':
176 |         throw new Error("GNU s2k type not supported.");
177 | 
178 |       default:
179 |         throw new Error("Unknown s2k type.");
180 |     }
181 |   }
182 | 
183 |   var arr = [],
184 |     rlength = 0,
185 |     prefix = new Uint8Array(numBytes);
186 | 
187 |   for(var i = 0; i {
 39 |     throw new Error('Unhandled error in openpgp worker: ' + e.message + ' (' + e.filename + ':' + e.lineno + ')');
 40 |   };
 41 |   this.seedRandom(INITIAL_RANDOM_SEED);
 42 |   // FIFO
 43 |   this.tasks = [];
 44 |   if (config) {
 45 |     this.worker.postMessage({ event:'configure', config });
 46 |   }
 47 | }
 48 | 
 49 | /**
 50 |  * Message handling
 51 |  */
 52 | AsyncProxy.prototype.onMessage = function(event) {
 53 |   const msg = event.data;
 54 |   switch (msg.event) {
 55 |     case 'method-return':
 56 |       if (msg.err) {
 57 |         // fail
 58 |         this.tasks.shift().reject(new Error(msg.err));
 59 |       } else {
 60 |         // success
 61 |         this.tasks.shift().resolve(msg.data);
 62 |       }
 63 |       break;
 64 |     case 'request-seed':
 65 |       this.seedRandom(RANDOM_SEED_REQUEST);
 66 |       break;
 67 |     default:
 68 |       throw new Error('Unknown Worker Event.');
 69 |   }
 70 | };
 71 | 
 72 | /**
 73 |  * Send message to worker with random data
 74 |  * @param  {Integer} size Number of bytes to send
 75 |  */
 76 | AsyncProxy.prototype.seedRandom = function(size) {
 77 |   const buf = this.getRandomBuffer(size);
 78 |   this.worker.postMessage({ event:'seed-random', buf }, util.getTransferables.call(util, buf));
 79 | };
 80 | 
 81 | /**
 82 |  * Get Uint8Array with random numbers
 83 |  * @param  {Integer} size Length of buffer
 84 |  * @return {Uint8Array}
 85 |  */
 86 | AsyncProxy.prototype.getRandomBuffer = function(size) {
 87 |   if (!size) {
 88 |     return null;
 89 |   }
 90 |   const buf = new Uint8Array(size);
 91 |   crypto.random.getRandomValues(buf);
 92 |   return buf;
 93 | };
 94 | 
 95 | /**
 96 |  * Terminates the worker
 97 |  */
 98 | AsyncProxy.prototype.terminate = function() {
 99 |   this.worker.terminate();
100 | };
101 | 
102 | /**
103 |  * Generic proxy function that handles all commands from the public api.
104 |  * @param  {String} method    the public api function to be delegated to the worker thread
105 |  * @param  {Object} options   the api function's options
106 |  * @return {Promise}          see the corresponding public api functions for their return types
107 |  */
108 | AsyncProxy.prototype.delegate = function(method, options) {
109 |   return new Promise((resolve, reject) => {
110 |     // clone packets (for web worker structured cloning algorithm)
111 |     this.worker.postMessage({ event:method, options:packet.clone.clonePackets(options) }, util.getTransferables.call(util, options));
112 | 
113 |     // remember to handle parsing cloned packets from worker
114 |     this.tasks.push({ resolve: data => resolve(packet.clone.parseClonedPackets(data, method)), reject });
115 |   });
116 | };
117 | 
--------------------------------------------------------------------------------
/src/worker/worker.js:
--------------------------------------------------------------------------------
 1 | // GPG4Browsers - An OpenPGP implementation in javascript
 2 | // Copyright (C) 2011 Recurity Labs GmbH
 3 | //
 4 | // This library is free software; you can redistribute it and/or
 5 | // modify it under the terms of the GNU Lesser General Public
 6 | // License as published by the Free Software Foundation; either
 7 | // version 3.0 of the License, or (at your option) any later version.
 8 | //
 9 | // This library is distributed in the hope that it will be useful,
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 | // Lesser General Public License for more details.
13 | //
14 | // You should have received a copy of the GNU Lesser General Public
15 | // License along with this library; if not, write to the Free Software
16 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17 | 
18 | /* globals self: true */
19 | 
20 | self.window = {}; // to make UMD bundles work
21 | 
22 | importScripts('openpgp.js');
23 | var openpgp = window.openpgp;
24 | 
25 | var MIN_SIZE_RANDOM_BUFFER = 40000;
26 | var MAX_SIZE_RANDOM_BUFFER = 60000;
27 | 
28 | openpgp.crypto.random.randomBuffer.init(MAX_SIZE_RANDOM_BUFFER);
29 | 
30 | self.onmessage = function (event) {
31 |   var msg = event.data || {},
32 |       options = msg.options || {};
33 | 
34 |   switch (msg.event) {
35 |     case 'configure':
36 |       for (var i in msg.config) {
37 |         openpgp.config[i] = msg.config[i];
38 |       }
39 |       break;
40 | 
41 |     case 'seed-random':
42 |       if (!(msg.buf instanceof Uint8Array)) {
43 |         msg.buf = new Uint8Array(msg.buf);
44 |       }
45 |       openpgp.crypto.random.randomBuffer.set(msg.buf);
46 |       break;
47 | 
48 |     default:
49 |       if (typeof openpgp[msg.event] !== 'function') {
50 |         throw new Error('Unknown Worker Event');
51 |       }
52 | 
53 |       // parse cloned packets
54 |       openpgp[msg.event](openpgp.packet.clone.parseClonedPackets(options, msg.event)).then(function(data) {
55 |         // clone packets (for web worker structured cloning algorithm)
56 |         response({ event:'method-return', data:openpgp.packet.clone.clonePackets(data) });
57 |       }).catch(function(e) {
58 |         response({ event:'method-return', err:e.message });
59 |       });
60 |   }
61 | };
62 | 
63 | function response(event) {
64 |   if (openpgp.crypto.random.randomBuffer.size < MIN_SIZE_RANDOM_BUFFER) {
65 |     self.postMessage({event: 'request-seed'});
66 |   }
67 |   self.postMessage(event, openpgp.util.getTransferables.call(openpgp.util, event.data));
68 | }
--------------------------------------------------------------------------------