# Digital Envelope Module

This module defines the digital envelope API for Scytl's JavaScript cryptographic library. The starting point for using this module is the instantiation of a digital envelope service.

## How to view, build and test the source code of this module

Start by git cloning the project `comm/scytl-cryptolib` from `Stash`.

The source code of this module will be found in the directory `scytl-cryptolib/cryptolib-js-digitalenvelope/lib`.

To build this module, change to the directory `scytl-cryptolib/cryptolib-js-digitalenvelope` and do the following:

```java
npm install
--or--
mvn clean install -DskipTests
```
The unit tests of this module will be found in the directory `scytl-cryptolib/cryptolib-js-digitalenvelope/spec`. To run the tests, change to the directory `scytl-cryptolib/cryptolib-js-digitalenvelope` and do the following:

```javascript
karma test
--or--
mvn test
```
To only run a chosen test suite, add an `f` in front of the corresponding `describe` statement. For example:

```javascript
fdescribe('create a digital envelope generator/opener pair that should be able to', function()
...
```
To only run a chosen test, add an `f` in front of the corresponding `it` statement. For example:

```javascript
fit('generate a digital envelope with a single public key and open the envelope with the corresponding private key',
...
```
**Note:** To build and test the entire `scytl-cryptolib` project, change to the directory `scytl-cryptolib` and do the following:

```javascript
mvn clean install
```
## How to generate the JSDoc for this module

To generate the JSDoc for this module, change to the directory `scytl-cryptolib/cryptolib-js-digitalenvelope`, build the module (if not already done) and do the following:

```javascript
node_modules/.bin/jsdoc lib
```
This will generate a file called `out`. Double click on the file `out/index.html` to view the JSDoc.

## How to `npm` install this module

To `npm` install this module in standalone mode, do the following:

```javascript
npm install --registry https://nexus.scytl.net/content/groups/public-npm/ scytl-digitalenvelope
```
To `npm` install this module as a dependency of your own module, do the following:

1. Add the following lines to the `dependencies` section of your module's `package.json` file.
    ```javascript
    "scytl-bitwise": "^2.1.0",
    "scytl-codec": "^2.1.0",
    "scytl-cryptopolicy": "^2.1.0",
    "scytl-symmetric": "^2.1.0",
    "scytl-asymmetric": "^2.1.0",
    "scytl-digitalenvelope": "^2.1.0",
    ```
2. Make sure that the `.npmrc` file of your module contains the following line.
    ```javascript
    registry=https://nexus.scytl.net/content/groups/public-npm/
    ```
3. Install all dependencies.
    ```javascript
    npm install
    ```
## How to instantiate a digital envelope service

The following example shows the default way to create a new instance of a digital envelope service.

```javascript
var digitalEnvelope = require('scytl-digitalenvelope');

var envelopeService = digitalEnvelope.newService();
```
The following example shows how to override the default cryptographic policy used for digital envelope operations by changing the MAC hash algorithm to `SHA512/224`.

```javascript
var cryptoPolicy = require('scytl-cryptopolicy');
var digitalEnvelope = require('scytl-digitalenvelope');

var myPolicy = cryptoPolicy.newInstance();

myPolicy.digitalEnvelope.symmetric.mac.hashAlgorithm =
  cryptoPolicy.options.digitalEnvelope.symmetric.mac.hashAlgorithm.SHA512_224;

var envelopeService = digitalEnvelope.newService({policy: myPolicy});
```
**Note:** It is desirable to use the property `CryptographicPolicy.options` to override the default policy, as shown above, in order to ensure that one is using an option that is allowed by the cryptographic policy.

The following example shows how to supply one's own symmetric cryptography service to the digital envelope service.

``` javascript
var digitalEnvelope = require('scytl-digitalenvelope');
var symmetric = require('scytl-symmetric');

var mySymmetricService = symmetric.newService({policy: myPolicy});
var envelopeService = digitalEnvelope.newService({
  policy: myPolicy,
  symmetricCrytographyService: mySymmetricService
});
```
**Note** If both a service and the cryptographic policy are specified as options, one must ensure that the specified service uses the specified policy, as shown above.

## How to generate a digital envelope

The following example shows how to generate a digital envelope from a single public key (PEM encoded), given the data to store in the envelope. The data can be in the form of a byte array, wrapped in a `Uint8Array` object, or a string.

```javascript
var envelopeGenerator = envelopeService.newGenerator(publicKeyPem);
...
var envelope = envelopeGenerator.generate(data);
```
The resulting digital envelope can be opened by using the private key corresponding to the public key used to generate the envelope (see next section).

The following example shows how to generate a digital envelope from multiple public keys (each PEM encoded), given the data to store in the envelope.

```javascript
var envelopeGenerator = envelopeService.newGenerator(publicKey1Pem, publicKey2Pem, ...);
...
var envelope = envelopeGenerator.generate(data);
```
The resulting digital envelope can be opened by using any private key corresponding to one of the public keys used to generate the envelope (see next section).

## How to open a digital envelope

The following example shows how to open a digital envelope and retrieve its data, using any private key corresponding to a public key that was used to generate the envelope. The output data will be in form of a byte array, wrapped in a `Uint8Array` object.

```javascript
var envelopeOpener = envelopeService.newOpener(privateKeyPem);
...
var data = envelopeOpener.open(envelope);
```
## Description of the digital envelope structure

The digital envelope is encapsulated by a `DigitalEnvelope` object, which defines the following properties and functions.

```java
@property encryptedData The symmetrically encrypted data.
@property mac The MAC of the symmetrically encrypted data.
@property encryptedSecretKeyPairs The asymmetric encryptions of the concatenation of the encryption secret key and MAC secret key used to generate and open the digital envelope, each asymmetric encryption having been generated using a different one of the public keys used to initialize digital envelope generator.

@function toJson Serializes the object into a JSON string representation.
```
## How to instantiate a digital envelope object.

The following example shows how to create a new `DigitalEnvelope` object from another envelope's properties.

```javascript
var envelope = envelopeGenerator.init(publicKeyPem).generate(data);
...
var newEnvelope = envelopeService.newEnvelope(envelope.encryptedData, envelope.mac, envelope.encryptedSecretKeyPairs);
```

The following example shows how to serialize a `DigitalEnvelope` object to its corresponding JSON string representation and deserialize it by providing it as input when creating a new `DigitalEnvelope` object.

```javascript
var envelopeJson = envelope.toJson();
...
var envelopeFromJson = envelopeService.newEnvelope(envelopeJson);
```
