generated from nichoth/template-ts-browser
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
513 additions
and
174 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,61 @@ | ||
# template ts browser | ||
# keys | ||
![tests](https://github.com/bicycle-codes/keys/actions/workflows/nodejs.yml/badge.svg) | ||
[![types](https://img.shields.io/npm/types/@bicycle-codes/keys?style=flat-square)](README.md) | ||
[![module](https://img.shields.io/badge/module-ESM%2FCJS-blue?style=flat-square)](README.md) | ||
[![semantic versioning](https://img.shields.io/badge/semver-2.0.0-blue?logo=semver&style=flat-square)](https://semver.org/) | ||
[![Common Changelog](https://nichoth.github.io/badge/common-changelog.svg)](./CHANGELOG.md) | ||
[![install size](https://flat.badgen.net/packagephobia/install/@bicycle-codes/keys)](https://packagephobia.com/result?p=@bicycle-codes/keys) | ||
[![license](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) | ||
|
||
A template for typescript *dependency* modules that run in a browser environment. | ||
Uses `tape-run` for tests in a browser. See [template-ts](https://github.com/nichoth/template-ts) for the same thing but targeting Node. | ||
Create and store keypairs in-browser with the [web crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API). | ||
|
||
Use [indexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) to store [non-extractable keypairs](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey#extractable). This means that the browser prevents you from reading the private key, but it can be persisted and re-used indefinitely. | ||
|
||
<details><summary><h2>Contents</h2></summary> | ||
<!-- toc --> | ||
</details> | ||
|
||
## install | ||
|
||
```sh | ||
npm i -S @bicycle-codes/keys | ||
``` | ||
|
||
## API | ||
|
||
This exposes ESM and common JS via [package.json `exports` field](https://nodejs.org/api/packages.html#exports). | ||
|
||
### ESM | ||
```js | ||
import '@bicycle-codes/keys' | ||
``` | ||
|
||
### Common JS | ||
```js | ||
require('@bicycle-codes/keys') | ||
``` | ||
|
||
### pre-built JS | ||
This package exposes minified JS files too. Copy them to a location that is | ||
accessible to your web server, then link to them in HTML. | ||
|
||
#### copy | ||
```sh | ||
cp ./node_modules/@bicycle-codes/keys/dist/index.min.js ./public/keys.min.js | ||
``` | ||
|
||
#### HTML | ||
```html | ||
<script type="module" src="./keys.min.js"></script> | ||
``` | ||
|
||
------------------------------------------------------ | ||
|
||
## use | ||
1. Use the template button in github. Or clone this then | ||
`rm -rf .git && git init`. Then `npm i && npm init`. | ||
|
||
2. Edit the source code in `src/index.ts`. | ||
|
||
3. Delete either `.github/workflows/gh-pages-docs.yml` or `.github/workflows/gh-pages.yml`, depending on whether you want to deploy an example or docs to github pages. | ||
|
||
4. __Edit things__ | ||
* Use `./README.example.md` as a starter for docs: | ||
```sh | ||
cp ./README.example.md ./README.md | ||
``` | ||
* edit the [build-example](https://github.com/nichoth/template-web-component/blob/c580636f1c912fe2633f7c2478f28b11729c9b80/package.json#L20) command in `package.json` so that it has the right | ||
namespace for github pages | ||
|
||
## featuring | ||
|
||
* compile the source to both ESM and CJS format, and put compiled files in `dist`. | ||
* ignore `dist` and `*.js` in git, but don't ignore them in npm. That way we | ||
don't commit any compiled code to git, but it is available to consumers. | ||
* use npm's `prepublishOnly` hook to compile the code before publishing to npm. | ||
* use [exports](./package.json#L41) field in `package.json` to make sure the right format is used | ||
by consumers. | ||
* `preversion` npm hook -- lint | ||
* `postversion` npm hook -- `git push --follow-tags && npm publish` | ||
* eslint -- `npm run lint` | ||
* tests run in a browser environment via `tape-run` -- see [`npm test`](./package.json#L12). | ||
Includes `tap` testing tools -- [tapzero](https://github.com/bicycle-codes/tapzero) | ||
and [tap-spec](https://www.npmjs.com/package/tap-spec) | ||
* CI via github actions | ||
|
||
### example | ||
|
||
### JS | ||
```js | ||
import '@bicycle-codes/keys' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { RsaSize, HashAlg, CharSize } from './types' | ||
|
||
export const BASE58_DID_PREFIX = 'did:key:z' | ||
|
||
export const RSA_ALGORITHM = 'RSA-OAEP' | ||
export const RSA_SIGN_ALGORITHM = 'RSASSA-PKCS1-v1_5' | ||
export const RSA_HASHING_ALGORITHM = 'SHA-256' | ||
|
||
export const DEFAULT_RSA_SIZE = RsaSize.B2048 | ||
export const DEFAULT_HASH_ALGORITHM = HashAlg.SHA_256 | ||
export const DEFAULT_CHAR_SIZE = CharSize.B8 | ||
|
||
export const SALT_LENGTH = 128 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,93 @@ | ||
import { createDebug } from '@bicycle-codes/debug' | ||
const debug = createDebug() | ||
import { webcrypto } from '@bicycle-codes/one-webcrypto' | ||
import { | ||
RSA_ALGORITHM, | ||
DEFAULT_RSA_SIZE, | ||
DEFAULT_HASH_ALGORITHM, | ||
RSA_SIGN_ALGORITHM | ||
} from './constants' | ||
import { | ||
KeyUse, | ||
type RsaSize, | ||
type HashAlg, | ||
type DID | ||
} from './types' | ||
import Debug from '@bicycle-codes/debug' | ||
const debug = Debug() | ||
|
||
export function example ():void { | ||
debug('hello') | ||
/** | ||
* Expose RSA keys only for now, because we are | ||
* waiting for more browsers to support ECC. | ||
*/ | ||
export class Keys { | ||
encrypt:CryptoKeyPair | ||
sign:CryptoKeyPair | ||
|
||
constructor (keys:{ encrypt:CryptoKeyPair, sign:CryptoKeyPair }) { | ||
this.encrypt = keys.encrypt | ||
this.sign = keys.sign | ||
} | ||
|
||
static async create ():Promise<Keys> { | ||
const encryptionKeypair = await makeRSAKeypair( | ||
DEFAULT_RSA_SIZE, | ||
DEFAULT_HASH_ALGORITHM, | ||
KeyUse.Encrypt | ||
) | ||
const signingKeypair = await makeRSAKeypair( | ||
DEFAULT_RSA_SIZE, | ||
DEFAULT_HASH_ALGORITHM, | ||
KeyUse.Sign | ||
) | ||
|
||
const keys = new Keys({ | ||
encrypt: encryptionKeypair, | ||
sign: signingKeypair | ||
}) | ||
|
||
const rootDID = await writeKeyToDid(signingKeypair) | ||
|
||
debug('create new keys', keys) | ||
|
||
return keys | ||
} | ||
} | ||
|
||
async function makeRSAKeypair ( | ||
size:RsaSize, | ||
hashAlg:HashAlg, | ||
use:KeyUse | ||
):Promise<CryptoKeyPair> { | ||
if (!(Object.values(KeyUse).includes(use))) { | ||
throw new Error('invalid key use') | ||
} | ||
const alg = use === KeyUse.Encrypt ? RSA_ALGORITHM : RSA_SIGN_ALGORITHM | ||
const uses:KeyUsage[] = (use === KeyUse.Encrypt ? | ||
['encrypt', 'decrypt'] : | ||
['sign', 'verify']) | ||
|
||
return webcrypto.subtle.generateKey({ | ||
name: alg, | ||
modulusLength: size, | ||
publicExponent: publicExponent(), | ||
hash: { name: hashAlg } | ||
}, false, uses) | ||
} | ||
|
||
function publicExponent ():Uint8Array { | ||
return new Uint8Array([0x01, 0x00, 0x01]) | ||
} | ||
|
||
/** | ||
* "write" key is for signing things | ||
* | ||
* @param {CryptoKeyPair} publicWriteKey This device's write key. | ||
* @returns {Promise<DID>} | ||
*/ | ||
export async function writeKeyToDid ( | ||
publicWriteKey:CryptoKeyPair | ||
):Promise<DID> { | ||
const arr = await getPublicKeyAsArrayBuffer(publicWriteKey) | ||
const ksAlg = 'rsa' | ||
|
||
return publicKeyToDid(new Uint8Array(arr), ksAlg) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
export type DID = `did:key:z${string}` | ||
|
||
export enum RsaSize { | ||
B1024 = 1024, | ||
B2048 = 2048, | ||
B4096 = 4096 | ||
} | ||
|
||
export enum HashAlg { | ||
SHA_1 = 'SHA-1', | ||
SHA_256 = 'SHA-256', | ||
SHA_384 = 'SHA-384', | ||
SHA_512 = 'SHA-512', | ||
} | ||
|
||
export enum KeyUse { | ||
Encrypt = 'encryption', // encrypt/decrypt | ||
Sign = 'signing', // sign | ||
} | ||
|
||
export enum CharSize { | ||
B8 = 8, | ||
B16 = 16, | ||
} | ||
|
||
export type Msg = ArrayBuffer|string|Uint8Array |
Oops, something went wrong.