Crypto-wraps
Tags: javascript, crypto, subtle
Published: 2021-08-10 02:21:54

---
title: Crypto-wraps
published: true
description: Some methods to wrap crypto.subtle, hopefully making life simpler
tags: #JavaScript #crypto #subtle
//cover_image: https://direct_url_to_image.jpg
---

So, I put this npm package out there: [crypto-wraps](https://www.npmjs.com/package/crypto-wraps)

For this package, which is on GitHub [crypto-wraps-GitHub](https://www.github.com/copious-world/crypto-wraps)

```
npm test
```

I tested it in FireFox and node.js

As with many wrapper libraries, some of the methods pick which encryption standard they use. So, while crypto.subtle  gives you just about every standard crypto routine you can think of, this library just uses some of them.

More on the crypto.subtle library can be found at MDN: [Crypto/subtle](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/subtle). 

What is there to say? Well, calling the crypto.subtle methods has its ins and outs. The code gets a little long, and you are always worrying about the types of the data buffers going in and out of the methods. Then, since the crypto.subtle methods always use ArrayBuffers or more specifically Uint8Arrays, your program has to put the buffers into text (hex or base64url) to send them anywhere.

Actually, I ran into some trouble storing buffers straight up in the IndexedDB. But, they stored well as blobURls which are usually a base64 encoding of the blob along with some mime type information.  But, yes, the first time I stuck a blob straight into the IndexedDB to have it disappear, I was a little surprised and started converting the buffers to base text.

So, here is a code example from the node.js test:

```
let cwraps = require('../lib/crypto-wraps')
let hashit = require('../lib/crypto-hash');
...

    let again_text = "Finally the last test again until the next last test."
    let again_cipher_text = await cwraps.encipher_message(again_text,aes_key,nonce)
    let wrapped_key = await cwraps.key_wrapper(aes_key,key_pack.pk_str)
    let again_decipher_text =  await cwraps.decipher_message(again_cipher_text,wrapped_key,key_pack.priv_key,nonce)

```

Now, I saved myself a lot lines. Here is the code for just the key_wrapper:

```
async function key_wrapper(key_to_wrap,pub_wrapper_key) {
	try {
		let wrapper_jwk = JSON.parse(pub_wrapper_key)
		let wrapper = await g_crypto.importKey(
				"jwk",
				wrapper_jwk,
				{   //these are the wrapping key's algorithm options
					name: "RSA-OAEP",
					modulusLength: 4096, //can be 1024, 2048, or 4096
					publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
					hash: { name: "SHA-256" },
				},
				true,
				["wrapKey"]
		);

		let wrapped_key = await g_crypto.wrapKey(
											"jwk",
											key_to_wrap,
											wrapper,
											{   //these are the wrapping key's algorithm options
												name: "RSA-OAEP"
											}
										);
		let type8 = new Uint8Array(wrapped_key)
		let tranportable = to_base64_from_uint8array(type8)
		return tranportable
	} catch(e) {
		console.log(e)
	}
	return false
}
```

So, you see how things can grow. Here the program is parsing JSON to get an "jwk" object carrying the public wrapper key. This is the key you would give someone to wrap something to send to you, that only you can unwrap with your private key. The code imports the wrapper key from the "jwk" object. The key to wrap is passed in as an object of type Cryptokey. The wrapper does not know too much about it. But, it is an AES key that I got out of the key gen method.

The methods are using this global variable: **g\_crypto**. The reason for that is that node.js exposed the *crypto.subtle* methods from one global object, while the browser uses another: 

node.js way:

```
let g_crypto = crypto.webcrypto.subtle
```

browser way:

```
window.g_crypto = window.crypto ? window.crypto.subtle : null
```

It turns out that node.js and the browser are very much in agreement with the exposition of the *crypto.subtle* methods. The modules, crypto-wraps.js, for the two versions are almost identical. For base64url encoding, they both import to methods from the hash module: 

* to_base64_from_uint8array
* from_base64_to_uint8array

These methods do differ between node.js and the browser. But, at the next level up, they are used exactly the same. 

For the browser version, I borrowed base64 encoding from a Gist by Egor Nepomnyaschih. [base64](https://gist.github.com/enepomnyaschih/72c423f727d395eeaa09697058238727).  That proved to be very helpful. The node version makes use of easy Buffer class conversions.

### That's all for now folks.

Have fun with it. Leave notes in the issues. Thanks.