# Symmetric Cryptography Module

This module defines the symmetric cryptography API for Scytl's JavaScript cryptographic library. The starting point for using this module is the instantiation of a symmetric cryptography 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-symmetric/lib`.

To build this module, change to the directory `scytl-cryptolib/cryptolib-js-symmetric` 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-symmetric/spec`. To run the tests, change to the directory `scytl-cryptolib/cryptolib-js-symmetric` 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 secret key generator 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 secret key for encryption', function()
...
```
**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-symmetric`, 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-symmetric
```
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-securerandom": "^2.1.0",
    "scytl-symmetric": "^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 symmetric cryptography service

The following example shows the default way to create a new instance of a symmetric cryptography service.

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

var symmetricService = symmetric.newService();
```
The following example shows how to override the default cryptographic policy used for symmetric cryptography operations by changing the encryption secret key length to 32 bytes.

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

var myPolicy = cryptoPolicy.newInstance();

myPolicy.symmetric.secretKey.encryption.lengthBytes =
  cryptoPolicy.options.symmetric.secretKey.encryption.lengthBytes.KL_32;

var symmetricService = symmetric.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 secure random service object to the symmetric cryptography service.

``` javascript
var symmetric = require('scytl-symmetric');
var secureRandom = require('scytl-securerandom');

var mySecureRandomService = secureRandom.newService();

var symmetricService = symmetric.newService({secureRandomService: mySecureRandomService});
```
## How to generate secret keys

The following examples show how to generate a secret key for encryption and a secret key for MAC generation. The keys will be returned in the form of a byte array, wrapped in a `Uint8Array` object.

```javascript
var keyGenerator = symmetricService.newKeyGenerator();

var encryptionKey = keyGenerator.nextEncryptionKey());
var macKey = keyGenerator.nextMacKey());
```
## How to encrypt and decrypt data

The following examples show how to symmetrically encrypt and decrypt some data. The data to encrypt can be in the form of a `string` or a byte array, wrapped in a `Uint8Array` object. The output of both the encrypt and decrypt operations will be a byte array, wrapped in a `Uint8Array` object. To retrieve encrypted data of type `string`, the result of the decryption must be UTF-8 decoded.

```javascript
var codec = require('scytl-codec');
...
var cipher = symmetricService.newCipher().init(encryptionKey);

var encryptedData = cipher.encrypt('myData');
var decryptedData = codec.utf8Decode(cipher.decrypt(encryptedData));
expect(decryptedData).toBe('myData');

var encryptedData = cipher.encrypt(new Uint8Array[0x01, 0x02, 0x03]);
var decryptedData = cipher.decrypt(encryptedData);
expect(decryptedData).toEqual(new Uint8Array[0x01, 0x02, 0x03]);
```
## How to generate and verify a MAC

The following examples show how to generate and verify a MAC from some data. The data for MAC generation or verification can be in the form of a `string` or a byte array, wrapped in a `Uint8Array` object. The output of the MAC generation will be in the form of a byte array, wrapped in a `Uint8Array` object.

```javascript
var macHandler = symmetricService.newMacHandler().init(macKey);
...

var mac = macHandler.generate('myData');
var verified = macHandler.verify(mac, 'myData');
expect(verified).toBeTruthy();

var mac = macHandler.generate(new Uint8Array[0x01, 0x02, 0x03]);
var verified = macHandler.verify(mac, new Uint8Array[0x01, 0x02, 0x03]);
expect(verified).toBeTruthy();
```
The following example shows how to generate a MAC from multiple data parts.

```javascript
var dataParts = ['myData1', 'myData2', 'myData3'];
...

for (var i = 0; i < dataParts.length; i++) {
  macHandler.update(dataParts[i]);
}
var mac = macHandler.generate();

--or--

for (var i = 0; i < (dataParts.length-1); i++) {
  macHandler.update(dataParts[i]);
}
var mac = macHandler.generate('myData3');
```
The following example shows how to verify a MAC from multiple data parts.

```javascript
for (var j = 0; j < dataParts.length; j++) {
  macHandler.update(dataParts[j]);
}
var verified = macHandler.verify(mac);

--or--

for (var j = 0; j < (dataParts.length-1); j++) {
  macHandler.update(dataParts[j]);
}
var verified = macHandler.verify(mac, 'myData3');
```
The following example shows how to generate a MAC from multiple data parts, using method chaining.

```javascript
var mac = macHandler.update('myData1').update('myData2').update('myData3').generate();

--or--

var mac = macHandler.update('myData1').update('myData2').generate('myData3');
```

The following example shows how to verify a MAC from multiple data parts, using method chaining.

```javascript
var verified = macHandler.update('myData1').update('myData2').update('myData3').verify(mac);

--or--

var verified = macHandler.update('myData1').update('myData2').verify(mac, 'myData3');
```
