Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions docs/1_pure_tricks/HowTo_encrypt_Max.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# HowTo: Encrypt data

Encryption is a key way to protect information from intruders, not only by transferring it over a network without risk, but also by guaranteeing data integrity. There are many ciphers, but we will consider one of the most reliable and popular - **AES-GCM**.
`AES-GCM` is an authenticated encryption mode that uses the AES block cipher in counter mode with a polynomial MAC based on Galois field multiplication.

AES stands for `Advanced Encryption Standard` and is a symmetric block encryption algorithm. Symmetric encryption means that the key used for encryption and decryption is identical. The public key used for encrypted data, and only someone with the private key can read the encrypted data.

To encrypt data `getEncryptedData()` is use.

```javascript
async function getEncryptedData(data) {
const iv = crypto.getRandomValues(new Uint8Array(12));
const cipher = await encryptAESGCM(SECRET, iv, data);
return uint8ToHexString(iv) + '.' + toBase64url(btoa(cipher));
}
```
To encrypt data use:
* `iv` Initial vector() - random or pseudo-random sequence of characters that is added to the encryption key to improve its security. The initialization vector does not require encryption and is usually passed along with the cryptographic key. The result of the encryption is a string containing initial vector and encrypted data divided into `.`.
* `SECRET` the secret key used to decrypt the data.
* `data` data to be encrypted.

To create a cipher, use the `encryptAESGCM()` function.

```javascript
let cachedPassHash;

async function passHash(pw) {
return cachedPassHash || (cachedPassHash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(pw)));
}

async function makeKeyAESGCM(password, iv) {
const pwHash = await passHash(password); //small value generated by a hash function from a whole message
const alg = { name: 'AES-GCM', iv: iv }; // specify algorithm to use
return await crypto.subtle.importKey('raw', pwHash, alg, false, ['decrypt', 'encrypt']); //make crypto key
}

async function encryptAESGCM(password, iv, plaintext) {
const key = await makeKeyAESGCM(password, iv); //[1]
const ptUint8 = new TextEncoder().encode(plaintext); //[2]
const ctBuffer = await crypto.subtle.encrypt({ name: key.algorithm.name, iv: iv }, key, ptUint8);//[3]
const ctArray = Array.from(new Uint8Array(ctBuffer)); //[4]
return ctArray.map(byte => String.fromCharCode(byte)).join(''); // ciphertext as string
}
```
1. The function creates the cipher key (not to be confused with the secret key). Creating and managing keys is an important part of the ciphering process. The key should be kept secret from anyone who should not decrypt your data.
2. The data to be encrypted are converted to _UTF-8_ format.
3. Using the Crypto API, data are encrypted.
4. In order for a user to receive data in String format, they must be converted back to Uint8Array and then to string.


Result of encryption is a string which contains `iv` converted into hexString and cipher which is encoded by `btoa()` and converted into _Base64_.

```javascript
function toBase64url(base64str) {
return base64str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

function uint8ToHexString(ar) {
return Array.from(ar).map(b => ('00' + b.toString(16)).slice(-2)).join('');
}
```
The `btoa()` method is for encoding a string specified as a parameter in the ACSII string base-64, which will be represented by 64 characters: "A-Z", "a-z", "0-9", "+", "/" and "=". Base64 encoding can be used to visually hide data from the user, to transfer information, etc. The principle of the method is that it first converts a string into a sequence of bits, which are then converted into an encoded string based on the base-64 scheme.

To reduce the risk of data tampering it is important to follow a few tips:
* Each encryption operation performed with a given key must be unique.
* Never use iv with the same key twice.
* Do not reuse initialization vectors.

## Reference
* [Wikipedia: Galois/Counter Mode](https://en.wikipedia.org/wiki/Galois/Counter_Mode)
* [MDN: importKey](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey)
* [MDN: btoa()](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/btoa)
4 changes: 2 additions & 2 deletions docs/newChapters/the_law/5_6_1_Pattern_Monad_1.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Commonly, monads are described as being created by a plain `function`s, not `con
3. The `new` and `constructor` pattern in JS is a bit flawed:
1. JS doesn't allow `constructor` overloading. This means you *must* have only *one* `constructor` per class. This doesn't really fit well with the class concept in general, nor monads in particular. What *can* happen is that you end up cramming *two or more different functions* into *one constructor*, which then *can* fill your `constructor` function with super fragile, god-awful argument type and value checking, extra arguments to identify which variant of the `constructor` that you intend to call, etc.
2. Whenever you write `new` in your code, then the JS engine *must* create a new object. This is bad if you need to reuse objects from your own pool of objects. Put simply, you can't memoize nor reuse a `new` thing.
* However, there is a way out of this dilemma: `static` factory functions. You can have many factory functions (no need to cram many functions into one), and you can make the factory functions manage your pool of objects (it's fine to memoize and reuse static factory functions). `class`, `new`, `constructor`, and `static` factory functions is a viable OO pattern.
3. However, there is a way out of this dilemma: `static` factory functions. You can have many factory functions (no need to cram many functions into one), and you can make the factory functions manage your pool of objects (it's fine to memoize and reuse static factory functions). `class`, `new`, `constructor`, and `static` factory functions is a viable OO pattern.

The counter argument advocating for `class` and `constructor` syntax is that they explicitly marks the *role* of the `class` in particular and clearly identify which functionality will be needed by *every* object instance created. It is a step in the direction of making JS a more statically typed langauge. And this yields *three* benefits when using the `class` and `constructor` pattern to create monads:

Expand Down Expand Up @@ -135,4 +135,4 @@ Here is my rules of thumb for making monads in JS:

## References

* [Eric Elliot on OO, constructor, new, class, and extends](https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3)
* [Eric Elliot on OO, constructor, new, class, and extends](https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3)