{"id":31376513,"url":"https://github.com/substrate-system/keys","last_synced_at":"2025-09-28T03:53:38.198Z","repository":{"id":261336238,"uuid":"883558324","full_name":"substrate-system/keys","owner":"substrate-system","description":"Create and store asymmetric keys with the webcrypto API in the browser","archived":false,"fork":false,"pushed_at":"2025-09-17T22:31:26.000Z","size":332,"stargazers_count":3,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-27T06:37:41.580Z","etag":null,"topics":["browser","cryptography","keypair","keys"],"latest_commit_sha":null,"homepage":"https://substrate-system.github.io/keys/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/substrate-system.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["nichoth"]}},"created_at":"2024-11-05T07:14:45.000Z","updated_at":"2025-09-22T06:45:38.000Z","dependencies_parsed_at":"2024-11-06T02:05:12.590Z","dependency_job_id":"8e533078-17e9-4997-915c-44090a255788","html_url":"https://github.com/substrate-system/keys","commit_stats":null,"previous_names":["bicycle-codes/keys","substrate-system/keys"],"tags_count":50,"template":false,"template_full_name":"nichoth/template-ts-browser","purl":"pkg:github/substrate-system/keys","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fkeys","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fkeys/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fkeys/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fkeys/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/substrate-system","download_url":"https://codeload.github.com/substrate-system/keys/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/substrate-system%2Fkeys/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277261229,"owners_count":25788578,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-27T02:00:08.978Z","response_time":73,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["browser","cryptography","keypair","keys"],"created_at":"2025-09-28T03:53:37.456Z","updated_at":"2025-09-28T03:53:38.192Z","avatar_url":"https://github.com/substrate-system.png","language":"TypeScript","funding_links":["https://github.com/sponsors/nichoth"],"categories":[],"sub_categories":[],"readme":"# keys\n[![tests](https://img.shields.io/github/actions/workflow/status/substrate-system/keys/nodejs.yml?style=flat-square)](https://github.com/substrate-system/keys/actions/workflows/nodejs.yml)\n[![types](https://img.shields.io/npm/types/@substrate-system/keys?style=flat-square)](README.md)\n[![module](https://img.shields.io/badge/module-ESM%2FCJS-blue?style=flat-square)](README.md)\n[![semantic versioning](https://img.shields.io/badge/semver-2.0.0-blue?logo=semver\u0026style=flat-square)](https://semver.org/)\n[![Common Changelog](https://nichoth.github.io/badge/common-changelog.svg)](./CHANGELOG.md)\n[![install size](https://flat.badgen.net/packagephobia/install/@substrate-system/keys?cache-control=no-cache)](https://packagephobia.com/result?p=@substrate-system/keys)\n[![GZip size](https://flat.badgen.net/bundlephobia/minzip/@substrate-system/keys)](https://bundlephobia.com/package/@substrate-system/keys)\n[![license](https://img.shields.io/badge/license-Big_Time-blue?style=flat-square)](LICENSE)\n\n\nCreate and store keypairs in the browser with the [web crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API).\n\nUse [`indexedDB`](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)\nto store [non-extractable keypairs](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/generateKey#extractable)\nin the browser. \"Non-extractable\" means that the browser prevents you from ever\nreading the private key, but the keys can be persisted and re-used indefinitely.\n\n\u003e\n\u003e [!TIP]\n\u003e Use the [persist method](https://developer.mozilla.org/en-US/docs/Web/API/StorageManager/persist)\n\u003e to tell the browser not to delete from `indexedDB`.\n\u003e\n\nEach instance of `Keys` has two keypairs -- one for signing, and another for\nencrypting. \n\nSee also, [the API docs generated from typescript](https://substrate-system.github.io/keys/).\n\n\u003cdetails\u003e\u003csummary\u003e\u003ch2\u003eContents\u003c/h2\u003e\u003c/summary\u003e\n\n\u003c!-- toc --\u003e\n\n- [Install](#install)\n- [Modules](#modules)\n  * [`exports`](#exports)\n  * [ESM](#esm)\n  * [Common JS](#common-js)\n  * [pre-built JS](#pre-built-js)\n- [Get started](#get-started)\n  * [Verify a signature](#verify-a-signature)\n  * [ECC](#ecc)\n  * [some notes about the `keys` instance](#some-notes-about-the-keys-instance)\n  * [Delete a keypair](#delete-a-keypair)\n  * [Sign and Verify Something](#sign-and-verify-something)\n  * [encrypt something](#encrypt-something)\n  * [decrypt something](#decrypt-something)\n- [examples](#examples)\n  * [Create a new `Keys` instance](#create-a-new-keys-instance)\n  * [Get a hash of the DID](#get-a-hash-of-the-did)\n  * [Persist the keys](#persist-the-keys)\n  * [Restore from indexedDB](#restore-from-indexeddb)\n  * [Sign something](#sign-something)\n  * [Get a signature as a string](#get-a-signature-as-a-string)\n  * [Verify a signature](#verify-a-signature-1)\n  * [Encrypt a key](#encrypt-a-key)\n  * [Asymmetrically encrypt some arbitrary data](#asymmetrically-encrypt-some-arbitrary-data)\n  * [Asymmetrically encrypt a string, return a new string](#asymmetrically-encrypt-a-string-return-a-new-string)\n  * [Decrypt a message](#decrypt-a-message)\n  * [Backward compatibility: `.decrypt.asString`](#backward-compatibility-decryptasstring)\n  * [In memory only](#in-memory-only)\n- [AES](#aes)\n  * [`create`](#create)\n  * [`export`](#export)\n  * [`exportAsString`](#exportasstring)\n  * [`AES.encrypt`](#aesencrypt)\n  * [`AES.decrypt`](#aesdecrypt)\n\n\u003c!-- tocstop --\u003e\n\n\u003c/details\u003e\n\n\n## Install\n\n```sh\nnpm i -S @substrate-system/keys\n```\n\n## Modules\n\n### `exports`\n\nThis exposes ESM and common JS via [package.json `exports` field](https://nodejs.org/api/packages.html#exports).\n\n### ESM\n```js\nimport { EccKeys, verify } from '@substrate-system/keys/ecc'\nimport { RsaKeys, verify } from '@substrate-system/keys/rsa'\nimport { AES } from '@substrate-system/keys/aes'\n```\n\n### Common JS\n```js\nconst { EccKeys, verify } = require('@substrate-system/keys/ecc')\nconst { RsaKeys, verify } = require('@substrate-system/keys/rsa')\nconst { AES } = require('@substrate-system/keys/aes')\n```\n\n### pre-built JS\nThis package exposes minified JS files too. Copy them to a location that is\naccessible to your web server, then link to them in HTML.\n\n#### copy\n```sh\ncp ./node_modules/@substrate-system/keys/dist/index.min.js ./public/keys.min.js\n```\n\n#### HTML\n```html\n\u003cscript type=\"module\" src=\"./keys.min.js\"\u003e\u003c/script\u003e\n```\n\n------------------------------------------------------\n\n\n## Get started\n\n### Verify a signature\n\nThis function takes either an Ed25519 key or an RSA key.\n\n```js\nimport { verify } from '@substrate-system/keys/crypto'\n\n// ed25519\nconst isOk = await verify({ message, publicKey: ecc.DID, signature })\n\n// RSA\nconst isOk = await verify({ message, publicKey: rsa.DID, signature })\n```\n\n### ECC\n\n#### Create a keypair\nCreate a new keypair, then save it in `indexedDB`.\n\nECC is now supported in all major browsers.\n\n```js\nimport { EccKeys, verify } from '@substrate-system/keys/ecc'\n\nconst keys = await EccKeys.create()\n\n// save the keys to indexedDB\nawait keys.persist()\n\n// ... sometime in the future ...\n// get our keys from indexedDB\nconst keysAgain = await EccKeys.load()\n\nconsole.assert(keys.DID === keysAgain.DID)  // true\n```\n\n### some notes about the `keys` instance\n\n#### `keys.DID`\n\n```js\n'did:key:z13V3Sog2YaUKhdGCmgx9UZuW...'\n```\n\nThis is the [DID string](https://www.w3.org/TR/did-1.0/) for the signing key for\nthis instance. The DID looks like this:\n\nThe Ed25519 DID looks like this:\n\n```\ndid:key:zStERvoWtx7FQS432smzbGENZHjsN55X8pUZ3np8DXGhZFf3TCorijCPeJoLytwb\n```\n\nThe RSA DID looks like this:\n\n```\ndid:key:z13V3Sog2YaUKhdGCmgx9UZuW1o1ShFJYc6DvGYe7NTt689NoL2HdpC46K4PjfsUVAopaqmnySjJV8T6K9dMB2FUXhqfKYLUz9o9fA7xkgiNr25sUQq4vJPuPfP1kbSqtYXe5V2CZTUMucF2jfNMrWjHHRUZpEzPwGeZd5prsu9pxnVhPKnVxxKTJAVqQCp3CDRASeYKQmqVRmyPSrdQaYz4AoQxaBd52mNC7dEC4xXKbVw45dhQc52j5chR8YKCeaNANWh8DEZ7U8Dtb89PL5qP8817oxswQhz4e97p8EGtJDVrGbCXN4EucnpYaacRane4YPcmevs1pMYV8iqzJd8UZLWtDcUBNrCkeVTdnzXnM4Rq9sWiFwF3nYk6fxqfUZDfYyfPtxacSoGaSjo38ye\n```\n\n#### `keys.getDeviceName` / `keys.deviceName`\n\nReturn a 32 character, DNS friendly hash of the signing public key.\n\n```js\nconst name = await keys.getDeviceName()\n\n// a promise is exposed as property `deviceName`\nconst name = await keys.deviceName\n```\n\n#### `keys.hasPersisted`\n\nA flag indicating whether `.persist` has been called, meaning that these keys\nare saved in `indexedDB`.\n\n#### `keys.publicExchangeKey`\n\nThe public encryption `CryptoKey`. For ECC keys, this is the X25519 exchange key.\nFor RSA keys, this is the RSA encryption key.\n\n#### `keys.publicExchangeKeyAsString()`\n\nGet the public encryption key as a `base64` string. For other formats,\n[see below](#format-options).\n\n```ts\n{\n  async publicExchangeKeyAsString (format?:SupportedEncodings):Promise\u003cstring\u003e\n}\n```\n\n#### `keys.publicWriteKey`\n\nThe public signing `CryptoKey`. This is the Ed25519 or RSA signing key.\n\n#### `keys.publicWriteKeyAsString()`\n\nGet the public signing key as a string.\n\n```ts\n{\n  async publicWriteKeyAsString (format?:SupportedEncodings):Promise\u003cstring\u003e\n}\n```\n\n### Delete a keypair\n\nDelete the keys from `indexedDB`.\n\n```js\nawait keys.delete()\n```\n\n--------------------------------------------------------------------------\n\n\n### Sign and Verify Something\n\n`.verify` takes the content, the signature, and the DID for the public key\nused to sign. The DID is exposed as the property `.DID` on a `Keys` instance.\n\n\u003e\n\u003e [!NOTE]  \n\u003e `verify` is exposed as a separate function, so you don't\n\u003e have to include all of `Keys` just to verify a signature.\n\u003e\n\n```js\nimport { RsaKeys, verify } from '@substrate-system/keys/rsa'\n// or: import { EccKeys, verify } from '@substrate-system/keys/ecc'\n\nconst keys = await RsaKeys.create()\n// or: const keys = await EccKeys.create()\n\n// sign something\nconst sig = await keys.signAsString('hello string')\n// or string format: const sig = await keys.sign.asString('hello string')\n\n// verify the signature\nconst isOk = await verify('hello string', sig, keys.DID)\n```\n\n### encrypt something\nTake the public key we are encrypting to, return encrypted content.\n\n#### `keys.encrypt` methods\n\nEncrypt something, return a Uint8Array.\n\n**ECC:**\n\n\u003e\n\u003e [!NOTE]  \n\u003e `recipient` is optional. If it is omitted, then this will encrypt to\n\u003e its own public key, a \"note to self.\"\n\u003e\n\n```ts\nasync encrypt (\n  content:string|Uint8Array,\n  recipient?:CryptoKey|string,  // their public key\n  info?:string,\n  aesKey?:SymmKey|Uint8Array|string,\n  keysize?:SymmKeyLength\n):Promise\u003cUint8Array\u003e\n```\n\n**RSA:**\n```ts\nasync encrypt (\n  content:string|Uint8Array,\n  recipient?:CryptoKey|string,\n  aesKey?:SymmKey|Uint8Array|string,  // For RSA, can pass in AES key\n  keysize?:SymmKeyLength,\n):Promise\u003cUint8Array\u003e\n```\n\n#### `keys.encryptAsString` methods\n\nEncrypt something, return a string.\n\n**ECC:**\n```ts\nasync encryptAsString (\n  content:string|Uint8Array,\n  recipient?:CryptoKey|string,\n  info?:string,\n  aesKey?:SymmKey|Uint8Array|string,\n  keysize?:SymmKeyLength,\n):Promise\u003cstring\u003e\n```\n\n**RSA:**\n```ts\nasync encryptAsString (\n  content:string|Uint8Array,\n  recipient?:CryptoKey|string,\n  aesKey?:SymmKey|Uint8Array|string,\n  keysize?:SymmKeyLength,\n):Promise\u003cstring\u003e\n```\n\n```js\nimport { encryptTo } from '@substrate-system/keys/rsa'  // RSA version\n\n// need to know the public key we are encrypting for\nconst publicKey = await keys.publicExchangeKeyAsString()  // Both ECC and RSA\n\nconst encrypted = await encryptTo({\n  content: 'hello public key',\n  publicKey\n})  // =\u003e ArrayBuffer\n\nconst encrypted = await encryptTo.asString({\n  content: 'hello public key',\n  publicKey\n})  // =\u003e \u003cencrypted text\u003e\n```\n\n### decrypt something\nA `Keys` instance has a method `decrypt`. The `encryptedMessage` argument is\nan `ArrayBuffer`, as returned from `encryptTo`, above.\n\n```js\nimport { EccKeys } from '@substrate-system/keys/ecc'\n// or: import { RsaKeys } from '@substrate-system/keys/rsa'\n\nconst keys = await EccKeys.create()\n// or: const keys = await RsaKeys.create()\n\n// This will decrypt the message using our own public key\nconst decrypted = await keys.decrypt(encryptedMsg)\n```\n\n----------------------------------------------------------------------\n\n## examples\n\n### Create a new `Keys` instance\n\nUse the factory function `EccKeys.create` or `RsaKeys.create`. The optional parameters,\n`encryptionKeyName` and `signingKeyName`, are added as properties to the\n`keys` instance. These are used as indexes for saving the keys in `indexedDB`.\n\n**ECC:**\n```ts\nclass EccKeys {\n  static EXCHANGE_KEY_NAME:string = 'ecc-exchange'\n  static WRITE_KEY_NAME:string = 'ecc-write'\n\n  static async create (session?:boolean, extractable?:boolean):Promise\u003cEccKeys\u003e\n}\n```\n\n**RSA:**\n```ts\nclass RsaKeys {\n  static EXCHANGE_KEY_NAME:string = 'rsa-exchange'\n  static WRITE_KEY_NAME:string = 'rsa-write'\n\n  static async create (session?:boolean, extractable?:boolean):Promise\u003cRsaKeys\u003e\n}\n```\n\n#### Parameters\n\n- `session` (optional, boolean): If `true`, keys are created in memory only and won't be saved to `indexedDB` even if `persist()` is called.\n- `extractable` (optional, boolean): If `true`, creates extractable keys that can be exported/read. Defaults to `false` for security.\n\n\u003e **⚠️ Security Note**: Set `extractable: true` only when you need to export private keys. Non-extractable keys (default) provide better security as the browser prevents the private key from being read, while still allowing use for cryptographic operations.\n\n#### `.create()` example\n\nUse the factory function b/c async.\n\n```js\nimport { EccKeys } from '@substrate-system/keys/ecc'\n// or: import { RsaKeys } from '@substrate-system/keys/rsa'\n\n// Create non-extractable keys (recommended)\nconst keys = await EccKeys.create()\n\n// Create extractable keys (only when export is needed)\nconst extractableKeys = await EccKeys.create(false, true)\n\n// Create session-only, extractable keys\nconst sessionKeys = await EccKeys.create(true, true)\n```\n\n### Get a hash of the DID\nGet a 32-character, DNS-friendly string of the hash of the given `DID`.\nAvailable as static or instance method. If called as an instance method,\nthis will use the `DID` assigned to the given `Keys` instance.\n\nThe static method requires a `DID` string to be passed in.\n\n#### static method\n\n```ts\nclass EccKeys {  // or RsaKeys\n  static async deviceName (did:DID):Promise\u003cstring\u003e\n}\n```\n\n#### instance method\n\nIf used as an instance method, this will use the `DID` assigned to the instance.\n\n```ts\nclass EccKeys {  // or RsaKeys\n  async getDeviceName ():Promise\u003cstring\u003e\n}\n```\n\n### Persist the keys\nSave the keys to `indexedDB`. This depends on the values of the static class\nproperties `EXCHANGE_KEY_NAME` and `WRITE_KEY_NAME`.\nSet them if you want to change the indexes under which the keys are\nsaved to `indexedDB`.\n\nBy default we use these:\n- **ECC**: `'ecc-exchange'` and `'ecc-write'`\n- **RSA**: `'rsa-exchange'` and `'rsa-write'`\n\n#### `.persist`\n\n```ts\nclass EccKeys {  // or RsaKeys\n  async persist ():Promise\u003cvoid\u003e\n}\n```\n\n#### `.persist` example\n```js\nimport { EccKeys } from '@substrate-system/keys/ecc'\n\nconst keys = await EccKeys.create()\nEccKeys.EXCHANGE_KEY_NAME = 'encryption-key-custom-name'\nEccKeys.WRITE_KEY_NAME = 'signing-key-custom-name'\nawait keys.persist()\n```\n\n### Restore from indexedDB\nCreate a `Keys` instance from data saved to `indexedDB`. Pass in different\n`indexedDB` key names for the keys if you need to.\n\n#### `static .load`\n```ts\nclass EccKeys {  // or RsaKeys\n    static async load (opts?:{\n      encryptionKeyName?:string,\n      signingKeyName?:string,\n      session?:boolean,\n      extractable?:boolean,\n    }):Promise\u003cEccKeys\u003e\n}\n```\n\n#### Parameters\n\n- `encryptionKeyName` (optional, string): Custom name for the encryption key in `indexedDB`\n- `signingKeyName` (optional, string): Custom name for the signing key in `indexedDB`\n- `session` (optional, boolean): If `true`, creates session-only keys if no keys exist in `indexedDB`\n- `extractable` (optional, boolean): If `true` and keys don't exist in `indexedDB`, new keys will be created as extractable. Defaults to `false`.\n\n#### example\n```js\nimport { EccKeys } from '@substrate-system/keys/ecc'\n// or: import { RsaKeys } from '@substrate-system/keys/rsa'\n\n// Load existing keys from indexedDB, or create new non-extractable ones\nconst newKeys = await EccKeys.load()\n\n// Load with custom options\nconst customKeys = await EccKeys.load({\n  encryptionKeyName: 'my-custom-encryption-key',\n  signingKeyName: 'my-custom-signing-key',\n  extractable: true  // If keys don't exist, create them as extractable\n})\n```\n\n\n### Sign something\nCreate a new signature for the given input.\n\n**ECC:**\n```ts\nasync sign (msg:Msg, _charsize?:CharSize):Promise\u003cUint8Array\u003e\n```\n\n**RSA:**\n```ts\nasync sign (\n  msg:Msg,\n  charsize:CharSize = DEFAULT_CHAR_SIZE\n):Promise\u003cUint8Array\u003e\n```\n\n#### example\n```js\nconst sig = await keys.sign('hello signatures')\n```\n\n### Get a signature as a string\n\n#### `keys.signAsString(msg)`\n\nSign a message and return the signature as a base64 encoded string.\n\n```ts\n{\n  async signAsString (msg:string, charsize?:CharSize):Promise\u003cstring\u003e\n}\n```\n\n```js\nconst sig = await keys.signAsString('hello string')\n// =\u003e ubW9PIjb360v...\n```\n\n#### Backward compatibility: `keys.sign.asString(msg)`\n\nFor backward compatibility, the `.asString` method is still available:\n\n```js\nconst sig = await keys.sign.asString('hello string')\n// =\u003e ubW9PIjb360v...\n```\n\n### Verify a signature\nCheck if a given signature is valid. This is exposed as a stateless function so\nthat it can be used independently from any keypairs. You need to pass in the\ndata that was signed, the signature, and the `DID` string of the public key used\nto create the signature.\n\nThis works the same for either RSA or ECC keys.\n\n```ts\nasync function verify (\n    msg:string|Uint8Array,\n    sig:string|Uint8Array,\n    signingDid:DID\n):Promise\u003cboolean\u003e\n```\n\n**RSA verification uses RSA-PSS with SHA-256:**\n\n```js\nimport { verify } from '@substrate-system/keys/rsa'\n\nconst isOk = await verify('hello string', sig, keys.DID)\n```\n\n**ECC verification uses Ed25519:**\n\n```js\nimport { verify } from '@substrate-system/keys/ecc'\n\nconst isOk = await verify('hello string', sig, keys.DID)\n```\n\n### Encrypt a key\n\nUse asymmetric (RSA) encryption to encrypt an AES key to the given public key.\n\n```ts\nasync function encryptKeyTo ({ key, publicKey }:{\n    key:string|Uint8Array|CryptoKey;\n    publicKey:CryptoKey|Uint8Array|string;\n}, format?:'uint8array'|'arraybuffer'):Promise\u003cUint8Array|ArrayBuffer\u003e\n```\n\n#### example\n```js\nimport { encryptKeyTo } from '@substrate-system/keys/rsa'\n\n// pass in a CryptoKey\nconst encrypted = await encryptKeyTo({\n    key: myAesKey,\n    publicKey: keys.publicExchangeKey\n})\n\n// pass in a base64 string\nconst encryptedTwo = await encryptKeyTo({\n  key: aesKey,\n  publicKey: await keys.publicExchangeKeyAsString()\n})  // =\u003e Uint8Array\n```\n\n#### encrypt a key, return a string\n\nEncrypt the given key to the public key, and return the result as a\nbase64 string.\n\n\u003e !NOTE\n\u003e This is only relevant for RSA keys\n\n```ts\nimport { encryptKeyTo } from '@substrate-system/keys/rsa'\n\nencryptKeyTo.asString = async function ({ key, publicKey }:{\n    key:string|Uint8Array|CryptoKey;\n    publicKey:CryptoKey|string|Uint8Array;\n}, format?:SupportedEncodings):Promise\u003cstring\u003e {\n```\n\n#### format\n`encryptKeyTo.asString` takes an optional second argument for\n[the format](https://github.com/achingbrain/uint8arrays/blob/26684d4fa1a78f3e5c16e74bf13192e881db4fcf/src/util/bases.ts#L46)\nof the returned string.\nFormat is anything supported by [uint8arrays](https://github.com/achingbrain/uint8arrays).\nBy default, if omitted, it is `base64`.\n\n\n### Asymmetrically encrypt some arbitrary data\n\nEncrypt the given message to the given public key. If an AES key is not\nprovided, one will be created. Use the AES key to encrypt the given\ncontent, then encrypt the AES key to the given public key.\n\n\u003e !NOTE\n\u003e This is only relevant for RSA keys.\n\u003e If using ECC keys, a symmetric key is automatically generated\n\u003e via diffie-hellman.\n\nThe return value is an ArrayBuffer containing the encrypted AES key +\nthe `iv` + the encrypted content if using RSA. It is `salt` + `iv` + cipher text\nif using ECC.\n\nTo decrypt, pass the returned value to `keys.decrypt`, where `keys` is an\ninstance with the corresponding private key.\n\n```ts\nasync function encryptTo (\n    opts:{\n        content:string|Uint8Array;\n        publicKey:CryptoKey|string;\n    },\n    aesKey?:SymmKey|Uint8Array|string,\n):Promise\u003cArrayBuffer\u003e\n```\n\n#### example\n```js\nimport { encryptTo } from '@substrate-system/keys/rsa'\n\nconst encrypted = await encryptTo({\n    content: 'hello encryption',\n    publicKey: keys.publicExchangeKey\n})\n\n// =\u003e ArrayBuffer\n```\n\n### Asymmetrically encrypt a string, return a new string\n\nEncrypt the given string, and return a new string that is the (encrypted) AES\nkey concatenated with the `iv` and cipher text. The\ncorresponding method `keys.decryptAsString` will know how to parse and\ndecrypt the resulting text.\n\nUse the functions `encryptTo.asString` and `keys.decryptAsString`.\n\n#### `keys.decryptAsString`\n\n**ECC:**\n```ts\nasync decryptAsString (\n  msg:string|Uint8Array|ArrayBuffer,\n  publicKey?:CryptoKey|string,\n  aesAlgorithm?:string,\n  info?:string,\n):Promise\u003cstring\u003e\n```\n\n**RSA:**\n```ts\nasync decryptAsString (\n  msg:string|Uint8Array|ArrayBuffer,\n  keysize?:CryptoKey|string|SymmKeyLength,\n  _aesAlgorithm?:string,\n):Promise\u003cstring\u003e\n```\n\n##### example\n\n```js\nimport { RsaKeys, encryptTo } from '@substrate-system/keys/rsa'  // RSA example\n// or: import { EccKeys } from '@substrate-system/keys/ecc'\n\nconst keys = await RsaKeys.create()\n// or: const keys = await EccKeys.create()\nconst pubKey = await keys.publicExchangeKeyAsString()  // Both ECC and RSA\nconst msg = { type: 'test', content: 'hello' }\nconst cipherText = await encryptTo.asString({\n    content: JSON.stringify(msg),\n    // pass in a string public key or crypto key or Uint8Array\n    publicKey: pubKey\n})  // =\u003e string\n\nconst text = await keys.decryptAsString(cipherText)\nconst data = JSON.parse(text)\n// =\u003e { type: 'test', content: 'hello' }\n```\n\n### Decrypt a message\n\n**ECC:**\n```ts\nasync decrypt (\n  msg:string|Uint8Array|ArrayBuffer,\n  publicKey?:CryptoKey|string,\n  aesAlgorithm?:string,\n  info?:string,\n):Promise\u003cArrayBuffer\u003e\n```\n\n\u003e !NOTE\n\u003e ECC keys will use our own public key if it is not passed in.\n\n**RSA:**\n```ts\nasync decrypt (\n  msg:string|Uint8Array|ArrayBuffer,\n  keysize?:CryptoKey|string|SymmKeyLength,\n  _aesAlgorithm?:string,\n):Promise\u003cUint8Array\u003e\n```\n\n```js\nconst decrypted = await keys.decrypt(encrypted)\n// =\u003e ArrayBuffer (ECC) or Uint8Array (RSA)\n```\n\n### Backward compatibility: `.decrypt.asString`\nDecrypt a message, and stringify the result.\n\n```js\nawait keys.decrypt.asString(encryptedString)\n// =\u003e 'hello encryption'\n```\n\n### In memory only\nCreate a keypair, but do not save it in `indexedDB`, even if you call `persist`.\nPass `true` as the session parameter to `.create` or pass `{ session: true }` to `.load`.\n\n```js\nimport { EccKeys } from '@substrate-system/keys/ecc'\n// or: import { RsaKeys } from '@substrate-system/keys/rsa'\n\nconst keys = await EccKeys.create(true)\n// or: const keys = await RsaKeys.create(true)\n\n// or pass it to `.load`\nconst keysTwo = await EccKeys.load({ session: true })\n// or: const keysTwo = await RsaKeys.load({ session: true })\n```\n\n## AES\nExpose several AES functions with nice defaults.\n\n* algorithm: `AES-GCM`\n* key size: `256`\n* `iv` size: [`12` bytes](https://crypto.stackexchange.com/questions/41601/aes-gcm-recommended-iv-size-why-12-bytes) (96 bits)\n\n```js\nimport { AES } from '@substrate-system/keys/aes'\n\nconst key = await AES.create(/* ... optional arguments ... */)\n```\n\n### `create`\nCreate a new AES key. By default uses 256 bits \u0026 GCM algorithm.\n\n```ts\nfunction create (opts:{ alg:string, length:number } = {\n    alg: DEFAULT_SYMM_ALGORITHM,  // AES-GCM\n    length: DEFAULT_SYMM_LENGTH  // 256\n}):Promise\u003cCryptoKey\u003e\n```\n\n```ts\nimport { AES } from '@substrate-system/keys/aes'\nconst aesKey = await AES.create()\n```\n\n### `export`\nGet the AES key as a `Uint8Array`.\n\n```ts\n  async function export (key:CryptoKey):Promise\u003cUint8Array\u003e\n```\n\n```js\nimport { AES } from '@substrate-system/keys/aes'\nconst exported = await AES.export(aesKey)\n```\n\n### `exportAsString`\nGet the key as a string, `base64` encoded.\n\n```ts\nasync function asString (\n  key:CryptoKey,\n  format?:SupportedEncoding\n):Promise\u003cstring\u003e\n```\n\n```js\nimport { AES } from '@substrate-system/keys/aes'\nconst exported = await AES.export.asString(aesKey)\n```\n\n### `AES.encrypt`\n\nTake a `Uint8Array`, return an encrypted `Uint8Array`.\n\n```ts\nasync function encrypt (\n  data:Uint8Array,\n  cryptoKey:CryptoKey|Uint8Array,\n  iv?:Uint8Array\n):Promise\u003cUint8Array\u003e\n```\n\n```js\nimport { AES } from '@substrate-system/keys/aes'\nimport { fromString } from 'uint8arrays'\n\nconst encryptedText = await AES.encrypt(fromString('hello AES'), aesKey)\n```\n\n### `AES.decrypt`\n```ts\nasync function decrypt (\n  encryptedData:Uint8Array|string,\n  cryptoKey:CryptoKey|Uint8Array|ArrayBuffer,\n  iv?:Uint8Array\n):Promise\u003cUint8Array\u003e\n```\n\n```js\nimport { AES } from '@substrate-system/keys/aes'\n\nconst decryptedText = await AES.decrypt(encryptedText, aesKey)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsubstrate-system%2Fkeys","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsubstrate-system%2Fkeys","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsubstrate-system%2Fkeys/lists"}