Giter Club home page Giter Club logo

webcrypto-crypt's Introduction

Introduction

webcrypto-crypt provides a single library for encrypting and decrypting data at rest in node and the browser. It enables secret key cryptography with a passphrase using either Window.crypto or node-webcrypto-ossl, depending on the environment in which it's running. Please see this important WARNING.

For node, webcrypto-crypt also installs a utility called wcrypt intended to help with files on disk, other sources of piped data, etc. from the command line.

Technical details on webcrypto-crypt's default key derivation function and symmetric key algorithm can be found in the W3C WebCrypto API specification sections, PBKDF2 and AES-GCM.

Install

λ npm install -g webcrypto-crypt

Quickstart

Command-line

From prompt

λ wcrypt | wcrypt -d
Data to encrypt: no honour among consultants.
Passphrase?
Confirm passphrase:
Passphrase?
no honour among consultants.λ

From and to file

λ wcrypt -i LICENSE -o LICENSE.wcrypt
Passphrase?
Confirm passphrase:
λ wcrypt -d -i LICENSE.wcrypt
Passphrase?
MIT License

Copyright (c) 2017 C2FO...

From command line arg

λ wcrypt -a 'edge of a dynastic rebellion' > mydata.wcrypt
Passphrase?
Confirm passphrase:
λ cat mydata.wcrypt | wcrypt -d  # or wcrypt -di mydata.wcrypt
Passphrase?
edge of a dynastic rebellionλ

From pipe

λ echo 'pretty despite its implicit threat' | wcrypt | wcrypt -d
Passphrase?
Confirm passphrase:
Passphrase?
pretty despite its implicit threat

Node.js

    const Wcrypt = require('webcrypto-crypt'),
        wcrypt = new Wcrypt.cipher('testPass');
    wcrypt.encrypt('no honour among consultants.')
    .then((buf) => {
        // do something with buf
    });

Browser

    <script src="/path/to/dist/wcrypt.js"></script>
    <script>
        var wcrypt = new Wcrypt.cipher('testPass');
        wcrypt.encrypt('edge of a dynastic rebellion')
        .then((buf) => {
            // do something with buf
        });
    </script>

Examples

Node.js

    #!/bin/sh
    ':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"

    const readlineSync = require('readline-sync'),
        Wcrypt = require('webcrypto-crypt');

    function askForData() {
        return readlineSync
            .question('Data to encrypt? ');
    }

    function askForPassphrase() {
        return readlineSync
            .question('Passphrase to use? ',
                {hideEchoBack: true, mask:''}
        );
    }

    var wcrypt = new Wcrypt.cipher(askForPassphrase());

    wcrypt.encrypt(askForData())
    .then((data) => {
        console.log(
            "\nEncrypted, hex-encoded: " + data.toString('hex'),
            "\nEncrypted, base64-encoded: " + data.toString('base64'),
            "\nEncrypted, web-safe base64-encoded: " + wcrypt.uriSafeBase64(data),
            "\n\nDecrypted using same passphrase:"
        );
        wcrypt.decrypt(data)
        .then((data) => {
            console.log(Buffer.from(data).toString('utf8'));
        });
    });
λ node examples/prompts.js
Passphrase to use?
Data to encrypt? ambiguous or even contradictory situations

Encrypted, hex-encoded: c0e82e52c7400925f43e2753249afd8b1527a193917267df53d73d63f287519717c73d3e6c1a3da1797ef19055a49b8402cbb0e10f0a5a294545
Encrypted, base64-encoded: wOguUsdACSX0PidTJJr9ixUnoZORcmffU9c9Y/KHUZcXxz0+bBo9oXl+8ZBVpJuEAsuw4Q8KWilFRQ==
Encrypted, web-safe base64-encoded: wOguUsdACSX0PidTJJr9ixUnoZORcmffU9c9Y_KHUZcXxz0.bBo9oXl.8ZBVpJuEAsuw4Q8KWilFRQ--

Decrypted using same passphrase:
ambiguous or even contradictory situations
λ

Browser

<html>
    <head>
        <script src="/path/to/dist/wcrypt.js"></script>
        <script>
            var wcrypt = new Wcrypt.cipher(prompt("Secret? "));
            wcrypt.encrypt(prompt("Data to encrypt? "))
            .then((data) => {
                 console.log(
                     "\nEncrypted, hex-encoded: " + data.toString("hex"),
                     "\nEncrypted, base64-encoded: " + data.toString("base64"),
                     "\nEncrypted, web-safe base64-encoded: " + wcrypt.uriSafeBase64(data),
                     "\n\nDecrypted using same passphrase:"
                 );
                 wcrypt.decrypt(data)
                     .then((data) => {
                         console.log(Buffer.from(data).toString("utf8"));
                     });
            });
       </script>
   </head>
   <body>
       (Check the Developer console.)
   </body>
</html>
// In the dev console, after calls to window.prompt() are satisfied, e.g.:
1GTLSRGmdkiAn6pwBB1XWYllS2VgF87h8575Ok2NlIzdH42YgoUFRpFiqbYqj2BKLJEQqoQ-
index.html:11 in a world that allowed such mistakes

Note that webcrypto-crypt injects browserify's global Buffer object in the browser context so that data can be easily encoded outside of browserified code, as needed.

Test

Tested environments

OS Environment Version
Mac Sierra Firefox 53.0.3 (64-bit)
Mac Sierra Chrome 58.0.3029.110 (64-bit)
Mac Sierra WebKit Nightly Release 30 (Safari 10.2, WebKit 12604.1.22)
Mac Sierra Node node v6.6.0 v8 5.1.281.83
Mac Sierra Node node v7.9.0 v8 5.5.372.43
Mac Sierra Node node v7.10.0 v8 5.5.372.43
Mac Sierra Node node v8.0.0 v8 5.8.283.41

Node.js

λ npm run test

Browsers

A file that should run the module tests in the browser is test/browser/wcrypt-test.html

API

Wcrypt.parseHeader(Buffer data)

Provided data is a valid webcrypto-wcrypt header, parse it and return an object with the following structure:

    {
        "material": {
            "iv": "<iv>",
            "salt": "<salt>",
        },
        "config": {
            "crypto": {
                "tagLength": "<tagLength>"
            },
            "derive": {
                "iterations": "<iterations>"
            }
        }
    }

new Wcrypt.cipher(String passphrase || Object options)

Instantiate a webcrypto-crypt object using just a passphrase or more options beyond the passphrase. When passing in an object, the minimum specification looks like {material: { passphrase: <your passphrase> } }. All the possible options are described below:

    var wcrypt = new Wcrypt.cipher({
        config: {
            crypto: {
                algorithm: myAlgorithm,      // default 'AES-GCM'
                keyUsages: [myku1, myku2...],// default ['encrypt', 'decrypt']
                tagLength: myTagLength,      // default 128
            },
            debug: myDebugBoolean,           // default false
            delimiter: myDelimiter,          // default '<WcRyP+>'
            derive: {
                algorithm: myDerivFunction,  // default 'PBKDF2'
                hash: myHashFunction,        // default 'SHA-512'
                iterations: myIterations,    // default 2000
            }
        },
        material: {
            iv: myInitializationVector,   // default getRandomValues(new Uint8Array(12))
            passphrase: 'myTestSecret123' // REQUIRED, passphrase as String
            salt: mySalt                  // default getRandomValues(new Uint8Array(16))
        }
    })
    .then(...

wcrypt.createHeader()

Return a Buffer filled with the appropriate seed data for encryption. See these lines.

wcrypt.decrypt(Buffer data)

Decrypt data by first parsing its header section to extract configuration and material settings. Note that the invoking wcrypt object will assume these extracted configuration and material settings for all its subsequent operations, unless subsequently overridden by reading in a different header.

Returns a promise with its resolved value set to a Buffer of the decrypted data.

wcrypt.delimiter

The current delimiter in use by this library, e.g., <WcRyP+>.

wcrypt.encrypt(Buffer data)

Encrypt the given data and include a header.

Returns a promise with its resolved value set to a Buffer of the encrypted data.

wcrypt.encryptDelimited(Buffer data)

Encrypt the given data and include a delimiter.

Returns a promise with its resolved value set to a Buffer of the encrypted data.

wcrypt.getDelimiter()

Return the delimiter webcrypto-crypt is currently configured to use as a Buffer.

wcrypt.getSignature()

Return the current file signature in use by this library as a Buffer.

wcrypt.name

The current name of this library, e.g., webcrypto-crypt.

wcrypt.rawDecrypt(Buffer data, Object options)

Decrypt data. Assumes no header present unless assumeHeader: true is passed in via an options object.

Returns a promise with its resolved value set to a Buffer of the decrypted data.

wcrypt.rawEncrypt(Buffer data, Object options)

Returns a promise with its resolved value set to a Buffer of the encrypted data.

The first argument is the data to encrypt. The second argument options is optional and currently supports two attributes:

wcrypt.rawEncrypt('Some text to encrypt', {appendDelimiter: true});

Will append the wcrypt.delimiter to the end of the encrypted data before returning it. And:

wcrypt.rawEncrypt('Some text to encrypt', {includeHeader: true});

Will append a cleartext header to the returned data including: initialization vector, iterations, salt, and tagLength used in the encryption. See these lines.

wcrypt.subtle

The SubtleCrypto object currently in use.

wcrypt.uriSafeBase64(Buffer data)

Convenience method for browser contexts to encode the passed-in data using web safe base 64 alphabet and return the result.

wcrypt.version

The current version of this library, e.g., 0.1.2.

Command-line

Installing webcrypto-crypt also installs a command-line utilty, wcrypt:

Help

TTY

λ wcrypt -h
Usage: wcrypt [options]

Options:
  --debug, -D    write debug info to stderr         [boolean] [default: "false"]
  --help, -h     Show help                                             [boolean]
  --outfile, -o  write data to this file                                [string]
  --infile, -i   read data from this file                               [string]
  --arg, -a      read data from command line                            [string]
  --decrypt, -d                                       [boolean] [default: false]

Examples:
  wcrypt -i msg.txt -o msg.wcrypt      file to encrypt
  wcrypt -di msg.wcrypt -o msg.txt     file to decrypt
  wcrypt -a "nonessential appliances"  string to encrypt

Piped

λ echo '' | wcrypt -h
Usage: data | wcrypt [options]

Options:
  --debug, -D    write debug info to stderr         [boolean] [default: "false"]
  --help, -h     Show help                                             [boolean]
  --outfile, -o  write data to this file                                [string]
  --decrypt, -d                                       [boolean] [default: false]

Examples:
  cat msg.txt | wcrypt -o msg.wcrypt       encrypt,store in file
  cat msg.wcrypt | wcrypt -d               decrypt
  curl http:..:4196 | wcrypt > aud.wcrypt  stream to encrypt

Command-line examples

Note that some of these examples may take a few minutes to download or stream.

Note also that you may set the environment variable WCRYPT_PASS to have wcrypt skip its passphrase prompts.

Text file

λ export TXTFILE_URL="http://web.archive.org/web/20160514230001/http://www.mit.edu/~yandros/doc/command.txt"
λ curl -Ss "$TXTFILE_URL" | wcrypt > command.wcrypt
Passphrase?
Confirm passphrase:
λ wcrypt -di command.wcrypt -o command.txt
Passphrase?
λ less command.txt

Audio file

λ export AUDIO_URL="https://ia802509.us.archive.org/18/items/interview-with-neal-stephenson.JUcDkK.popuparchive.org/focus990527b.mp3"
λ curl -NSs "$AUDIO_URL" | wcrypt > ns-interview.wcrypt
Passphrase?
Confirm passphrase:
λ wcrypt -di ns-interview.wcrypt -o ns-interview.mp3
Passphrase?
λ open ns-interview.mp3

Audio stream

λ export STREAM_URL="http://vprbbc.streamguys.net/vprbbc24-mobile.mp3"
λ curl -NSsm 10 "$STREAM_URL" | wcrypt | wcrypt -d | mpg123 -q -
Passphrase?
Confirm passphrase:
Passphrase?

Header structure

See these lines.

Security

Security Mail: [email protected]
PGP key fingerprint: E838 B51C C63F 7ED6 0980 9535 4D46 5218 A674 6F81
Keyserver: pgp.mit.edu

See also

webcrypto-crypt's People

Contributors

petethomas avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.