Add comprehensive installation and setup documentation

- Add GETTING_STARTED.md with quick start guide and development modes
- Add INSTALL.sh automated installation script
- Add INSTALLATION_CHECKLIST.md, INSTALLATION_SUCCESS.md, and INSTALLATION_SUMMARY.md
- Add QUICK_REFERENCE.md for common commands
- Add SETUP_GUIDE.md with detailed setup instructions
- Update README.md with improved project overview
- Add did-wallet app dependencies and node_modules
This commit is contained in:
Dorian
2026-01-27 17:18:21 +00:00
parent a81f655133
commit 0d073fa89e
22658 changed files with 4494151 additions and 6 deletions
+201
View File
@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+695
View File
@@ -0,0 +1,695 @@
# Web5 Crypto API
| A cryptography and JOSE library for building secure Web5 applications |
| --------------------------------------------------------------------- |
[![NPM Package][crypto-npm-badge]][crypto-npm-link]
[![NPM Downloads][crypto-downloads-badge]][crypto-npm-link]
[![Build Status][crypto-build-badge]][crypto-build-link]
[![Open Issues][crypto-issues-badge]][crypto-issues-link]
[![Code Coverage][crypto-coverage-badge]][crypto-coverage-link]
---
- [Introduction](#introduction)
- [Supported Algorithms & Key Types](#supported-algorithms--key-types)
- [Extensions](#extensions)
- [Getting Started](#getting-started)
- [Node.js](#nodejs)
- [Web Browsers](#web-browsers)
- [React Native](#react-native)
- [Contributing](#contributing)
- [Core Concepts](#usage)
- [Key URIs](#key-uris)
- [Using a Local KMS](#using-a-local-kms)
- [JSON Web Key (JWK)](#json-web-key-jwk)
- [Random Number Generation](#random-number-generation)
- [Customization](#customization)
- [Persistent Local KMS Key Store](#persistent-local-kms-key-store)
- [Cryptographic Primitives](#cryptographic-primitives)
---
<a id="introduction"></a>
The Web5 Crypto API is a core component of the [Web5 JS](https://github.com/TBD54566975/web5-js)
ecosystem, providing the cryptography and JSON Object Signing and Encryption (JOSE) capabilities
essential for building secure applications and services with Decentralized Identifiers
([DID](https://www.w3.org/TR/did-core/)) and Verifiable Credentials
([VC](https://w3c.github.io/vc-data-model/)).
This JavaScript library was designed for modern development runtimes, including Node.js, web
browsers, and React Native. It provides cryptographic functionality for cipher, hash, and signature
algorithms and basic JOSE support for JSON Web Key (JWK). Additionally, it includes the crypto
interfaces and local Key Management System (KMS) implementation that are used by
[other libraries](https://github.com/TBD54566975/web5-js) in this monorepo.
### Supported Algorithms & Key Types
The following algorithms and key types are currently supported, with plans to expand its offerings
as the library progresses towards a 1.0 release.
| Capability | Details |
| -------------- | ----------------------------------------------- |
| Cipher | AES-CTR, AES-GCM, XChaCha20, XChaCha20-Poly1305 |
| Signature | ECDSA, EdDSA |
| Hash | SHA-256 |
| Key Derivation | ConcatKDF, ECDH, PBKDF2 |
| ECC Curves | Ed25519, secp256k1, X25519 |
### Extensions
Packages that extend the functionality of the `@web5/crypto` library:
| Extension | Repository |
| ----------------- | ------------------------------------------------------ |
| AWS KMS extension | [TBD54566975/crypto-aws-kms][crypto-aws-kms-repo-link] |
## Getting Started
The Web5 Crypto API is distributed as `@web5/crypto` via [npmjs.com][crypto-npm-link],
[jsdelivr.com][crypto-jsdelivr-link], [unpkg.com][crypto-unpkg-link], and
[github.com][crypto-repo-link].
### Node.js
This library is designed and tested for the _active_ (`v20`) and _maintenance_
(`v18`) [LTS releases](https://nodejs.org/en/about/previous-releases) of Node.js
Install the latest version of `@web5/crypto` using `npm` or your preferred package manager:
```shell
npm install @web5/crypto
```
Example ESM import:
```js
import { Ed25519 } from "@web5/crypto";
```
Example CJS require:
```js
const { Ed25519 } = require("@web5/crypto");
```
### Web Browsers
A polyfilled distribution is published to [jsdelivr.com][crypto-jsdelivr-browser] and
[unpkg.com][crypto-unpkg-browser] that can imported in a module `<script>` tag:
```html
<!DOCTYPE html>
<html lang="en">
<body>
<script type="module">
// Example import from JSDELIVR
import { Ed25519 } from "https://cdn.jsdelivr.net/npm/@web5/crypto/dist/browser.mjs";
</script>
</body>
</html>
```
<a id="secure-context"></a>
> [!IMPORTANT]
> The `@web5/crypto` library depends on the
> [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in web browsers.
> Web Crypto is available in all modern browsers but is accessible only in a
> [secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).
>
> This means you will not be able to use many `@web5/crypto` features in a browser unless the page
> is served over `https://` or `wss://`. Locally-delivered resources such as those with
> `http://127.0.0.1`, `http://localhost`, or `http://*.localhost` URLs are also considered to have
> been delivered securely.
### React Native
For React Native, you may need a
[polyfill](https://github.com/LinusU/react-native-get-random-values) for `crypto.getRandomValues`.
```js
import "react-native-get-random-values";
```
## Contributing
We welcome you to join our open source community. Whether you're new to open source or a seasoned
contributor, there's a place for you here. From coding to documentation, every contribution matters.
Check out our [contribution guide][contributing-link] for ways to get started.
For help, discussion about best practices, or to chat with others building on Web5 join our
[Discord Server][discord-link]:
[![discord-badge]][discord-link]
Remember, contributing is not just about code; it's about building together. Join us in shaping the
future of the Web!
## Core Concepts
### Key URIs
One of the core design principles for the SDKs in the Web5 ecosystem is the protection of private
key material. Instead of directly handling sensitive key information, our SDKs interact with
cryptographic keys through Key Management Systems (KMS) referenced by a unique identifier called a
**Key URI**. This approach ensures that private keys remain secure, while still allowing for
versatile cryptographic functionalities.
Each KMS assigns a unique identifier to a key when it is created. This identifier can be used to
form a Uniform Resource Identifier ([URI](https://datatracker.ietf.org/doc/html/rfc3986)) by adding
a prefix. The following table shows the format of supported **Key URIs**:
| Prefix | Key URI Format |
| --------- | -------------------------- |
| `urn:jwk` | `urn:jwk:<jwk-thumbprint>` |
All cryptographic keys are represented in JSON Web Key
([JWK](https://datatracker.ietf.org/doc/html/rfc7517)) format and the `jwk-thumbprint`, a
[standardized](https://datatracker.ietf.org/doc/html/rfc7638), deterministic, and unique hash of the
key, acts as a fingerprint, enabling consistent key referencing across all Web5 libraries without
exposing private key information.
### Using a Local KMS
This library includes a self-contained Key Management System (KMS) implementation that supports
generating keys, hashing, and creating/verifying digital signatures. Cryptographic operations are
performed within the confines of the local environment, without relying on external services. This
KMS is designed to be used by browser-based web apps or when testing backend services that depend on
cloud-based services (e.g., AWS KMS). Extensions that support external KMS services are
[listed here](#extensions).
Start by instantiating a local KMS implementation of the `CryptoApi` interface:
```ts
import { LocalKeyManager } from "@web5/crypto";
const kms = new LocalKeyManager();
```
An ephemeral, in-memory key store is used by default but any persistent store that implements the
[`KeyValueStore`](https://github.com/TBD54566975/web5-js/blob/5f364bc0d859e28f1388524ebe8ef152a71727c4/packages/common/src/types.ts#L4-L43)
interface can also be passed. See the [Persistent Key Store](#persistent-key-store) customization
for an example.
Generate a random private key:
```ts
const privateKeyUri = await kms.generateKey({ algorithm: "Ed25519" });
console.log(privateKeyUri);
// Output: urn:jwk:8DaTzHZcvQXUVvl8ezQKgGQHza1hiOZlPkdrB55Vt6Q
```
Create an EdDSA signature over arbitrary data using the private key:
```ts
const data = new TextEncoder().encode("Message");
const signature = await kms.sign({
keyUri: privateKeyUri,
data,
});
console.log(signature);
// Output:
// Uint8Array(64) [
// 208, 172, 103, 148, 119, 138, 101, 95, 41, 218, 64,
// 178, 132, 102, 15, 126, 102, 85, 3, 174, 96, 140,
// 203, 58, 186, 72, 85, 64, 15, 250, 235, 12, 97,
// 247, 52, 31, 110, 58, 85, 191, 161, 253, 82, 4,
// 1, 4, 230, 135, 81, 145, 59, 128, 83, 106, 105,
// 135, 32, 124, 96, 0, 25, 41, 218, 75
// ]
```
Get the public key in JWK format:
```ts
const publicKey = await kms.getPublicKey({ keyUri: privateKeyUri });
console.log(publicKey);
// Output:
// {
// kty: "OKP",
// crv: "Ed25519",
// alg: "EdDSA",
// kid: "8DaTzHZcvQXUVvl8ezQKgGQHza1hiOZlPkdrB55Vt6Q",
// x: "6alAHg28tLuqWtaj0YOg7d5ySM4ERwPqQrLoy2pwdZk"
// }
```
Verify the signature using the public key:
```ts
const isValid = await kms.verify({
key: publicKey,
signature,
data,
});
console.log(isValid);
// Output: true
```
Export the private key:
```ts
const privateKey = await kms.exportKey({ keyUri });
console.log(privateKey);
// Output:
// {
// kty: "OKP",
// crv: "Ed25519",
// alg: "EdDSA",
// kid: "8DaTzHZcvQXUVvl8ezQKgGQHza1hiOZlPkdrB55Vt6Q",
// x: "6alAHg28tLuqWtaj0YOg7d5ySM4ERwPqQrLoy2pwdZk",
// d: "0xLuQyXFaWjrqp2o0orhwvwhtYhp2Z7KeRcioIs78CY"
// }
```
Import a private key generated by another library:
```ts
import type { Jwk } from "@web5/crypto";
const privateKey: Jwk = {
kty: "OKP",
crv: "Ed25519",
x: "0thnrEFw6MVSs1XFgd4OD-Yn05XGQv24hvskmGajtKQ",
d: "0xLuQyXFaWjrqp2o0orhwvwhtYhp2Z7KeRcioIs78CY",
};
const keyUri = await kms.importKey({ key: privateKey });
```
Compute the hash digest of arbitrary data:
```ts
const data = new TextEncoder().encode("Message");
const hash = await kms.digest({ algorithm: "SHA-256", data });
console.log(hash);
// Output:
// Uint8Array(32) [
// 8, 187, 94, 93, 110, 170, 193, 4,
// 158, 222, 8, 147, 211, 14, 208, 34,
// 177, 164, 217, 181, 180, 141, 180, 20,
// 135, 31, 81, 201, 203, 53, 40, 61
// ]
```
### JSON Web Key (JWK)
A JSON Web Key (JWK) is a [standardized](https://datatracker.ietf.org/doc/html/rfc7517) format for
representing cryptographic keys in a JSON data structure. The JWK format is used by all
[Web5 SDKs](https://github.com/TBD54566975/sdk-development) to promote portability and
interoperability.
Defining a JWK:
```ts
import type { Jwk } from "@web5/crypto";
const publicKey: Jwk = {
kty: "OKP",
crv: "Ed25519",
x: "KsZRg2-gm9MoSrZqN9aSHUv-zYW8ajgyCfKxLGWJ2DI",
};
```
Computing the [thumbprint](https://datatracker.ietf.org/doc/html/rfc7638) of a JWK outputs a value
that can be used as a unique key identifier (`kid`) or to securely compare JWKs to determine if they
are equivalent:
```ts
import { computeJwkThumbprint } from "@web5/crypto";
const thumbprint = await computeJwkThumbprint({ jwk: publicKey });
console.log(thumbprint);
// Output: VhWyK5rpk2u_51_KniJxjRhwTUOsL8BLuKJaqpNYuEA
```
The provided type guard functions can be used for type narrowing or to perform runtime verification
of a specific JWK key type:
```ts
isPublicJwk(publicKey); // true
isPrivateJwk(publicKey); // false
isOkpPublicJwk(publicKey); // true
isOkpPrivateJwk(publicKey); // false
isOctPrivateJwk(publicKey); // false
isEcPublicJwk(publicKey); // false
isEcPrivateJwk(publicKey); // false
```
### Random Number Generation
Cryptographically strong random number generation is vital in cryptography. The unpredictability of
these random numbers is crucial for creating secure cryptographic keys, initialization vectors, and
nonces (numbers used once). Their strength lies in their resistance to being guessed or replicated,
making them foundational to maintaining the integrity and confidentiality of cryptographic systems.
The Web5 Crypto API includes two utility functions for random number generation:
#### `randomBytes()`
The `randomBytes()` method generates cryptographically strong random values (CSPRNG) of the
specified length. The implementation relies on
[`crypto.getRandomValues`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues),
which defers to the runtime (browser, Node.js, etc.) for entropy. The pseudo-random number
generator algorithm may vary across runtimes, but is suitable for generating initialization vectors,
nonces and other random values.
> [!IMPORTANT]
> Use a cipher algorithm's `generateKey()` method to generate encryption keys rather than
> `randomBytes()`. This ensures that secrets used for encryption are guaranteed to be generated in a
> [secure context](#secure-context) and
> that the runtime uses the best
> [source of entropy](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#usage_notes)
> available.
```typescript
import { randomBytes } from "@web5/crypto/utils";
const nonce = randomBytes(24);
```
#### `randomUuid()`
The `randomUuid()` method generates a UUID (Universally Unique Identifier) using a cryptographically
strong random number generator (CSPRNG) following the version 4 format, as specified in
[RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122).
UUIDs are of a fixed size (128 bits), can guarantee uniqueness across space and time, and can be
generated without a centralized authority to administer them. Since UUIDs are unique and persistent,
they make excellent Uniform Resource Names ([URN](https://datatracker.ietf.org/doc/html/rfc2141)).
The following is an example of the string representation of a UUID as a URN:
`urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6`.
> [!NOTE]
> This function is available only in [secure contexts](#secure-context) (HTTPS and localhost).
```typescript
import { randomUuid } from "@web5/crypto/utils";
const uuid = randomUuid();
```
## Customization
### Persistent Local KMS Key Store
By default, `LocalKeyManager` uses an in-memory key store to simplify prototyping and testing.
To persist keys that are generated or imported, an implementation of the
[`KeyValueStore`](https://github.com/TBD54566975/web5-js/blob/5f364bc0d859e28f1388524ebe8ef152a71727c4/packages/common/src/types.ts#L4-L43)
interface can be passed.
For example, to use the [LevelDB](https://github.com/Level/level)-backed store from `@web5/common`:
```ts
import type { KeyIdentifier, Jwk } from "@web5/crypto";
import { Level } from "level";
import { LevelStore } from "@web5/common";
const db = new Level<KeyIdentifier, Jwk>("db_location", {
valueEncoding: "json",
});
const keyStore = new LevelStore<KeyIdentifier, Jwk>({ db });
const kms = new LocalKeyManager({ keyStore });
```
## Cryptographic Primitives
This library encourages using its capabilities through concrete implementations of the `CryptoApi`
interface (e.g., [`LocalKeyManager`](#using-a-local-kms) or
[`AwsKeyManager`][crypto-aws-kms-repo-link]). These implementations provides high-level,
user-friendly access to a range of cryptographic functions. However, for developers requiring
lower-level control or specific customizations, the library also exposes its cryptographic
primitives directly. These primitives include a variety of cipher, hash, signature, key derivation,
and key conversion algorithms for advanced use cases.
> [!WARNING]
> While `@web5/crypto` offers low-level cryptographic primitives, it's crucial to acknowledge the
> complexity and potential risks associated with their use. Secure key management and security
> system design are highly specialized fields, often requiring expert knowledge. Even with correct
> usage of cryptographic functions, designing a secure system poses significant challenges.
>
> It's important to approach the creation of secure systems with caution, seeking expert review and
> continual learning to ensure effectiveness and security. [Crypto 101](https://www.crypto101.io) is
> an introductory course on cryptography to _begin_ your learning journey, freely available for
> developers of all skill levels.
#### AES-CTR
```ts
import { AesCtr, utils } from "@web5/crypto";
// Key Generation
const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
const privateKey = await AesCtr.generateKey({ length });
// Encryption
const data = new TextEncoder().encode("Message");
const counter = utils.randomBytes(16); // Initial value of the counter block
const encryptedData = await AesCtr.encrypt({
data,
counter,
key: privateKey,
length: 64, // Length of the counter in bits
});
// Decryption
const decryptedData = await AesCtr.decrypt({
data: encryptedData,
counter,
key: privateKey,
length: 64, // Length of the counter in bits
});
```
#### AES-GCM
```ts
import { AesGcm, utils } from "@web5/crypto";
// Key Generation
const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
const privateKey = await AesGcm.generateKey({ length });
// Encryption
const data = new TextEncoder().encode("Message");
const iv = utils.randomBytes(12); // Initialization vector
const encryptedData = await AesGcm.encrypt({
data,
iv,
key: privateKey,
});
// Decryption
const decryptedData = await AesGcm.decrypt({
data: encryptedData,
iv,
key: privateKey,
});
```
#### ConcatKDF
```ts
import { ConcatKdf, utils } from "@web5/crypto";
// Key Derivation
const derivedKeyingMaterial = await ConcatKdf.deriveKey({
sharedSecret: utils.randomBytes(32),
keyDataLen: 128,
otherInfo: {
algorithmId: "A128GCM",
partyUInfo: "Alice",
partyVInfo: "Bob",
suppPubInfo: 128,
},
});
```
#### Ed25519
```ts
import { Ed25519 } from "@web5/crypto";
// Key Generation
const privateKey = await Ed25519.generateKey();
// Public Key Derivation
const publicKey = await Ed25519.computePublicKey({ key: privateKey });
// EdDSA Signing
const signature = await Ed25519.sign({
key: privateKey,
data: new TextEncoder().encode("Message"),
});
// EdDSA Signature Verification
const isValid = await Ed25519.verify({
key: publicKey,
signature: signature,
data: new TextEncoder().encode("Message"),
});
```
#### PBKDF2
```ts
import { Pbkdf2, utils } from "@web5/crypto";
// Key Derivation
const derivedKey = await Pbkdf2.deriveKey({
hash: "SHA-256", // Hash function to use ('SHA-256', 'SHA-384', 'SHA-512')
password: new TextEncoder().encode("password"), // Password as a Uint8Array
salt: utils.randomBytes(16), // Salt value
iterations: 1000, // Number of iterations
length: 256, // Length of the derived key in bits
});
```
#### secp256k1
```ts
import { Secp256k1 } from "@web5/crypto";
// Key Generation
const privateKey = await Secp256k1.generateKey();
// Public Key Derivation
const publicKey = await Secp256k1.computePublicKey({ key: privateKey });
// ECDH Shared Secret Computation
const sharedSecret = await Secp256k1.sharedSecret({
privateKeyA: privateKey,
publicKeyB: anotherPublicKey,
});
// ECDSA Signing
const signature = await Secp256k1.sign({
key: privateKey,
data: new TextEncoder().encode("Message"),
});
// ECDSA Signature Verification
const isValid = await Secp256k1.verify({
key: publicKey,
signature: signature,
data: new TextEncoder().encode("Message"),
});
```
#### SHA-256
```ts
import { Sha256 } from "@web5/crypto";
// Hashing
const data = new TextEncoder().encode("Message");
const hash = await Sha256.digest({ data });
```
#### X25519
```ts
import { X25519 } from "@web5/crypto";
// Key Generation
const privateKey = await X25519.generateKey();
// Public Key Derivation
const publicKey = await X25519.computePublicKey({ key: privateKey });
// ECDH Shared Secret Computation
const sharedSecret = await X25519.sharedSecret({
privateKeyA: privateKey,
publicKeyB: anotherPublicKey,
});
```
#### XChaCha20
```ts
import { XChaCha20, utils } from "@web5/crypto";
// Key Generation
const privateKey = await XChaCha20.generateKey();
// Encryption
const data = new TextEncoder().encode("Message");
const nonce = utils.randomBytes(24);
const encryptedData = await XChaCha20.encrypt({
data,
nonce,
key: privateKey,
});
// Decryption
const decryptedData = await XChaCha20.decrypt({
data: encryptedData,
nonce,
key: privateKey,
});
```
#### XChaCha20-Poly1305
```ts
import { XChaCha20Poly1305, utils } from "@web5/crypto";
// Key Generation
const privateKey = await XChaCha20Poly1305.generateKey();
// Encryption
const data = new TextEncoder().encode("Message");
const nonce = utils.randomBytes(24);
const additionalData = new TextEncoder().encode("Associated data");
const { ciphertext, tag } = await XChaCha20Poly1305.encrypt({
data,
nonce,
additionalData,
key: privateKey,
});
// Decryption
const decryptedData = await XChaCha20Poly1305.decrypt({
data: ciphertext,
nonce,
tag,
additionalData,
key: privateKey,
});
```
## Project Resources
| Resource | Description |
| --------------------------------------- | ----------------------------------------------------------------------------- |
| [CODEOWNERS][codeowners-link] | Outlines the project lead(s) |
| [CODE OF CONDUCT][code-of-conduct-link] | Expected behavior for project contributors, promoting a welcoming environment |
| [CONTRIBUTING][contributing-link] | Developer guide to build, test, run, access CI, chat, discuss, file issues |
| [GOVERNANCE][governance-link] | Project governance |
| [LICENSE][license-link] | Apache License, Version 2.0 |
[crypto-npm-badge]: https://img.shields.io/npm/v/@web5/crypto.svg?style=flat&color=blue&santize=true
[crypto-npm-link]: https://www.npmjs.com/package/@web5/crypto
[crypto-downloads-badge]: https://img.shields.io/npm/dt/@web5/crypto?&color=blue
[crypto-build-badge]: https://img.shields.io/github/actions/workflow/status/TBD54566975/web5-js/tests-ci.yml?branch=main&label=build
[crypto-build-link]: https://github.com/TBD54566975/web5-js/actions/workflows/tests-ci.yml
[crypto-coverage-badge]: https://img.shields.io/codecov/c/gh/TBD54566975/web5-js/main?style=flat&token=YI87CKF1LI
[crypto-coverage-link]: https://app.codecov.io/github/TBD54566975/web5-js/tree/main/packages%2Fcrypto
[crypto-issues-badge]: https://img.shields.io/github/issues/TBD54566975/web5-js/package:%20crypto?label=issues
[crypto-issues-link]: https://github.com/TBD54566975/web5-js/issues?q=is%3Aopen+is%3Aissue+label%3A"package%3A+crypto"
[crypto-aws-kms-repo-link]: https://github.com/TBD54566975/web5-js/tree/main/packages/crypto-aws-kms
[crypto-repo-link]: https://github.com/TBD54566975/web5-js/tree/main/packages/crypto
[crypto-jsdelivr-link]: https://www.jsdelivr.com/package/npm/@web5/crypto
[crypto-jsdelivr-browser]: https://cdn.jsdelivr.net/npm/@web5/crypto/dist/browser.mjs
[crypto-unpkg-link]: https://unpkg.com/@web5/crypto
[crypto-unpkg-browser]: https://unpkg.com/@web5/crypto/dist/browser.mjs
[codeowners-link]: https://github.com/TBD54566975/web5-js/blob/main/CODEOWNERS
[code-of-conduct-link]: https://github.com/TBD54566975/web5-js/blob/main/CODE_OF_CONDUCT.md
[contributing-link]: https://github.com/TBD54566975/web5-js/blob/main/CONTRIBUTING.md
[governance-link]: https://github.com/TBD54566975/web5-js/blob/main/GOVERNANCE.md
[license-link]: https://github.com/TBD54566975/web5-js/blob/main/LICENSE
[discord-badge]: https://img.shields.io/discord/937858703112155166?color=5865F2&logo=discord&logoColor=white
[discord-link]: https://discord.com/channels/937858703112155166/969272658501976117
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+188
View File
@@ -0,0 +1,188 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AesCtrAlgorithm = void 0;
var aes_ctr_js_1 = require("../primitives/aes-ctr.js");
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
/**
* The `AesCtrAlgorithm` class provides a concrete implementation for cryptographic operations using
* the AES algorithm in Counter (CTR) mode. This class implements both {@link Cipher | `Cipher`} and
* { @link KeyGenerator | `KeyGenerator`} interfaces, providing key generation, encryption, and
* decryption features.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var AesCtrAlgorithm = /** @class */ (function (_super) {
__extends(AesCtrAlgorithm, _super);
function AesCtrAlgorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Decrypts the provided data using AES-CTR.
*
* @remarks
* This method performs AES-CTR decryption on the given encrypted data using the specified key.
* Similar to the encryption process, it requires an initial counter block and the length
* of the counter block, along with the encrypted data and the decryption key. The method
* returns the decrypted data as a Uint8Array.
*
* @example
* ```ts
* const aesCtr = new AesCtrAlgorithm();
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block used during encryption
* const key = { ... }; // A Jwk object representing the same AES key used for encryption
* const decryptedData = await aesCtr.decrypt({
* data: encryptedData,
* counter,
* key,
* length: 128 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
AesCtrAlgorithm.prototype.decrypt = function (params) {
return __awaiter(this, void 0, void 0, function () {
var plaintext;
return __generator(this, function (_a) {
plaintext = aes_ctr_js_1.AesCtr.decrypt(params);
return [2 /*return*/, plaintext];
});
});
};
/**
* Encrypts the provided data using AES-CTR.
*
* @remarks
* This method performs AES-CTR encryption on the given data using the specified key.
* It requires the initial counter block and the length of the counter block, alongside
* the data and key. The method is designed to work asynchronously and returns the
* encrypted data as a Uint8Array.
*
* @example
* ```ts
* const aesCtr = new AesCtrAlgorithm();
* const data = new TextEncoder().encode('Messsage');
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block
* const key = { ... }; // A Jwk object representing an AES key
* const encryptedData = await aesCtr.encrypt({
* data,
* counter,
* key,
* length: 128 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
AesCtrAlgorithm.prototype.encrypt = function (params) {
return __awaiter(this, void 0, void 0, function () {
var ciphertext;
return __generator(this, function (_a) {
ciphertext = aes_ctr_js_1.AesCtr.encrypt(params);
return [2 /*return*/, ciphertext];
});
});
};
/**
* Generates a symmetric key for AES in Counter (CTR) mode in JSON Web Key (JWK) format.
*
* @remarks
* This method generates a symmetric AES key for use in CTR mode, based on the specified
* `algorithm` parameter which determines the key length. It uses cryptographically secure random
* number generation to ensure the uniqueness and security of the key. The key is returned in JWK
* format.
*
* The generated key includes the following components:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const aesCtr = new AesCtrAlgorithm();
* const privateKey = await aesCtr.generateKey({ algorithm: 'A256CTR' });
* ```
*
* @param params - The parameters for the key generation.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
AesCtrAlgorithm.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var length, privateKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
length = { A128CTR: 128, A192CTR: 192, A256CTR: 256 }[algorithm];
return [4 /*yield*/, aes_ctr_js_1.AesCtr.generateKey({ length: length })];
case 1:
privateKey = _b.sent();
// Set the `alg` property based on the specified algorithm.
privateKey.alg = algorithm;
return [2 /*return*/, privateKey];
}
});
});
};
return AesCtrAlgorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.AesCtrAlgorithm = AesCtrAlgorithm;
//# sourceMappingURL=aes-ctr.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-ctr.js","sourceRoot":"","sources":["../../../src/algorithms/aes-ctr.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,uDAAkD;AAClD,6DAAwD;AA4BxD;;;;;;;;GAQG;AACH;IAAqC,mCAAe;IAApD;;IAgHA,CAAC;IA5GC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACU,iCAAO,GAApB,UAAqB,MACS;;;;gBAEtB,SAAS,GAAG,mBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAEzC,sBAAO,SAAS,EAAC;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACU,iCAAO,GAApB,UAAqB,MACS;;;;gBAEtB,UAAU,GAAG,mBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE1C,sBAAO,UAAU,EAAC;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACU,qCAAW,GAAxB,UAAyB,EACA;YADE,SAAS,eAAA;;;;;;wBAI5B,MAAM,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAoB,CAAC;wBAGvE,qBAAM,mBAAM,CAAC,WAAW,CAAC,EAAE,MAAM,QAAA,EAAE,CAAC,EAAA;;wBAAjD,UAAU,GAAG,SAAoC;wBAEvD,2DAA2D;wBAC3D,UAAU,CAAC,GAAG,GAAG,SAAS,CAAC;wBAE3B,sBAAO,UAAU,EAAC;;;;KACnB;IACH,sBAAC;AAAD,CAAC,AAhHD,CAAqC,qCAAe,GAgHnD;AAhHY,0CAAe"}
+196
View File
@@ -0,0 +1,196 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AesGcmAlgorithm = void 0;
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
var aes_gcm_js_1 = require("../primitives/aes-gcm.js");
/**
* The `AesGcmAlgorithm` class provides a concrete implementation for cryptographic operations using
* the AES algorithm in Galois/Counter Mode (GCM). This class implements both
* {@link Cipher | `Cipher`} and { @link KeyGenerator | `KeyGenerator`} interfaces, providing
* key generation, encryption, and decryption features.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var AesGcmAlgorithm = /** @class */ (function (_super) {
__extends(AesGcmAlgorithm, _super);
function AesGcmAlgorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Decrypts the provided data using AES-GCM.
*
* @remarks
* This method performs AES-GCM decryption on the given encrypted data using the specified key.
* It requires an initialization vector (IV), the encrypted data along with the decryption key,
* and optionally, additional authenticated data (AAD). The method returns the decrypted data as a
* Uint8Array. The optional `tagLength` parameter specifies the size in bits of the authentication
* tag used when encrypting the data. If not specified, the default tag length of 128 bits is
* used.
*
* @example
* ```ts
* const aesGcm = new AesGcmAlgorithm();
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const iv = new Uint8Array([...]); // Initialization vector used during encryption
* const additionalData = new Uint8Array([...]); // Optional additional authenticated data
* const key = { ... }; // A Jwk object representing the AES key
* const decryptedData = await aesGcm.decrypt({
* data: encryptedData,
* iv,
* additionalData,
* key,
* tagLength: 128 // Optional tag length in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
AesGcmAlgorithm.prototype.decrypt = function (params) {
return __awaiter(this, void 0, void 0, function () {
var plaintext;
return __generator(this, function (_a) {
plaintext = aes_gcm_js_1.AesGcm.decrypt(params);
return [2 /*return*/, plaintext];
});
});
};
/**
* Encrypts the provided data using AES-GCM.
*
* @remarks
* This method performs AES-GCM encryption on the given data using the specified key.
* It requires an initialization vector (IV), the encrypted data along with the decryption key,
* and optionally, additional authenticated data (AAD). The method returns the encrypted data as a
* Uint8Array. The optional `tagLength` parameter specifies the size in bits of the authentication
* tag generated in the encryption operation and used for authentication in the corresponding
* decryption. If not specified, the default tag length of 128 bits is used.
*
* @example
* ```ts
* const aesGcm = new AesGcmAlgorithm();
* const data = new TextEncoder().encode('Messsage');
* const iv = new Uint8Array([...]); // Initialization vector
* const additionalData = new Uint8Array([...]); // Optional additional authenticated data
* const key = { ... }; // A Jwk object representing an AES key
* const encryptedData = await aesGcm.encrypt({
* data,
* iv,
* additionalData,
* key,
* tagLength: 128 // Optional tag length in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
AesGcmAlgorithm.prototype.encrypt = function (params) {
return __awaiter(this, void 0, void 0, function () {
var ciphertext;
return __generator(this, function (_a) {
ciphertext = aes_gcm_js_1.AesGcm.encrypt(params);
return [2 /*return*/, ciphertext];
});
});
};
/**
* Generates a symmetric key for AES in Galois/Counter Mode (GCM) in JSON Web Key (JWK) format.
*
* @remarks
* This method generates a symmetric AES key for use in GCM mode, based on the specified
* `algorithm` parameter which determines the key length. It uses cryptographically secure random
* number generation to ensure the uniqueness and security of the key. The key is returned in JWK
* format.
*
* The generated key includes the following components:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const aesGcm = new AesGcmAlgorithm();
* const privateKey = await aesGcm.generateKey({ algorithm: 'A256GCM' });
* ```
*
* @param params - The parameters for the key generation.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
AesGcmAlgorithm.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var length, privateKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
length = { A128GCM: 128, A192GCM: 192, A256GCM: 256 }[algorithm];
return [4 /*yield*/, aes_gcm_js_1.AesGcm.generateKey({ length: length })];
case 1:
privateKey = _b.sent();
// Set the `alg` property based on the specified algorithm.
privateKey.alg = algorithm;
return [2 /*return*/, privateKey];
}
});
});
};
return AesGcmAlgorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.AesGcmAlgorithm = AesGcmAlgorithm;
//# sourceMappingURL=aes-gcm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-gcm.js","sourceRoot":"","sources":["../../../src/algorithms/aes-gcm.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,6DAAwD;AACxD,uDAAuE;AAmDvE;;;;;;;;GAQG;AACH;IAAqC,mCAAe;IAApD;;IAwHA,CAAC;IApHC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,iCAAO,GAApB,UAAqB,MACS;;;;gBAEtB,SAAS,GAAG,mBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAEzC,sBAAO,SAAS,EAAC;;;KAClB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,iCAAO,GAApB,UAAqB,MACS;;;;gBAEtB,UAAU,GAAG,mBAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE1C,sBAAO,UAAU,EAAC;;;KACnB;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACU,qCAAW,GAAxB,UAAyB,EACA;YADE,SAAS,eAAA;;;;;;wBAI5B,MAAM,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAoB,CAAC;wBAGvE,qBAAM,mBAAM,CAAC,WAAW,CAAC,EAAE,MAAM,QAAA,EAAE,CAAC,EAAA;;wBAAjD,UAAU,GAAG,SAAoC;wBAEvD,2DAA2D;wBAC3D,UAAU,CAAC,GAAG,GAAG,SAAS,CAAC;wBAE3B,sBAAO,UAAU,EAAC;;;;KACnB;IACH,sBAAC;AAAD,CAAC,AAxHD,CAAqC,qCAAe,GAwHnD;AAxHY,0CAAe"}
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CryptoAlgorithm = void 0;
/**
* Base class for all cryptographic algorithm implementations.
*/
var CryptoAlgorithm = /** @class */ (function () {
function CryptoAlgorithm() {
}
return CryptoAlgorithm;
}());
exports.CryptoAlgorithm = CryptoAlgorithm;
//# sourceMappingURL=crypto-algorithm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"crypto-algorithm.js","sourceRoot":"","sources":["../../../src/algorithms/crypto-algorithm.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACH;IAAA;IAAuC,CAAC;IAAD,sBAAC;AAAD,CAAC,AAAxC,IAAwC;AAAlB,0CAAe"}
+352
View File
@@ -0,0 +1,352 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EcdsaAlgorithm = void 0;
var secp256k1_js_1 = require("../primitives/secp256k1.js");
var secp256r1_js_1 = require("../primitives/secp256r1.js");
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `EcdsaAlgorithm` class provides a concrete implementation for cryptographic operations using
* the Elliptic Curve Digital Signature Algorithm (ECDSA). This class implements both
* {@link Signer | `Signer`} and { @link AsymmetricKeyGenerator | `AsymmetricKeyGenerator`}
* interfaces, providing private key generation, public key derivation, and creation/verification
* of signatures.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var EcdsaAlgorithm = /** @class */ (function (_super) {
__extends(EcdsaAlgorithm, _super);
function EcdsaAlgorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Derives the public key in JWK format from a given private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The process ensures that the derived public key correctly corresponds to
* the given private key.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await ecdsa.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
EcdsaAlgorithm.prototype.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var _b, publicKey, publicKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isEcPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
_b = key.crv;
switch (_b) {
case 'secp256k1': return [3 /*break*/, 1];
case 'P-256': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.computePublicKey({ key: key })];
case 2:
publicKey = _c.sent();
publicKey.alg = 'ES256K';
return [2 /*return*/, publicKey];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.computePublicKey({ key: key })];
case 4:
publicKey = _c.sent();
publicKey.alg = 'ES256';
return [2 /*return*/, publicKey];
case 5:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
/**
* Generates a new private key with the specified algorithm in JSON Web Key (JWK) format.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const privateKey = await ecdsa.generateKey({ algorithm: 'ES256K' });
* ```
*
* @param params - The parameters for key generation.
* @param params.algorithm - The algorithm to use for key generation.
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
EcdsaAlgorithm.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var _b, privateKey, privateKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_b = algorithm;
switch (_b) {
case 'ES256K': return [3 /*break*/, 1];
case 'secp256k1': return [3 /*break*/, 1];
case 'ES256': return [3 /*break*/, 3];
case 'secp256r1': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.generateKey()];
case 2:
privateKey = _c.sent();
privateKey.alg = 'ES256K';
return [2 /*return*/, privateKey];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.generateKey()];
case 4:
privateKey = _c.sent();
privateKey.alg = 'ES256';
return [2 /*return*/, privateKey];
case 5: return [2 /*return*/];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an ECDSA private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key.
*
* Note: This method offers a significant performance advantage, being about 200 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await ecdsa.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
EcdsaAlgorithm.prototype.getPublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var _b, publicKey, publicKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isEcPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
_b = key.crv;
switch (_b) {
case 'secp256k1': return [3 /*break*/, 1];
case 'P-256': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.getPublicKey({ key: key })];
case 2:
publicKey = _c.sent();
publicKey.alg = 'ES256K';
return [2 /*return*/, publicKey];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.getPublicKey({ key: key })];
case 4:
publicKey = _c.sent();
publicKey.alg = 'ES256';
return [2 /*return*/, publicKey];
case 5:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
/**
* Generates an ECDSA signature of given data using a private key.
*
* @remarks
* This method uses the signature algorithm determined by the given `algorithm` to sign the
* provided data.
*
* The signature can later be verified by parties with access to the corresponding
* public key, ensuring that the data has not been tampered with and was indeed signed by the
* holder of the private key.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const data = new TextEncoder().encode('Message');
* const privateKey = { ... }; // A Jwk object representing a private key
* const signature = await ecdsa.sign({
* key: privateKey,
* data
* });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign.
*
* @returns A Promise resolving to the digital signature as a `Uint8Array`.
*/
EcdsaAlgorithm.prototype.sign = function (_a) {
var key = _a.key, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isEcPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
_b = key.crv;
switch (_b) {
case 'secp256k1': return [3 /*break*/, 1];
case 'P-256': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.sign({ key: key, data: data })];
case 2: return [2 /*return*/, _c.sent()];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.sign({ key: key, data: data })];
case 4: return [2 /*return*/, _c.sent()];
case 5:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
/**
* Verifies an ECDSA signature associated with the provided data using the provided key.
*
* @remarks
* This method uses the signature algorithm determined by the `crv` property of the provided key
* to check the validity of a digital signature against the original data. It confirms whether the
* signature was created by the holder of the corresponding private key and that the data has not
* been tampered with.
*s
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const data = new TextEncoder().encode('Message');
* const isValid = await ecdsa.verify({
* key: publicKey,
* signature,
* data
* });
* ```
*
* @param params - The parameters for the verification operation.
* @param params.key - The key to use for verification.
* @param params.signature - The signature to verify.
* @param params.data - The data to verify.
*
* @returns A Promise resolving to a boolean indicating whether the signature is valid.
*/
EcdsaAlgorithm.prototype.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isEcPublicJwk)(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) public key.');
_b = key.crv;
switch (_b) {
case 'secp256k1': return [3 /*break*/, 1];
case 'P-256': return [3 /*break*/, 3];
}
return [3 /*break*/, 5];
case 1: return [4 /*yield*/, secp256k1_js_1.Secp256k1.verify({ key: key, signature: signature, data: data })];
case 2: return [2 /*return*/, _c.sent()];
case 3: return [4 /*yield*/, secp256r1_js_1.Secp256r1.verify({ key: key, signature: signature, data: data })];
case 4: return [2 /*return*/, _c.sent()];
case 5:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 6;
case 6: return [2 /*return*/];
}
});
});
};
return EcdsaAlgorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.EcdsaAlgorithm = EcdsaAlgorithm;
//# sourceMappingURL=ecdsa.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ecdsa.js","sourceRoot":"","sources":["../../../src/algorithms/ecdsa.ts"],"names":[],"mappings":"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"}
+325
View File
@@ -0,0 +1,325 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EdDsaAlgorithm = void 0;
var ed25519_js_1 = require("../primitives/ed25519.js");
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `EdDsaAlgorithm` class provides a concrete implementation for cryptographic operations using
* the Edwards-curve Digital Signature Algorithm (EdDSA). This class implements both
* {@link Signer | `Signer`} and { @link AsymmetricKeyGenerator | `AsymmetricKeyGenerator`}
* interfaces, providing private key generation, public key derivation, and creation/verification
* of signatures.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var EdDsaAlgorithm = /** @class */ (function (_super) {
__extends(EdDsaAlgorithm, _super);
function EdDsaAlgorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Derives the public key in JWK format from a given private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The process ensures that the derived public key correctly corresponds to
* the given private key.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await eddsa.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
EdDsaAlgorithm.prototype.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var _b, publicKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isOkpPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
_b = key.crv;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.computePublicKey({ key: key })];
case 2:
publicKey = _c.sent();
publicKey.alg = 'EdDSA';
return [2 /*return*/, publicKey];
case 3:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
/**
* Generates a new private key with the specified algorithm in JSON Web Key (JWK) format.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const privateKey = await eddsa.generateKey({ algorithm: 'Ed25519' });
* ```
*
* @param params - The parameters for key generation.
* @param params.algorithm - The algorithm to use for key generation.
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
EdDsaAlgorithm.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var _b, privateKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_b = algorithm;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.generateKey()];
case 2:
privateKey = _c.sent();
privateKey.alg = 'EdDSA';
return [2 /*return*/, privateKey];
case 3: return [2 /*return*/];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an EdDSA private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key.
*
* Note: This method offers a significant performance advantage, being about 100 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await eddsa.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
EdDsaAlgorithm.prototype.getPublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var _b, publicKey;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isOkpPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
_b = key.crv;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.getPublicKey({ key: key })];
case 2:
publicKey = _c.sent();
publicKey.alg = 'EdDSA';
return [2 /*return*/, publicKey];
case 3:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
/**
* Generates an EdDSA signature of given data using a private key.
*
* @remarks
* This method uses the signature algorithm determined by the given `algorithm` to sign the
* provided data.
*
* The signature can later be verified by parties with access to the corresponding
* public key, ensuring that the data has not been tampered with and was indeed signed by the
* holder of the private key.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const data = new TextEncoder().encode('Message');
* const privateKey = { ... }; // A Jwk object representing a private key
* const signature = await eddsa.sign({
* key: privateKey,
* data
* });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign.
*
* @returns A Promise resolving to the digital signature as a `Uint8Array`.
*/
EdDsaAlgorithm.prototype.sign = function (_a) {
var key = _a.key, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isOkpPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
_b = key.crv;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.sign({ key: key, data: data })];
case 2: return [2 /*return*/, _c.sent()];
case 3:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
/**
* Verifies an EdDSA signature associated with the provided data using the provided key.
*
* @remarks
* This method uses the signature algorithm determined by the `crv` property of the provided key
* to check the validity of a digital signature against the original data. It confirms whether the
* signature was created by the holder of the corresponding private key and that the data has not
* been tampered with.
*s
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const data = new TextEncoder().encode('Message');
* const isValid = await eddsa.verify({
* key: publicKey,
* signature,
* data
* });
* ```
*
* @param params - The parameters for the verification operation.
* @param params.key - The key to use for verification.
* @param params.signature - The signature to verify.
* @param params.data - The data to verify.
*
* @returns A Promise resolving to a boolean indicating whether the signature is valid.
*/
EdDsaAlgorithm.prototype.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if (!(0, jwk_js_1.isOkpPublicJwk)(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) public key.');
_b = key.crv;
switch (_b) {
case 'Ed25519': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, ed25519_js_1.Ed25519.verify({ key: key, signature: signature, data: data })];
case 2: return [2 /*return*/, _c.sent()];
case 3:
{
throw new Error("Unsupported curve: ".concat(key.crv));
}
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
};
return EdDsaAlgorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.EdDsaAlgorithm = EdDsaAlgorithm;
//# sourceMappingURL=eddsa.js.map
@@ -0,0 +1 @@
{"version":3,"file":"eddsa.js","sourceRoot":"","sources":["../../../src/algorithms/eddsa.ts"],"names":[],"mappings":"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"}
+119
View File
@@ -0,0 +1,119 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sha2Algorithm = void 0;
var sha256_js_1 = require("../primitives/sha256.js");
var crypto_algorithm_js_1 = require("./crypto-algorithm.js");
/**
* The `Sha2Algorithm` class is an implementation of the {@link Hasher | `Hasher`} interface for the
* SHA-2 family of cryptographic hash functions. The `digest` method takes the algorithm identifier
* of the hash function and arbitrary data as input and returns the hash digest of the data.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
var Sha2Algorithm = /** @class */ (function (_super) {
__extends(Sha2Algorithm, _super);
function Sha2Algorithm() {
return _super !== null && _super.apply(this, arguments) || this;
}
/**
* Generates a hash digest of the provided data.
*
* @remarks
* A digest is the output of the hash function. It's a fixed-size string of bytes
* that uniquely represents the data input into the hash function. The digest is often used for
* data integrity checks, as any alteration in the input data results in a significantly
* different digest.
*
* It takes the algorithm identifier of the hash function and data to digest as input and returns
* the digest of the data.
*
* @example
* ```ts
* const sha2 = new Sha2Algorithm();
* const data = new TextEncoder().encode('Messsage');
* const digest = await sha2.digest({ data });
* ```
*
* @param params - The parameters for the digest operation.
* @param params.algorithm - The name of hash function to use.
* @param params.data - The data to digest.
*
* @returns A Promise which will be fulfilled with the hash digest.
*/
Sha2Algorithm.prototype.digest = function (_a) {
var algorithm = _a.algorithm, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var _b, hash;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_b = algorithm;
switch (_b) {
case 'SHA-256': return [3 /*break*/, 1];
}
return [3 /*break*/, 3];
case 1: return [4 /*yield*/, sha256_js_1.Sha256.digest({ data: data })];
case 2:
hash = _c.sent();
return [2 /*return*/, hash];
case 3: return [2 /*return*/];
}
});
});
};
return Sha2Algorithm;
}(crypto_algorithm_js_1.CryptoAlgorithm));
exports.Sha2Algorithm = Sha2Algorithm;
//# sourceMappingURL=sha-2.js.map
@@ -0,0 +1 @@
{"version":3,"file":"sha-2.js","sourceRoot":"","sources":["../../../src/algorithms/sha-2.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,qDAAiD;AACjD,6DAAwD;AAcxD;;;;;;;GAOG;AACH;IAAmC,iCAAe;IAAlD;;IAsCA,CAAC;IAnCC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,8BAAM,GAAnB,UAAoB,EAAqC;YAAnC,SAAS,eAAA,EAAE,IAAI,UAAA;;;;;;wBAC3B,KAAA,SAAS,CAAA;;iCAEV,SAAS,CAAC,CAAV,wBAAS;;;4BACC,qBAAM,kBAAM,CAAC,MAAM,CAAC,EAAE,IAAI,MAAA,EAAE,CAAC,EAAA;;wBAApC,IAAI,GAAG,SAA6B;wBAC1C,sBAAO,IAAI,EAAC;;;;;KAIjB;IACH,oBAAC;AAAD,CAAC,AAtCD,CAAmC,qCAAe,GAsCjD;AAtCY,sCAAa"}
+54
View File
@@ -0,0 +1,54 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.utils = void 0;
__exportStar(require("./local-key-manager.js"), exports);
exports.utils = __importStar(require("./utils.js"));
__exportStar(require("./algorithms/aes-ctr.js"), exports);
__exportStar(require("./algorithms/aes-gcm.js"), exports);
__exportStar(require("./algorithms/crypto-algorithm.js"), exports);
__exportStar(require("./algorithms/ecdsa.js"), exports);
__exportStar(require("./algorithms/eddsa.js"), exports);
__exportStar(require("./algorithms/sha-2.js"), exports);
__exportStar(require("./jose/jwe.js"), exports);
__exportStar(require("./jose/jwk.js"), exports);
__exportStar(require("./jose/jws.js"), exports);
__exportStar(require("./jose/jwt.js"), exports);
__exportStar(require("./jose/utils.js"), exports);
__exportStar(require("./primitives/aes-ctr.js"), exports);
__exportStar(require("./primitives/aes-gcm.js"), exports);
__exportStar(require("./primitives/concat-kdf.js"), exports);
__exportStar(require("./primitives/ed25519.js"), exports);
__exportStar(require("./primitives/secp256r1.js"), exports);
__exportStar(require("./primitives/pbkdf2.js"), exports);
__exportStar(require("./primitives/secp256k1.js"), exports);
__exportStar(require("./primitives/sha256.js"), exports);
__exportStar(require("./primitives/x25519.js"), exports);
__exportStar(require("./primitives/xchacha20.js"), exports);
__exportStar(require("./primitives/xchacha20-poly1305.js"), exports);
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yDAAuC;AACvC,oDAAoC;AAEpC,0DAAwC;AACxC,0DAAwC;AACxC,mEAAiD;AACjD,wDAAsC;AACtC,wDAAsC;AACtC,wDAAsC;AAEtC,gDAA8B;AAC9B,gDAA8B;AAC9B,gDAA8B;AAC9B,gDAA8B;AAC9B,kDAAgC;AAEhC,0DAAwC;AACxC,0DAAwC;AACxC,6DAA2C;AAC3C,0DAAwC;AACxC,4DAA0C;AAC1C,yDAAuC;AACvC,4DAA0C;AAC1C,yDAAuC;AACvC,yDAAuC;AACvC,4DAA0C;AAC1C,qEAAmD"}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=jwe.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"jwe.js","sourceRoot":"","sources":["../../../src/jose/jwe.ts"],"names":[],"mappings":""}
+278
View File
@@ -0,0 +1,278 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isPublicJwk = exports.isPrivateJwk = exports.isOkpPublicJwk = exports.isOkpPrivateJwk = exports.isOctPrivateJwk = exports.isEcPublicJwk = exports.isEcPrivateJwk = exports.computeJwkThumbprint = exports.KEY_URI_PREFIX_JWK = void 0;
var common_1 = require("@web5/common");
var utils_js_1 = require("./utils.js");
var sha256_js_1 = require("../primitives/sha256.js");
/**
* Constant defining the prefix for JSON Web Keys (JWK) key URIs in this library.
*
* The prefix 'urn:jwk:' makes it explicit that a string represents a JWK, referenced by a
* {@link https://datatracker.ietf.org/doc/html/rfc3986 | URI} (Uniform Resource Identifier),
* which ensures consistent key referencing across all Web5 Key Management System (KMS)
* implementations.
*
* These key URIs take the form `urn:jwk:<JWK thumbprint>`, where the
* {@link https://datatracker.ietf.org/doc/html/rfc7638 | JWK thumbprint}, derived from the JWK, is
* unique to the key's material, unaffected by the order or optional properties in the JWK.
*/
exports.KEY_URI_PREFIX_JWK = 'urn:jwk:';
/**
* Computes the thumbprint of a JSON Web Key (JWK) using the method
* specified in RFC 7638. This function accepts RSA, EC, OKP, and oct keys
* and returns the thumbprint as a base64url encoded SHA-256 hash of the
* JWK's required members, serialized and sorted lexicographically.
*
* Purpose:
* - Uniquely Identifying Keys: The thumbprint allows the unique
* identification of a specific JWK within a set of JWKs. It provides a
* deterministic way to generate a value that can be used as a key
* identifier (kid) or to match a specific key.
*
* - Simplifying Key Management: In systems where multiple keys are used,
* managing and identifying individual keys can become complex. The
* thumbprint method simplifies this by creating a standardized, unique
* identifier for each key.
*
* - Enabling Interoperability: By standardizing the method to compute a
* thumbprint, different systems can compute the same thumbprint value for
* a given JWK. This enables interoperability among systems that use JWKs.
*
* - Secure Comparison: The thumbprint provides a way to securely compare
* JWKs to determine if they are equivalent.
*
* @example
* ```ts
* const jwk: PublicKeyJwk = {
* 'kty': 'EC',
* 'crv': 'secp256k1',
* 'x': '61iPYuGefxotzBdQZtDvv6cWHZmXrTTscY-u7Y2pFZc',
* 'y': '88nPCVLfrAY9i-wg5ORcwVbHWC_tbeAd1JE2e0co0lU'
* };
*
* const thumbprint = jwkThumbprint(jwk);
* console.log(`JWK thumbprint: ${thumbprint}`);
* ```
*
* @see {@link https://datatracker.ietf.org/doc/html/rfc7638 | RFC7638} for
* the specification of JWK thumbprint computation.
*
* @param jwk - The JSON Web Key for which the thumbprint will be computed.
* This must be an RSA, EC, OKP, or oct key.
* @returns The thumbprint as a base64url encoded string.
* @throws Throws an `Error` if the provided key type is unsupported.
*/
function computeJwkThumbprint(_a) {
var jwk = _a.jwk;
return __awaiter(this, void 0, void 0, function () {
var keyType, normalizedJwk, serializedJwk, utf8Bytes, digest, thumbprint;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
keyType = jwk.kty;
if (keyType === 'EC') {
normalizedJwk = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y };
}
else if (keyType === 'oct') {
normalizedJwk = { k: jwk.k, kty: jwk.kty };
}
else if (keyType === 'OKP') {
normalizedJwk = { crv: jwk.crv, kty: jwk.kty, x: jwk.x };
}
else if (keyType === 'RSA') {
normalizedJwk = { e: jwk.e, kty: jwk.kty, n: jwk.n };
}
else {
throw new Error("Unsupported key type: ".concat(keyType));
}
(0, common_1.removeUndefinedProperties)(normalizedJwk);
serializedJwk = (0, utils_js_1.canonicalize)(normalizedJwk);
utf8Bytes = common_1.Convert.string(serializedJwk).toUint8Array();
return [4 /*yield*/, sha256_js_1.Sha256.digest({ data: utf8Bytes })];
case 1:
digest = _b.sent();
thumbprint = common_1.Convert.uint8Array(digest).toBase64Url();
return [2 /*return*/, thumbprint];
}
});
});
}
exports.computeJwkThumbprint = computeJwkThumbprint;
/**
* Checks if the provided object is a valid elliptic curve private key in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid EC private JWK; otherwise, false.
*/
function isEcPrivateJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if (!('kty' in obj && 'crv' in obj && 'x' in obj && 'd' in obj))
return false;
if (obj.kty !== 'EC')
return false;
if (typeof obj.d !== 'string')
return false;
if (typeof obj.x !== 'string')
return false;
return true;
}
exports.isEcPrivateJwk = isEcPrivateJwk;
/**
* Checks if the provided object is a valid elliptic curve public key in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid EC public JWK; otherwise, false.
*/
function isEcPublicJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if (!('kty' in obj && 'crv' in obj && 'x' in obj))
return false;
if ('d' in obj)
return false;
if (obj.kty !== 'EC')
return false;
if (typeof obj.x !== 'string')
return false;
return true;
}
exports.isEcPublicJwk = isEcPublicJwk;
/**
* Checks if the provided object is a valid octet sequence (symmetric key) in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid oct private JWK; otherwise, false.
*/
function isOctPrivateJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if (!('kty' in obj && 'k' in obj))
return false;
if (obj.kty !== 'oct')
return false;
if (typeof obj.k !== 'string')
return false;
return true;
}
exports.isOctPrivateJwk = isOctPrivateJwk;
/**
* Checks if the provided object is a valid octet key pair private key in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid OKP private JWK; otherwise, false.
*/
function isOkpPrivateJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if (!('kty' in obj && 'crv' in obj && 'x' in obj && 'd' in obj))
return false;
if (obj.kty !== 'OKP')
return false;
if (typeof obj.d !== 'string')
return false;
if (typeof obj.x !== 'string')
return false;
return true;
}
exports.isOkpPrivateJwk = isOkpPrivateJwk;
/**
* Checks if the provided object is a valid octet key pair public key in JWK format.
*
* @param obj - The object to check.
* @returns True if the object is a valid OKP public JWK; otherwise, false.
*/
function isOkpPublicJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
if ('d' in obj)
return false;
if (!('kty' in obj && 'crv' in obj && 'x' in obj))
return false;
if (obj.kty !== 'OKP')
return false;
if (typeof obj.x !== 'string')
return false;
return true;
}
exports.isOkpPublicJwk = isOkpPublicJwk;
/**
* Checks if the provided object is a valid private key in JWK format of any supported type.
*
* @param obj - The object to check.
* @returns True if the object is a valid private JWK; otherwise, false.
*/
function isPrivateJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
var kty = obj.kty;
switch (kty) {
case 'EC':
case 'OKP':
case 'RSA':
return 'd' in obj;
case 'oct':
return 'k' in obj;
default:
return false;
}
}
exports.isPrivateJwk = isPrivateJwk;
/**
* Checks if the provided object is a valid public key in JWK format of any supported type.
*
* @param obj - The object to check.
* @returns True if the object is a valid public JWK; otherwise, false.
*/
function isPublicJwk(obj) {
if (!obj || typeof obj !== 'object')
return false;
var kty = obj.kty;
switch (kty) {
case 'EC':
case 'OKP':
return 'x' in obj && !('d' in obj);
case 'RSA':
return 'n' in obj && 'e' in obj && !('d' in obj);
default:
return false;
}
}
exports.isPublicJwk = isPublicJwk;
//# sourceMappingURL=jwk.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"jwk.js","sourceRoot":"","sources":["../../../src/jose/jwk.ts"],"names":[],"mappings":"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"}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=jws.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"jws.js","sourceRoot":"","sources":["../../../src/jose/jws.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=jwt.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../../src/jose/jwt.ts"],"names":[],"mappings":""}
+60
View File
@@ -0,0 +1,60 @@
"use strict";
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.canonicalize = void 0;
/**
* Canonicalizes a given object according to RFC 8785 (https://tools.ietf.org/html/rfc8785),
* which describes JSON Canonicalization Scheme (JCS). This function sorts the keys of the
* object and its nested objects alphabetically and then returns a stringified version of it.
* This method handles nested objects, array values, and null values appropriately.
*
* @param obj - The object to canonicalize.
* @returns The stringified version of the input object with its keys sorted alphabetically
* per RFC 8785.
*/
function canonicalize(obj) {
/**
* Recursively sorts the keys of an object.
*
* @param obj - The object whose keys are to be sorted.
* @returns A new object with sorted keys.
*/
var sortObjKeys = function (obj) {
var e_1, _a;
if (obj !== null && typeof obj === 'object' && !Array.isArray(obj)) {
var sortedKeys = Object.keys(obj).sort();
var sortedObj_1 = {};
try {
for (var sortedKeys_1 = __values(sortedKeys), sortedKeys_1_1 = sortedKeys_1.next(); !sortedKeys_1_1.done; sortedKeys_1_1 = sortedKeys_1.next()) {
var key = sortedKeys_1_1.value;
// Recursively sort keys of nested objects.
sortedObj_1[key] = sortObjKeys(obj[key]);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (sortedKeys_1_1 && !sortedKeys_1_1.done && (_a = sortedKeys_1.return)) _a.call(sortedKeys_1);
}
finally { if (e_1) throw e_1.error; }
}
return sortedObj_1;
}
return obj;
};
// Stringify and return the final sorted object.
var sortedObj = sortObjKeys(obj);
return JSON.stringify(sortedObj);
}
exports.canonicalize = canonicalize;
//# sourceMappingURL=utils.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/jose/utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAAC,GAA2B;IACtD;;;;;OAKG;IACH,IAAM,WAAW,GAAG,UAAC,GAA2B;;QAC9C,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YAClE,IAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAM,WAAS,GAA2B,EAAE,CAAC;;gBAC7C,KAAkB,IAAA,eAAA,SAAA,UAAU,CAAA,sCAAA,8DAAE;oBAAzB,IAAM,GAAG,uBAAA;oBACZ,2CAA2C;oBAC3C,WAAS,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;iBACxC;;;;;;;;;YACD,OAAO,WAAS,CAAC;SAClB;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,gDAAgD;IAChD,IAAM,SAAS,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,OAAO,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAvBD,oCAuBC"}
+521
View File
@@ -0,0 +1,521 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalKeyManager = void 0;
var common_1 = require("@web5/common");
var sha_2_js_1 = require("./algorithms/sha-2.js");
var ecdsa_js_1 = require("./algorithms/ecdsa.js");
var eddsa_js_1 = require("./algorithms/eddsa.js");
var jwk_js_1 = require("./jose/jwk.js");
/**
* `supportedAlgorithms` is an object mapping algorithm names to their respective implementations
* Each entry in this map specifies the algorithm name and its associated properties, including the
* implementation class and any relevant names or identifiers for the algorithm. This structure
* allows for easy retrieval and instantiation of algorithm implementations based on the algorithm
* name or key specification. It facilitates the support of multiple algorithms within the
* `LocalKeyManager` class.
*/
var supportedAlgorithms = {
'Ed25519': {
implementation: eddsa_js_1.EdDsaAlgorithm,
names: ['Ed25519'],
},
'secp256k1': {
implementation: ecdsa_js_1.EcdsaAlgorithm,
names: ['ES256K', 'secp256k1'],
},
'secp256r1': {
implementation: ecdsa_js_1.EcdsaAlgorithm,
names: ['ES256', 'secp256r1'],
},
'SHA-256': {
implementation: sha_2_js_1.Sha2Algorithm,
names: ['SHA-256']
}
};
var LocalKeyManager = /** @class */ (function () {
function LocalKeyManager(params) {
var _a;
/**
* A private map that stores instances of cryptographic algorithm implementations. Each key in
* this map is an `AlgorithmConstructor`, and its corresponding value is an instance of a class
* that implements a specific cryptographic algorithm. This map is used to cache and reuse
* instances for performance optimization, ensuring that each algorithm is instantiated only once.
*/
this._algorithmInstances = new Map();
this._keyStore = (_a = params === null || params === void 0 ? void 0 : params.keyStore) !== null && _a !== void 0 ? _a : new common_1.MemoryStore();
}
/**
* Generates a hash digest of the provided data.
*
* @remarks
* A digest is the output of the hash function. It's a fixed-size string of bytes
* that uniquely represents the data input into the hash function. The digest is often used for
* data integrity checks, as any alteration in the input data results in a significantly
* different digest.
*
* It takes the algorithm identifier of the hash function and data to digest as input and returns
* the digest of the data.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const data = new Uint8Array([...]);
* const digest = await keyManager.digest({ algorithm: 'SHA-256', data });
* ```
*
* @param params - The parameters for the digest operation.
* @param params.algorithm - The name of hash function to use.
* @param params.data - The data to digest.
*
* @returns A Promise which will be fulfilled with the hash digest.
*/
LocalKeyManager.prototype.digest = function (_a) {
var algorithm = _a.algorithm, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var hasher, hash;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
hasher = this.getAlgorithm({ algorithm: algorithm });
return [4 /*yield*/, hasher.digest({ algorithm: algorithm, data: data })];
case 1:
hash = _b.sent();
return [2 /*return*/, hash];
}
});
});
};
/**
* Exports a private key identified by the provided key URI from the local KMS.
*
* @remarks
* This method retrieves the key from the key store and returns it. It is primarily used
* for extracting keys for backup or transfer purposes.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const privateKey = await keyManager.exportKey({ keyUri });
* ```
*
* @param params - Parameters for exporting the key.
* @param params.keyUri - The key URI identifying the key to export.
*
* @returns A Promise resolving to the JWK representation of the exported key.
*/
LocalKeyManager.prototype.exportKey = function (_a) {
var keyUri = _a.keyUri;
return __awaiter(this, void 0, void 0, function () {
var privateKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.getPrivateKey({ keyUri: keyUri })];
case 1:
privateKey = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Generates a new cryptographic key in the local KMS with the specified algorithm and returns a
* unique key URI which can be used to reference the key in subsequent operations.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* console.log(keyUri); // Outputs the key URI
* ```
*
* @param params - The parameters for key generation.
* @param params.algorithm - The algorithm to use for key generation, defined in `SupportedAlgorithm`.
*
* @returns A Promise that resolves to the key URI, a unique identifier for the generated key.
*/
LocalKeyManager.prototype.generateKey = function (_a) {
var algorithm = _a.algorithm;
return __awaiter(this, void 0, void 0, function () {
var keyGenerator, key, keyUri;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
keyGenerator = this.getAlgorithm({ algorithm: algorithm });
return [4 /*yield*/, keyGenerator.generateKey({ algorithm: algorithm })];
case 1:
key = _b.sent();
if ((key === null || key === void 0 ? void 0 : key.kid) === undefined) {
throw new Error('Generated key is missing a required property: kid');
}
keyUri = "".concat(jwk_js_1.KEY_URI_PREFIX_JWK).concat(key.kid);
// Store the key in the key store.
return [4 /*yield*/, this._keyStore.set(keyUri, key)];
case 2:
// Store the key in the key store.
_b.sent();
return [2 /*return*/, keyUri];
}
});
});
};
/**
* Computes the Key URI for a given public JWK (JSON Web Key).
*
* @remarks
* This method generates a {@link https://datatracker.ietf.org/doc/html/rfc3986 | URI}
* (Uniform Resource Identifier) for the given JWK, which uniquely identifies the key across all
* `CryptoApi` implementations. The key URI is constructed by appending the
* {@link https://datatracker.ietf.org/doc/html/rfc7638 | JWK thumbprint} to the prefix
* `urn:jwk:`. The JWK thumbprint is deterministically computed from the JWK and is consistent
* regardless of property order or optional property inclusion in the JWK. This ensures that the
* same key material represented as a JWK will always yield the same thumbprint, and therefore,
* the same key URI.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const publicKey = await keyManager.getPublicKey({ keyUri });
* const keyUriFromPublicKey = await keyManager.getKeyUri({ key: publicKey });
* console.log(keyUri === keyUriFromPublicKey); // Outputs `true`
* ```
*
* @param params - The parameters for getting the key URI.
* @param params.key - The JWK for which to compute the key URI.
*
* @returns A Promise that resolves to the key URI as a string.
*/
LocalKeyManager.prototype.getKeyUri = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var jwkThumbprint, keyUri;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: key })];
case 1:
jwkThumbprint = _b.sent();
keyUri = "".concat(jwk_js_1.KEY_URI_PREFIX_JWK).concat(jwkThumbprint);
return [2 /*return*/, keyUri];
}
});
});
};
/**
* Retrieves the public key associated with a previously generated private key, identified by
* the provided key URI.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const publicKey = await keyManager.getPublicKey({ keyUri });
* ```
*
* @param params - The parameters for retrieving the public key.
* @param params.keyUri - The key URI of the private key to retrieve the public key for.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
LocalKeyManager.prototype.getPublicKey = function (_a) {
var keyUri = _a.keyUri;
return __awaiter(this, void 0, void 0, function () {
var privateKey, algorithm, keyGenerator, publicKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.getPrivateKey({ keyUri: keyUri })];
case 1:
privateKey = _b.sent();
algorithm = this.getAlgorithmName({ key: privateKey });
keyGenerator = this.getAlgorithm({ algorithm: algorithm });
return [4 /*yield*/, keyGenerator.getPublicKey({ key: privateKey })];
case 2:
publicKey = _b.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Imports a private key into the local KMS.
*
* @remarks
* This method stores the provided JWK in the key store, making it available for subsequent
* cryptographic operations. It is particularly useful for initializing the KMS with pre-existing
* keys or for restoring keys from backups.
*
* Note that, if defined, the `kid` (key ID) property of the JWK is used as the key URI for the
* imported key. If the `kid` property is not provided, the key URI is computed from the JWK
* thumbprint of the key.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const privateKey = { ... } // A private key in JWK format
* const keyUri = await keyManager.importKey({ key: privateKey });
* ```
*
* @param params - Parameters for importing the key.
* @param params.key - The private key to import to in JWK format.
*
* @returns A Promise resolving to the key URI, uniquely identifying the imported key.
*/
LocalKeyManager.prototype.importKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _c, _d, keyUri;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
if (!(0, jwk_js_1.isPrivateJwk)(key))
throw new TypeError('Invalid key provided. Must be a private key in JWK format.');
privateKey = structuredClone(key);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
privateKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [4 /*yield*/, this.getKeyUri({ key: privateKey })];
case 4:
keyUri = _e.sent();
// Store the key in the key store.
return [4 /*yield*/, this._keyStore.set(keyUri, privateKey)];
case 5:
// Store the key in the key store.
_e.sent();
return [2 /*return*/, keyUri];
}
});
});
};
/**
* Signs the provided data using the private key identified by the provided key URI.
*
* @remarks
* This method uses the signature algorithm determined by the `alg` and/or `crv` properties of the
* private key identified by the provided key URI to sign the provided data. The signature can
* later be verified by parties with access to the corresponding public key, ensuring that the
* data has not been tampered with and was indeed signed by the holder of the private key.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const data = new TextEncoder().encode('Message to sign');
* const signature = await keyManager.sign({ keyUri, data });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.keyUri - The key URI of the private key to use for signing.
* @param params.data - The data to sign.
*
* @returns A Promise resolving to the digital signature as a `Uint8Array`.
*/
LocalKeyManager.prototype.sign = function (_a) {
var keyUri = _a.keyUri, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var privateKey, algorithm, signer, signature;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.getPrivateKey({ keyUri: keyUri })];
case 1:
privateKey = _b.sent();
algorithm = this.getAlgorithmName({ key: privateKey });
signer = this.getAlgorithm({ algorithm: algorithm });
signature = signer.sign({ data: data, key: privateKey });
return [2 /*return*/, signature];
}
});
});
};
/**
* Verifies a digital signature associated the provided data using the provided key.
*
* @remarks
* This method uses the signature algorithm determined by the `alg` and/or `crv` properties of the
* provided key to check the validity of a digital signature against the original data. It
* confirms whether the signature was created by the holder of the corresponding private key and
* that the data has not been tampered with.
*
* @example
* ```ts
* const keyManager = new LocalKeyManager();
* const keyUri = await keyManager.generateKey({ algorithm: 'Ed25519' });
* const data = new TextEncoder().encode('Message to sign');
* const signature = await keyManager.sign({ keyUri, data });
* const isSignatureValid = await keyManager.verify({ keyUri, data, signature });
* ```
*
* @param params - The parameters for the verification operation.
* @param params.key - The key to use for verification.
* @param params.signature - The signature to verify.
* @param params.data - The data to verify.
*
* @returns A Promise resolving to a boolean indicating whether the signature is valid.
*/
LocalKeyManager.prototype.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var algorithm, signer, isSignatureValid;
return __generator(this, function (_b) {
algorithm = this.getAlgorithmName({ key: key });
signer = this.getAlgorithm({ algorithm: algorithm });
isSignatureValid = signer.verify({ key: key, signature: signature, data: data });
return [2 /*return*/, isSignatureValid];
});
});
};
/**
* Retrieves an algorithm implementation instance based on the provided algorithm name.
*
* @remarks
* This method checks if the requested algorithm is supported and returns a cached instance
* if available. If an instance does not exist, it creates and caches a new one. This approach
* optimizes performance by reusing algorithm instances across cryptographic operations.
*
* @example
* ```ts
* const signer = this.getAlgorithm({ algorithm: 'Ed25519' });
* ```
*
* @param params - The parameters for retrieving the algorithm implementation.
* @param params.algorithm - The name of the algorithm to retrieve.
*
* @returns An instance of the requested algorithm implementation.
*
* @throws Error if the requested algorithm is not supported.
*/
LocalKeyManager.prototype.getAlgorithm = function (_a) {
var _b;
var algorithm = _a.algorithm;
// Check if algorithm is supported.
var AlgorithmImplementation = (_b = supportedAlgorithms[algorithm]) === null || _b === void 0 ? void 0 : _b['implementation'];
if (!AlgorithmImplementation) {
throw new Error("Algorithm not supported: ".concat(algorithm));
}
// Check if instance already exists for the `AlgorithmImplementation`.
if (!this._algorithmInstances.has(AlgorithmImplementation)) {
// If not, create a new instance and store it in the cache
this._algorithmInstances.set(AlgorithmImplementation, new AlgorithmImplementation());
}
// Return the cached instance
return this._algorithmInstances.get(AlgorithmImplementation);
};
/**
* Determines the name of the algorithm based on the key's properties.
*
* @remarks
* This method facilitates the identification of the correct algorithm for cryptographic
* operations based on the `alg` or `crv` properties of a {@link Jwk | JWK}.
*
* @example
* ```ts
* const publicKey = { ... }; // Public key in JWK format
* const algorithm = this.getAlgorithmName({ key: publicKey });
* ```
*
* @param params - The parameters for determining the algorithm name.
* @param params.key - A JWK containing the `alg` or `crv` properties.
*
* @returns The name of the algorithm associated with the key.
*
* @throws Error if the algorithm cannot be determined from the provided input.
*/
LocalKeyManager.prototype.getAlgorithmName = function (_a) {
var key = _a.key;
var algProperty = key.alg;
var crvProperty = key.crv;
for (var algName in supportedAlgorithms) {
var algorithmInfo = supportedAlgorithms[algName];
if (algProperty && algorithmInfo.names.includes(algProperty)) {
return algName;
}
else if (crvProperty && algorithmInfo.names.includes(crvProperty)) {
return algName;
}
}
throw new Error("Unable to determine algorithm based on provided input: alg=".concat(algProperty, ", crv=").concat(crvProperty));
};
/**
* Retrieves a private key from the key store based on the provided key URI.
*
* @example
* ```ts
* const privateKey = this.getPrivateKey({ keyUri: 'urn:jwk:...' });
* ```
*
* @param params - Parameters for retrieving the private key.
* @param params.keyUri - The key URI identifying the private key to retrieve.
*
* @returns A Promise resolving to the JWK representation of the private key.
*
* @throws Error if the key is not found in the key store.
*/
LocalKeyManager.prototype.getPrivateKey = function (_a) {
var keyUri = _a.keyUri;
return __awaiter(this, void 0, void 0, function () {
var privateKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this._keyStore.get(keyUri)];
case 1:
privateKey = _b.sent();
if (!privateKey) {
throw new Error("Key not found: ".concat(keyUri));
}
return [2 /*return*/, privateKey];
}
});
});
};
return LocalKeyManager;
}());
exports.LocalKeyManager = LocalKeyManager;
//# sourceMappingURL=local-key-manager.js.map
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
{"type": "commonjs"}
+398
View File
@@ -0,0 +1,398 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AesCtr = void 0;
var common_1 = require("@web5/common");
var utils_1 = require("@noble/ciphers/webcrypto/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* Constant defining the AES block size in bits.
*
* @remarks
* In AES Counter (CTR) mode, the counter length must match the block size of the AES algorithm,
* which is 128 bits. NIST publication 800-38A, which provides guidelines for block cipher modes of
* operation, specifies this requirement. Maintaining a counter length of 128 bits is essential for
* the correct operation and security of AES-CTR.
*
* This implementation does not support counter lengths that are different from the value defined by
* this constant.
*
* @see {@link https://doi.org/10.6028/NIST.SP.800-38A | NIST SP 800-38A}
*/
var AES_BLOCK_SIZE = 128;
/**
* Constant defining the AES key length values in bits.
*
* @remarks
* NIST publication FIPS 197 states:
* > The AES algorithm is capable of using cryptographic keys of 128, 192, and 256 bits to encrypt
* > and decrypt data in blocks of 128 bits.
*
* This implementation does not support key lengths that are different from the three values
* defined by this constant.
*
* @see {@link https://doi.org/10.6028/NIST.FIPS.197-upd1 | NIST FIPS 197}
*/
var AES_KEY_LENGTHS = [128, 192, 256];
/**
* Constant defining the maximum length of the counter in bits.
*
* @remarks
* The rightmost bits of the counter block are used as the actual counter value, while the leftmost
* bits are used as the nonce. The maximum length of the counter is 128 bits, which is the same as
* the AES block size.
*/
var COUNTER_MAX_LENGTH = AES_BLOCK_SIZE;
/**
* The `AesCtr` class provides a comprehensive set of utilities for cryptographic operations
* using the Advanced Encryption Standard (AES) in Counter (CTR) mode. This class includes
* methods for key generation, encryption, decryption, and conversions between raw byte arrays
* and JSON Web Key (JWK) formats. It is designed to support AES-CTR, a symmetric key algorithm
* that is widely used in various cryptographic applications for its efficiency and security.
*
* AES-CTR mode operates as a stream cipher using a block cipher (AES) and is well-suited for
* scenarios where parallel processing is beneficial or where the same key is required to
* encrypt multiple data blocks. The class adheres to standard cryptographic practices, ensuring
* compatibility and security in its implementations.
*
* Key Features:
* - Key Generation: Generate AES symmetric keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Encryption: Encrypt data using AES-CTR with the provided symmetric key.
* - Decryption: Decrypt data encrypted with AES-CTR using the corresponding symmetric key.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
* const privateKey = await AesCtr.generateKey({ length });
*
* // Encryption
* const data = new TextEncoder().encode('Messsage');
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block
* const encryptedData = await AesCtr.encrypt({
* data,
* counter,
* key: privateKey,
* length: 64 // Length of the counter in bits
* });
*
* // Decryption
* const decryptedData = await AesCtr.decrypt({
* data: encryptedData,
* counter,
* key: privateKey,
* length: 64 // Length of the counter in bits
* });
*
* // Key Conversion
* const privateKeyBytes = await AesCtr.privateKeyToBytes({ privateKey });
* ```
*/
var AesCtr = /** @class */ (function () {
function AesCtr() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a symmetric key represented as a byte array (Uint8Array) and
* converts it into a JWK object for use with AES (Advanced Encryption Standard)
* in Counter (CTR) mode. The conversion process involves encoding the key into
* base64url format and setting the appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
* - `k`: The symmetric key, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
* const privateKey = await AesCtr.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
*
* @returns A Promise that resolves to the symmetric key in JWK format.
*/
AesCtr.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
privateKey = {
k: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'oct'
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Decrypts the provided data using AES in Counter (CTR) mode.
*
* @remarks
* This method performs AES-CTR decryption on the given encrypted data using the specified key.
* Similar to the encryption process, it requires an initial counter block and the length
* of the counter block, along with the encrypted data and the decryption key. The method
* returns the decrypted data as a Uint8Array.
*
* @example
* ```ts
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block used during encryption
* const key = { ... }; // A Jwk object representing the same AES key used for encryption
* const decryptedData = await AesCtr.decrypt({
* data: encryptedData,
* counter,
* key,
* length: 64 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
* @param params.key - The key to use for decryption, represented in JWK format.
* @param params.data - The encrypted data to decrypt, as a Uint8Array.
* @param params.counter - The initial value of the counter block.
* @param params.length - The number of bits in the counter block that are used for the actual counter.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
AesCtr.decrypt = function (_a) {
var key = _a.key, data = _a.data, counter = _a.counter, length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, plaintextBuffer, plaintext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Validate the initial counter block length matches the AES block size.
if (counter.byteLength !== AES_BLOCK_SIZE / 8) {
throw new TypeError("The counter must be ".concat(AES_BLOCK_SIZE, " bits in length"));
}
// Validate the length of the counter.
if (length === 0 || length > COUNTER_MAX_LENGTH) {
throw new TypeError("The 'length' property must be in the range 1 to ".concat(COUNTER_MAX_LENGTH));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.importKey('jwk', key, { name: 'AES-CTR' }, true, ['decrypt'])];
case 1:
webCryptoKey = _b.sent();
return [4 /*yield*/, webCrypto.decrypt({ name: 'AES-CTR', counter: counter, length: length }, webCryptoKey, data)];
case 2:
plaintextBuffer = _b.sent();
plaintext = new Uint8Array(plaintextBuffer);
return [2 /*return*/, plaintext];
}
});
});
};
/**
* Encrypts the provided data using AES in Counter (CTR) mode.
*
* @remarks
* This method performs AES-CTR encryption on the given data using the specified key.
* It requires the initial counter block and the length of the counter block, alongside
* the data and key. The method is designed to work asynchronously and returns the
* encrypted data as a Uint8Array.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage');
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block
* const key = { ... }; // A Jwk object representing an AES key
* const encryptedData = await AesCtr.encrypt({
* data,
* counter,
* key,
* length: 64 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
* @param params.key - The key to use for encryption, represented in JWK format.
* @param params.data - The data to encrypt, represented as a Uint8Array.
* @param params.counter - The initial value of the counter block.
* @param params.length - The number of bits in the counter block that are used for the actual counter.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
AesCtr.encrypt = function (_a) {
var key = _a.key, data = _a.data, counter = _a.counter, length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, ciphertextBuffer, ciphertext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Validate the initial counter block value length.
if (counter.byteLength !== AES_BLOCK_SIZE / 8) {
throw new TypeError("The counter must be ".concat(AES_BLOCK_SIZE, " bits in length"));
}
// Validate the length of the counter.
if (length === 0 || length > COUNTER_MAX_LENGTH) {
throw new TypeError("The 'length' property must be in the range 1 to ".concat(COUNTER_MAX_LENGTH));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.importKey('jwk', key, { name: 'AES-CTR' }, true, ['encrypt', 'decrypt'])];
case 1:
webCryptoKey = _b.sent();
return [4 /*yield*/, webCrypto.encrypt({ name: 'AES-CTR', counter: counter, length: length }, webCryptoKey, data)];
case 2:
ciphertextBuffer = _b.sent();
ciphertext = new Uint8Array(ciphertextBuffer);
return [2 /*return*/, ciphertext];
}
});
});
};
/**
* Generates a symmetric key for AES in Counter (CTR) mode in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new symmetric key of a specified length suitable for use with
* AES-CTR encryption. It uses cryptographically secure random number generation to
* ensure the uniqueness and security of the key. The generated key adheres to the JWK
* format, making it compatible with common cryptographic standards and easy to use in
* various cryptographic processes.
*
* The generated key includes the following components:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
* const privateKey = await AesCtr.generateKey({ length });
* ```
*
* @param params - The parameters for the key generation.
* @param params.length - The length of the key in bits. Common lengths are 128, 192, and 256 bits.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
AesCtr.generateKey = function (_a) {
var length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, _b, ext, key_ops, privateKey, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
// Validate the key length.
if (!AES_KEY_LENGTHS.includes(length)) {
throw new RangeError("The key length is invalid: Must be ".concat(AES_KEY_LENGTHS.join(', '), " bits"));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.generateKey({ name: 'AES-CTR', length: length }, true, ['encrypt'])];
case 1:
webCryptoKey = _d.sent();
return [4 /*yield*/, webCrypto.exportKey('jwk', webCryptoKey)];
case 2:
_b = _d.sent(), ext = _b.ext, key_ops = _b.key_ops, privateKey = __rest(_b, ["ext", "key_ops"]);
// Compute the JWK thumbprint and set as the key ID.
_c = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_c.kid = _d.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
* It decodes the 'k' parameter of the JWK value, which represents the symmetric key in base64url
* encoding, into a byte array.
*
* @example
* ```ts
* const privateKey = { ... }; // A symmetric key in JWK format
* const privateKeyBytes = await AesCtr.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKey - The symmetric key in JWK format.
*
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
*/
AesCtr.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid oct private key.
if (!(0, jwk_js_1.isOctPrivateJwk)(privateKey)) {
throw new Error("AesCtr: The provided key is not a valid oct private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.k).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
return AesCtr;
}());
exports.AesCtr = AesCtr;
//# sourceMappingURL=aes-ctr.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-ctr.js","sourceRoot":"","sources":["../../../src/primitives/aes-ctr.ts"],"names":[],"mappings":"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"}
+425
View File
@@ -0,0 +1,425 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AesGcm = exports.AES_GCM_TAG_LENGTHS = void 0;
var common_1 = require("@web5/common");
var utils_1 = require("@noble/ciphers/webcrypto/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* Const defining the AES-GCM initialization vector (IV) length in bits.
*
* @remarks
* NIST Special Publication 800-38D, Section 5.2.1.1 states that the IV length:
* > For IVs, it is recommended that implementations restrict support to the length of 96 bits, to
* > promote interoperability, efficiency, and simplicity of design.
*
* This implementation does not support IV lengths that are different from the value defined by
* this constant.
*
* @see {@link https://doi.org/10.6028/NIST.SP.800-38D | NIST SP 800-38D}
*/
var AES_GCM_IV_LENGTH = 96;
/**
* Constant defining the AES key length values in bits.
*
* @remarks
* NIST publication FIPS 197 states:
* > The AES algorithm is capable of using cryptographic keys of 128, 192, and 256 bits to encrypt
* > and decrypt data in blocks of 128 bits.
*
* This implementation does not support key lengths that are different from the three values
* defined by this constant.
*
* @see {@link https://doi.org/10.6028/NIST.FIPS.197-upd1 | NIST FIPS 197}
*/
var AES_KEY_LENGTHS = [128, 192, 256];
/**
* Constant defining the AES-GCM tag length values in bits.
*
* @remarks
* NIST Special Publication 800-38D, Section 5.2.1.2 states that the tag length:
* > may be any one of the following five values: 128, 120, 112, 104, or 96
*
* Although the NIST specification allows for tag lengths of 32 or 64 bits in certain applications,
* the use of shorter tag lengths can be problematic for GCM due to targeted forgery attacks. As a
* precaution, this implementation does not support tag lengths that are different from the five
* values defined by this constant. See Appendix C of the NIST SP 800-38D specification for
* additional guidance and details.
*
* @see {@link https://doi.org/10.6028/NIST.SP.800-38D | NIST SP 800-38D}
*/
exports.AES_GCM_TAG_LENGTHS = [96, 104, 112, 120, 128];
/**
* The `AesGcm` class provides a comprehensive set of utilities for cryptographic operations
* using the Advanced Encryption Standard (AES) in Galois/Counter Mode (GCM). This class includes
* methods for key generation, encryption, decryption, and conversions between raw byte arrays
* and JSON Web Key (JWK) formats. It is designed to support AES-GCM, a symmetric key algorithm
* that is widely used for its efficiency, security, and provision of authenticated encryption.
*
* AES-GCM is particularly favored for scenarios that require both confidentiality and integrity
* of data. It integrates the counter mode of encryption with the Galois mode of authentication,
* offering high performance and parallel processing capabilities.
*
* Key Features:
* - Key Generation: Generate AES symmetric keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Encryption: Encrypt data using AES-GCM with the provided symmetric key.
* - Decryption: Decrypt data encrypted with AES-GCM using the corresponding symmetric key.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
* const privateKey = await AesGcm.generateKey({ length });
*
* // Encryption
* const data = new TextEncoder().encode('Messsage');
* const iv = new Uint8Array(12); // 12-byte initialization vector
* const encryptedData = await AesGcm.encrypt({
* data,
* iv,
* key: privateKey
* });
*
* // Decryption
* const decryptedData = await AesGcm.decrypt({
* data: encryptedData,
* iv,
* key: privateKey
* });
*
* // Key Conversion
* const privateKeyBytes = await AesGcm.privateKeyToBytes({ privateKey });
* ```
*/
var AesGcm = /** @class */ (function () {
function AesGcm() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a symmetric key represented as a byte array (Uint8Array) and
* converts it into a JWK object for use with AES-GCM (Advanced Encryption Standard -
* Galois/Counter Mode). The conversion process involves encoding the key into
* base64url format and setting the appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
* - `k`: The symmetric key, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
* const privateKey = await AesGcm.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
*
* @returns A Promise that resolves to the symmetric key in JWK format.
*/
AesGcm.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
privateKey = {
k: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'oct'
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Decrypts the provided data using AES-GCM.
*
* @remarks
* This method performs AES-GCM decryption on the given encrypted data using the specified key.
* It requires an initialization vector (IV), the encrypted data along with the decryption key,
* and optionally, additional authenticated data (AAD). The method returns the decrypted data as a
* Uint8Array. The optional `tagLength` parameter specifies the size in bits of the authentication
* tag used when encrypting the data. If not specified, the default tag length of 128 bits is
* used.
*
* @example
* ```ts
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const iv = new Uint8Array([...]); // Initialization vector used during encryption
* const additionalData = new Uint8Array([...]); // Optional additional authenticated data
* const key = { ... }; // A Jwk object representing the AES key
* const decryptedData = await AesGcm.decrypt({
* data: encryptedData,
* iv,
* additionalData,
* key,
* tagLength: 128 // Optional tag length in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
* @param params.key - The key to use for decryption, represented in JWK format.
* @param params.data - The encrypted data to decrypt, represented as a Uint8Array.
* @param params.iv - The initialization vector, represented as a Uint8Array.
* @param params.additionalData - Optional additional authenticated data. Optional.
* @param params.tagLength - The length of the authentication tag in bits. Optional.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
AesGcm.decrypt = function (_a) {
var key = _a.key, data = _a.data, iv = _a.iv, additionalData = _a.additionalData, tagLength = _a.tagLength;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, algorithm, plaintextBuffer, plaintext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Validate the initialization vector length.
if (iv.byteLength !== AES_GCM_IV_LENGTH / 8) {
throw new TypeError("The initialization vector must be ".concat(AES_GCM_IV_LENGTH, " bits in length"));
}
// Validate the tag length.
if (tagLength && !exports.AES_GCM_TAG_LENGTHS.includes(tagLength)) {
throw new RangeError("The tag length is invalid: Must be ".concat(exports.AES_GCM_TAG_LENGTHS.join(', '), " bits"));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.importKey('jwk', key, { name: 'AES-GCM' }, true, ['decrypt'])];
case 1:
webCryptoKey = _b.sent();
algorithm = __assign(__assign({ name: 'AES-GCM', iv: iv }, (tagLength && { tagLength: tagLength })), (additionalData && { additionalData: additionalData }));
return [4 /*yield*/, webCrypto.decrypt(algorithm, webCryptoKey, data)];
case 2:
plaintextBuffer = _b.sent();
plaintext = new Uint8Array(plaintextBuffer);
return [2 /*return*/, plaintext];
}
});
});
};
/**
* Encrypts the provided data using AES-GCM.
*
* @remarks
* This method performs AES-GCM encryption on the given data using the specified key.
* It requires an initialization vector (IV), the encrypted data along with the decryption key,
* and optionally, additional authenticated data (AAD). The method returns the encrypted data as a
* Uint8Array. The optional `tagLength` parameter specifies the size in bits of the authentication
* tag generated in the encryption operation and used for authentication in the corresponding
* decryption. If not specified, the default tag length of 128 bits is used.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage');
* const iv = new Uint8Array([...]); // Initialization vector
* const additionalData = new Uint8Array([...]); // Optional additional authenticated data
* const key = { ... }; // A Jwk object representing an AES key
* const encryptedData = await AesGcm.encrypt({
* data,
* iv,
* additionalData,
* key,
* tagLength: 128 // Optional tag length in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
* @param params.key - The key to use for encryption, represented in JWK format.
* @param params.data - The data to encrypt, represented as a Uint8Array.
* @param params.iv - The initialization vector, represented as a Uint8Array.
* @param params.additionalData - Optional additional authenticated data. Optional.
* @param params.tagLength - The length of the authentication tag in bits. Optional.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
AesGcm.encrypt = function (_a) {
var data = _a.data, iv = _a.iv, key = _a.key, additionalData = _a.additionalData, tagLength = _a.tagLength;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, algorithm, ciphertextBuffer, ciphertext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Validate the initialization vector length.
if (iv.byteLength !== AES_GCM_IV_LENGTH / 8) {
throw new TypeError("The initialization vector must be ".concat(AES_GCM_IV_LENGTH, " bits in length"));
}
// Validate the tag length.
if (tagLength && !exports.AES_GCM_TAG_LENGTHS.includes(tagLength)) {
throw new RangeError("The tag length is invalid: Must be ".concat(exports.AES_GCM_TAG_LENGTHS.join(', '), " bits"));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.importKey('jwk', key, { name: 'AES-GCM' }, true, ['encrypt'])];
case 1:
webCryptoKey = _b.sent();
algorithm = __assign(__assign({ name: 'AES-GCM', iv: iv }, (tagLength && { tagLength: tagLength })), (additionalData && { additionalData: additionalData }));
return [4 /*yield*/, webCrypto.encrypt(algorithm, webCryptoKey, data)];
case 2:
ciphertextBuffer = _b.sent();
ciphertext = new Uint8Array(ciphertextBuffer);
return [2 /*return*/, ciphertext];
}
});
});
};
/**
* Generates a symmetric key for AES in Galois/Counter Mode (GCM) in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new symmetric key of a specified length suitable for use with
* AES-GCM encryption. It leverages cryptographically secure random number generation
* to ensure the uniqueness and security of the key. The generated key adheres to the JWK
* format, facilitating compatibility with common cryptographic standards and ease of use
* in various cryptographic applications.
*
* The generated key includes these components:
* - `kty`: Key Type, set to 'oct' for Octet Sequence, indicating a symmetric key.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint, providing a unique identifier.
*
* @example
* ```ts
* const length = 256; // Length of the key in bits (e.g., 128, 192, 256)
* const privateKey = await AesGcm.generateKey({ length });
* ```
*
* @param params - The parameters for the key generation.
* @param params.length - The length of the key in bits. Common lengths are 128, 192, and 256 bits.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
AesGcm.generateKey = function (_a) {
var length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, _b, ext, key_ops, privateKey, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
// Validate the key length.
if (!AES_KEY_LENGTHS.includes(length)) {
throw new RangeError("The key length is invalid: Must be ".concat(AES_KEY_LENGTHS.join(', '), " bits"));
}
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.generateKey({ name: 'AES-GCM', length: length }, true, ['encrypt'])];
case 1:
webCryptoKey = _d.sent();
return [4 /*yield*/, webCrypto.exportKey('jwk', webCryptoKey)];
case 2:
_b = _d.sent(), ext = _b.ext, key_ops = _b.key_ops, privateKey = __rest(_b, ["ext", "key_ops"]);
// Compute the JWK thumbprint and set as the key ID.
_c = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_c.kid = _d.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
* It focuses on the 'k' parameter of the JWK, which represents the symmetric key component
* in base64url encoding. The method decodes this value into a byte array, providing
* the symmetric key in its raw binary form.
*
* @example
* ```ts
* const privateKey = { ... }; // A symmetric key in JWK format
* const privateKeyBytes = await AesGcm.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKey - The symmetric key in JWK format.
*
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
*/
AesGcm.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid oct private key.
if (!(0, jwk_js_1.isOctPrivateJwk)(privateKey)) {
throw new Error("AesGcm: The provided key is not a valid oct private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.k).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
return AesGcm;
}());
exports.AesGcm = AesGcm;
//# sourceMappingURL=aes-gcm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-gcm.js","sourceRoot":"","sources":["../../../src/primitives/aes-gcm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,215 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConcatKdf = void 0;
var sha256_1 = require("@noble/hashes/sha256");
var common_1 = require("@web5/common");
var utils_1 = require("@noble/hashes/utils");
/**
* An implementation of the Concatenation Key Derivation Function (ConcatKDF)
* as specified in NIST.800-56A, a single-step key-derivation function (SSKDF).
* ConcatKDF produces a derived key from a secret key (like a shared secret
* from ECDH), and other optional public information. This implementation
* specifically uses SHA-256 as the pseudorandom function (PRF).
*
* Note: This implementation allows for only a single round / repetition using the function
* `K(1) = H(counter || Z || FixedInfo)`, where:
* - `K(1)` is the derived key material after one round
* - `H` is the SHA-256 hashing function
* - `counter` is a 32-bit, big-endian bit string counter set to 0x00000001
* - `Z` is the shared secret value obtained from a key agreement protocol
* - `FixedInfo` is a bit string used to ensure that the derived keying material is adequately
* "bound" to the key-agreement transaction.
*
* @example
* ```ts
* // Key Derivation
* const derivedKeyingMaterial = await ConcatKdf.deriveKey({
* sharedSecret: utils.randomBytes(32),
* keyDataLen: 128,
* fixedInfo: {
* algorithmId: "A128GCM",
* partyUInfo: "Alice",
* partyVInfo: "Bob",
* suppPubInfo: 128,
* },
* });
* ```
*
* Additional Information:
*
* `Z`, or "shared secret":
* The shared secret value obtained from a key agreement protocol, such as
* Diffie-Hellman, ECDH (Elliptic Curve Diffie-Hellman). Importantly, this
* shared secret is not directly used as the encryption or authentication
* key, but as an input to a key derivation function (KDF), such as Concat
* KDF, to generate the actual key. This adds an extra layer of security, as
* even if the shared secret gets compromised, the actual encryption or
* authentication key stays safe. This shared secret `Z` value is kept
* confidential between the two parties in the key agreement protocol.
*
* @see {@link https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf | NIST.800-56A}
* @see {@link https://datatracker.ietf.org/doc/html/rfc7518#section-4.6.2 | RFC 7518, Section 4.6.2}
*/
var ConcatKdf = /** @class */ (function () {
function ConcatKdf() {
}
/**
* Derives a key of a specified length from the input parameters.
*
* @example
* ```ts
* // Key Derivation
* const derivedKeyingMaterial = await ConcatKdf.deriveKey({
* sharedSecret: utils.randomBytes(32),
* keyDataLen: 128,
* fixedInfo: {
* algorithmId: "A128GCM",
* partyUInfo: "Alice",
* partyVInfo: "Bob",
* suppPubInfo: 128,
* },
* });
* ```
*
* @param params - Input parameters for key derivation.
* @param params.keyDataLen - The desired length of the derived key in bits.
* @param params.sharedSecret - The shared secret key to derive from.
* @param params.fixedInfo - Additional public information to use in key derivation.
* @returns The derived key as a Uint8Array.
*
* @throws {Error} If the `keyDataLen` would require multiple rounds.
*/
ConcatKdf.deriveKey = function (_a) {
var keyDataLen = _a.keyDataLen, fixedInfo = _a.fixedInfo, sharedSecret = _a.sharedSecret;
return __awaiter(this, void 0, void 0, function () {
var hashLen, roundCount, counter, fixedInfoBytes, derivedKeyingMaterial;
return __generator(this, function (_b) {
hashLen = 256;
roundCount = Math.ceil(keyDataLen / hashLen);
if (roundCount !== 1) {
throw new Error("Concat KDF with ".concat(roundCount, " rounds not supported."));
}
counter = new Uint8Array(4);
new DataView(counter.buffer).setUint32(0, roundCount);
fixedInfoBytes = ConcatKdf.computeFixedInfo(fixedInfo);
derivedKeyingMaterial = (0, sha256_1.sha256)((0, utils_1.concatBytes)(counter, sharedSecret, fixedInfoBytes));
// Return the bit string of derived keying material of length keyDataLen bits.
return [2 /*return*/, derivedKeyingMaterial.slice(0, keyDataLen / 8)];
});
});
};
/**
* Computes the `FixedInfo` parameter for Concat KDF, which binds the derived key material to the
* context of the key agreement transaction.
*
* @remarks
* This implementation follows the recommended format for `FixedInfo` specified in section
* 5.8.1.2.1 of the NIST.800-56A publication.
*
* `FixedInfo` is a bit string equal to the following concatenation:
* `AlgorithmID || PartyUInfo || PartyVInfo {|| SuppPubInfo }{|| SuppPrivInfo }`.
*
* `SuppPubInfo` is the key length in bits, big endian encoded as a 32-bit number. For example,
* 128 would be [0, 0, 0, 128] and 256 would be [0, 0, 1, 0].
*
* @param params - Input data to construct FixedInfo.
* @returns FixedInfo as a Uint8Array.
*/
ConcatKdf.computeFixedInfo = function (params) {
// Required sub-fields.
var algorithmId = ConcatKdf.toDataLenData({ data: params.algorithmId });
var partyUInfo = ConcatKdf.toDataLenData({ data: params.partyUInfo });
var partyVInfo = ConcatKdf.toDataLenData({ data: params.partyVInfo });
// Optional sub-fields.
var suppPubInfo = ConcatKdf.toDataLenData({ data: params.suppPubInfo, variableLength: false });
var suppPrivInfo = ConcatKdf.toDataLenData({ data: params.suppPrivInfo });
// Concatenate AlgorithmID || PartyUInfo || PartyVInfo || SuppPubInfo || SuppPrivInfo.
var fixedInfo = (0, utils_1.concatBytes)(algorithmId, partyUInfo, partyVInfo, suppPubInfo, suppPrivInfo);
return fixedInfo;
};
/**
* Encodes input data as a length-prefixed byte string, or
* as a fixed-length bit string if specified.
*
* If variableLength = true, return the data in the form Datalen || Data,
* where Data is a variable-length string of zero or more (eight-bit)
* bytes, and Datalen is a fixed-length, big-endian counter that
* indicates the length (in bytes) of Data.
*
* If variableLength = false, return the data formatted as a
* fixed-length bit string.
*
* @param params - Input data and options for the conversion.
* @param params.data - The input data to encode. Must be a type convertible to Uint8Array by the Convert class.
* @param params.variableLength - Whether to output the data as variable length. Default is true.
*
* @returns The input data encoded as a Uint8Array.
*
* @throws {TypeError} If fixed-length data is not a number.
*/
ConcatKdf.toDataLenData = function (_a) {
var data = _a.data, _b = _a.variableLength, variableLength = _b === void 0 ? true : _b;
var encodedData;
var dataType = (0, common_1.universalTypeOf)(data);
// Return an emtpy octet sequence if data is not specified.
if (dataType === 'Undefined') {
return new Uint8Array(0);
}
if (variableLength) {
var dataU8A = (dataType === 'Uint8Array')
? data
: new common_1.Convert(data, dataType).toUint8Array();
var bufferLength = dataU8A.length;
encodedData = new Uint8Array(4 + bufferLength);
new DataView(encodedData.buffer).setUint32(0, bufferLength);
encodedData.set(dataU8A, 4);
}
else {
if (typeof data !== 'number') {
throw TypeError('Fixed length input must be a number.');
}
encodedData = new Uint8Array(4);
new DataView(encodedData.buffer).setUint32(0, data);
}
return encodedData;
};
return ConcatKdf;
}());
exports.ConcatKdf = ConcatKdf;
//# sourceMappingURL=concat-kdf.js.map
@@ -0,0 +1 @@
{"version":3,"file":"concat-kdf.js","sourceRoot":"","sources":["../../../src/primitives/concat-kdf.ts"],"names":[],"mappings":"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"}
+651
View File
@@ -0,0 +1,651 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Ed25519 = void 0;
var common_1 = require("@web5/common");
var ed25519_1 = require("@noble/curves/ed25519");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `Ed25519` class provides a comprehensive suite of utilities for working with the Ed25519
* elliptic curve, widely used in modern cryptographic applications. This class includes methods for
* key generation, conversion, signing, verification, and public key derivation.
*
* The class supports conversions between raw byte formats and JSON Web Key (JWK) formats. It
* follows the guidelines and specifications outlined in RFC8032 for EdDSA (Edwards-curve Digital
* Signature Algorithm) operations.
*
* Key Features:
* - Key Generation: Generate Ed25519 private keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Public Key Derivation: Derive public keys from private keys.
* - Signing and Verification: Sign data and verify signatures with Ed25519 keys.
* - Key Validation: Validate the mathematical correctness of Ed25519 keys.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments, and use `Uint8Array` for binary data handling.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await Ed25519.generateKey();
*
* // Public Key Derivation
* const publicKey = await Ed25519.computePublicKey({ key: privateKey });
* console.log(publicKey === await Ed25519.getPublicKey({ key: privateKey })); // Output: true
*
* // EdDSA Signing
* const signature = await Ed25519.sign({
* key: privateKey,
* data: new TextEncoder().encode('Message')
* });
*
* // EdDSA Signature Verification
* const isValid = await Ed25519.verify({
* key: publicKey,
* signature: signature,
* data: new TextEncoder().encode('Message')
* });
*
* // Key Conversion
* const privateKeyBytes = await Ed25519.privateKeyToBytes({ privateKey });
* const publicKeyBytes = await Ed25519.publicKeyToBytes({ publicKey });
*
* // Key Validation
* const isPublicKeyValid = await Ed25519.validatePublicKey({ publicKeyBytes });
* ```
*/
var Ed25519 = /** @class */ (function () {
function Ed25519() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a private key as a byte array (Uint8Array) for the Curve25519 curve in
* Twisted Edwards form and transforms it into a JWK object. The process involves first deriving
* the public key from the private key, then encoding both the private and public keys into
* base64url format.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'Ed25519'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The computed public key, base64url-encoded.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual private key bytes
* const privateKey = await Ed25519.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKeyBytes - The raw private key as a Uint8Array.
*
* @returns A Promise that resolves to the private key in JWK format.
*/
Ed25519.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
publicKeyBytes = ed25519_1.ed25519.getPublicKey(privateKeyBytes);
privateKey = {
crv: 'Ed25519',
d: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'OKP',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a public key as a byte array (Uint8Array) for the Curve25519 curve in
* Twisted Edwards form and transforms it into a JWK object. The process involves encoding the
* public key bytes into base64url format.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'X25519'.
* - `x`: The public key, base64url-encoded.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // Replace with actual public key bytes
* const publicKey = await X25519.bytesToPublicKey({ publicKeyBytes });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKeyBytes - The raw public key as a `Uint8Array`.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Ed25519.bytesToPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
publicKey = {
kty: 'OKP',
crv: 'Ed25519',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Derives the public key in JWK format from a given Ed25519 private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The derivation process involves converting the private key to a
* raw byte array and then computing the corresponding public key on the Curve25519 curve in
* Twisted Edwards form. The public key is then encoded into base64url format to construct
* a JWK representation.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing an Ed25519 private key
* const publicKey = await Ed25519.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the computed public key in JWK format.
*/
Ed25519.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, publicKeyBytes, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Ed25519.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _c.sent();
publicKeyBytes = ed25519_1.ed25519.getPublicKey(privateKeyBytes);
publicKey = {
kty: 'OKP',
crv: 'Ed25519',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts an Ed25519 private key to its X25519 counterpart.
*
* @remarks
* This method enables the use of the same key pair for both digital signature (Ed25519)
* and key exchange (X25519) operations. It takes an Ed25519 private key and converts it
* to the corresponding X25519 format, facilitating interoperability between signing
* and encryption protocols.
*
* @example
* ```ts
* const ed25519PrivateKey = { ... }; // An Ed25519 private key in JWK format
* const x25519PrivateKey = await Ed25519.convertPrivateKeyToX25519({
* privateKey: ed25519PrivateKey
* });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The Ed25519 private key to convert, in JWK format.
*
* @returns A Promise that resolves to the X25519 private key in JWK format.
*/
Ed25519.convertPrivateKeyToX25519 = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var ed25519PrivateKeyBytes, x25519PrivateKeyBytes, x25519PublicKeyBytes, x25519PrivateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Ed25519.privateKeyToBytes({ privateKey: privateKey })];
case 1:
ed25519PrivateKeyBytes = _c.sent();
x25519PrivateKeyBytes = (0, ed25519_1.edwardsToMontgomeryPriv)(ed25519PrivateKeyBytes);
x25519PublicKeyBytes = ed25519_1.x25519.getPublicKey(x25519PrivateKeyBytes);
x25519PrivateKey = {
kty: 'OKP',
crv: 'X25519',
d: common_1.Convert.uint8Array(x25519PrivateKeyBytes).toBase64Url(),
x: common_1.Convert.uint8Array(x25519PublicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = x25519PrivateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: x25519PrivateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, x25519PrivateKey];
}
});
});
};
/**
* Converts an Ed25519 public key to its X25519 counterpart.
*
* @remarks
* This method enables the use of the same key pair for both digital signature (Ed25519)
* and key exchange (X25519) operations. It takes an Ed25519 public key and converts it
* to the corresponding X25519 format, facilitating interoperability between signing
* and encryption protocols.
*
* @example
* ```ts
* const ed25519PublicKey = { ... }; // An Ed25519 public key in JWK format
* const x25519PublicKey = await Ed25519.convertPublicKeyToX25519({
* publicKey: ed25519PublicKey
* });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The Ed25519 public key to convert, in JWK format.
*
* @returns A Promise that resolves to the X25519 public key in JWK format.
*/
Ed25519.convertPublicKeyToX25519 = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var ed25519PublicKeyBytes, isValid, x25519PublicKeyBytes, x25519PublicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Ed25519.publicKeyToBytes({ publicKey: publicKey })];
case 1:
ed25519PublicKeyBytes = _c.sent();
return [4 /*yield*/, Ed25519.validatePublicKey({ publicKeyBytes: ed25519PublicKeyBytes })];
case 2:
isValid = _c.sent();
if (!isValid) {
throw new Error('Ed25519: Invalid public key.');
}
x25519PublicKeyBytes = (0, ed25519_1.edwardsToMontgomeryPub)(ed25519PublicKeyBytes);
x25519PublicKey = {
kty: 'OKP',
crv: 'X25519',
x: common_1.Convert.uint8Array(x25519PublicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = x25519PublicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: x25519PublicKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, x25519PublicKey];
}
});
});
};
/**
* Generates an Ed25519 private key in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new private key suitable for use with the Curve25519 elliptic curve in
* Twisted Edwards form. The key generation process involves using cryptographically secure
* random number generation to ensure the uniqueness and security of the key. The resulting
* private key adheres to the JWK format making it compatible with common cryptographic
* standards and easy to use in various cryptographic processes.
*
* The generated private key in JWK format includes the following components:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'Ed25519'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The derived public key, base64url-encoded.
*
* @example
* ```ts
* const privateKey = await Ed25519.generateKey();
* ```
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
Ed25519.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, privateKey, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
privateKeyBytes = ed25519_1.ed25519.utils.randomPrivateKey();
return [4 /*yield*/, Ed25519.bytesToPrivateKey({ privateKeyBytes: privateKeyBytes })];
case 1:
privateKey = _b.sent();
// Compute the JWK thumbprint and set as the key ID.
_a = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_a.kid = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an Ed25519 private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key. The method sets the 'kid' (key ID) property using the JWK thumbprint if it is not
* already defined. This approach is used under the assumption that a private key in JWK format
* always contains the corresponding public key properties.
*
* Note: This method offers a significant performance advantage, being about 100 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing an Ed25519 private key
* const publicKey = await Ed25519.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Ed25519.getPublicKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var d, publicKey, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Verify the provided JWK represents an octet key pair (OKP) Ed25519 private key.
if (!((0, jwk_js_1.isOkpPrivateJwk)(key) && key.crv === 'Ed25519')) {
throw new Error("Ed25519: The provided key is not an Ed25519 private JWK.");
}
d = key.d, publicKey = __rest(key, ["d"]);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
publicKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a private key in JWK format and extracts its raw byte representation.
*
* This method accepts a public key in JWK format and converts it into its raw binary
* form. The conversion process involves decoding the 'd' parameter of the JWK
* from base64url format into a byte array.
*
* @example
* ```ts
* const privateKey = { ... }; // An Ed25519 private key in JWK format
* const privateKeyBytes = await Ed25519.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The private key in JWK format.
*
* @returns A Promise that resolves to the private key as a Uint8Array.
*/
Ed25519.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid OKP private key.
if (!(0, jwk_js_1.isOkpPrivateJwk)(privateKey)) {
throw new Error("Ed25519: The provided key is not a valid OKP private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.d).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
/**
* Converts a public key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a public key in JWK format and converts it into its raw binary form.
* The conversion process involves decoding the 'x' parameter of the JWK (which represent the
* x coordinate of the elliptic curve point) from base64url format into a byte array.
*
* @example
* ```ts
* const publicKey = { ... }; // An Ed25519 public key in JWK format
* const publicKeyBytes = await Ed25519.publicKeyToBytes({ publicKey });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The public key in JWK format.
*
* @returns A Promise that resolves to the public key as a Uint8Array.
*/
Ed25519.publicKeyToBytes = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid OKP public key.
if (!(0, jwk_js_1.isOkpPublicJwk)(publicKey)) {
throw new Error("Ed25519: The provided key is not a valid OKP public key.");
}
publicKeyBytes = common_1.Convert.base64Url(publicKey.x).toUint8Array();
return [2 /*return*/, publicKeyBytes];
});
});
};
/**
* Generates an RFC8032-compliant EdDSA signature of given data using an Ed25519 private key.
*
* @remarks
* This method signs the provided data with a specified private key using the EdDSA
* (Edwards-curve Digital Signature Algorithm) as defined in RFC8032. It
* involves converting the private key from JWK format to a byte array and then employing
* the Ed25519 algorithm to sign the data. The output is a digital signature in the form
* of a Uint8Array, uniquely corresponding to both the data and the private key used for
* signing.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data to be signed
* const privateKey = { ... }; // A Jwk object representing an Ed25519 private key
* const signature = await Ed25519.sign({ key: privateKey, data });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign, represented as a Uint8Array.
*
* @returns A Promise that resolves to the signature as a Uint8Array.
*/
Ed25519.sign = function (_a) {
var key = _a.key, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, signature;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Ed25519.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
signature = ed25519_1.ed25519.sign(data, privateKeyBytes);
return [2 /*return*/, signature];
}
});
});
};
/**
* Validates a given public key to confirm its mathematical correctness on the Edwards curve.
*
* @remarks
* This method decodes the Edwards points from the key bytes and asserts their validity on the
* Curve25519 curve in Twisted Edwards form. If the points are not valid, the method returns
* false. If the points are valid, the method returns true.
*
* Note that this validation strictly pertains to the key's format and numerical validity; it does
* not assess whether the key corresponds to a known entity or its security status (e.g., whether
* it has been compromised).
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // A public key in byte format
* const isValid = await Ed25519.validatePublicKey({ publicKeyBytes });
* console.log(isValid); // true if the key is valid on the Edwards curve, false otherwise
* ```
*
* @param params - The parameters for the public key validation.
* @param params.publicKeyBytes - The public key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the key
* corresponds to a valid point on the Edwards curve.
*/
Ed25519.validatePublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
try {
point = ed25519_1.ed25519.ExtendedPoint.fromHex(publicKeyBytes);
// Check if points are on the Twisted Edwards curve.
point.assertValidity();
}
catch (error) {
return [2 /*return*/, false];
}
return [2 /*return*/, true];
});
});
};
/**
* Verifies an RFC8032-compliant EdDSA signature against given data using an Ed25519 public key.
*
* @remarks
* This method validates a digital signature to ensure its authenticity and integrity.
* It uses the EdDSA (Edwards-curve Digital Signature Algorithm) as specified in RFC8032.
* The verification process involves converting the public key from JWK format to a raw
* byte array and using the Ed25519 algorithm to validate the signature against the provided data.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data that was signed
* const publicKey = { ... }; // A Jwk object representing an Ed25519 public key
* const signature = new Uint8Array([...]); // Signature to verify
* const isValid = await Ed25519.verify({ key: publicKey, signature, data });
* console.log(isValid); // true if the signature is valid, false otherwise
* ```
*
* @param params - The parameters for the signature verification.
* @param params.key - The public key in JWK format used for verification.
* @param params.signature - The signature to verify, represented as a Uint8Array.
* @param params.data - The data that was signed, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the signature is valid.
*/
Ed25519.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, isValid;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Ed25519.publicKeyToBytes({ publicKey: key })];
case 1:
publicKeyBytes = _b.sent();
isValid = ed25519_1.ed25519.verify(signature, data, publicKeyBytes);
return [2 /*return*/, isValid];
}
});
});
};
return Ed25519;
}());
exports.Ed25519 = Ed25519;
//# sourceMappingURL=ed25519.js.map
File diff suppressed because one or more lines are too long
+120
View File
@@ -0,0 +1,120 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Pbkdf2 = void 0;
var crypto_1 = require("@noble/hashes/crypto");
/**
* The `Pbkdf2` class provides a secure way to derive cryptographic keys from a password
* using the PBKDF2 (Password-Based Key Derivation Function 2) algorithm.
*
* The PBKDF2 algorithm is widely used for generating keys from passwords, as it applies
* a pseudorandom function to the input password along with a salt value and iterates the
* process multiple times to increase the key's resistance to brute-force attacks.
*
* This class offers a single static method `deriveKey` to perform key derivation.
*
* @example
* ```ts
* // Key Derivation
* const derivedKey = await Pbkdf2.deriveKey({
* hash: 'SHA-256', // The hash function to use ('SHA-256', 'SHA-384', 'SHA-512')
* password: new TextEncoder().encode('password'), // The password as a Uint8Array
* salt: new Uint8Array([...]), // The salt value
* iterations: 1000, // The number of iterations
* length: 256 // The length of the derived key in bits
* });
* ```
*
* @remarks
* This class relies on the availability of the Web Crypto API.
*/
var Pbkdf2 = /** @class */ (function () {
function Pbkdf2() {
}
/**
* Derives a cryptographic key from a password using the PBKDF2 algorithm.
*
* @remarks
* This method applies the PBKDF2 algorithm to the provided password along with
* a salt value and iterates the process a specified number of times. It uses
* a cryptographic hash function to enhance security and produce a key of the
* desired length. The method is capable of utilizing either the Web Crypto API
* or the Node.js Crypto module, depending on the environment's support.
*
* @example
* ```ts
* const derivedKey = await Pbkdf2.deriveKey({
* hash: 'SHA-256',
* password: new TextEncoder().encode('password'),
* salt: new Uint8Array([...]),
* iterations: 1000,
* length: 256
* });
* ```
*
* @param params - The parameters for key derivation.
* @param params.hash - The hash function to use, such as 'SHA-256', 'SHA-384', or 'SHA-512'.
* @param params.password - The password from which to derive the key, represented as a Uint8Array.
* @param params.salt - The salt value to use in the derivation process, as a Uint8Array.
* @param params.iterations - The number of iterations to apply in the PBKDF2 algorithm.
* @param params.length - The desired length of the derived key in bits.
*
* @returns A Promise that resolves to the derived key as a Uint8Array.
*/
Pbkdf2.deriveKey = function (_a) {
var hash = _a.hash, password = _a.password, salt = _a.salt, iterations = _a.iterations, length = _a.length;
return __awaiter(this, void 0, void 0, function () {
var webCryptoKey, derivedKeyBuffer, derivedKey;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, crypto_1.crypto.subtle.importKey('raw', password, { name: 'PBKDF2' }, false, ['deriveBits'])];
case 1:
webCryptoKey = _b.sent();
return [4 /*yield*/, crypto_1.crypto.subtle.deriveBits({ name: 'PBKDF2', hash: hash, salt: salt, iterations: iterations }, webCryptoKey, length)];
case 2:
derivedKeyBuffer = _b.sent();
derivedKey = new Uint8Array(derivedKeyBuffer);
return [2 /*return*/, derivedKey];
}
});
});
};
return Pbkdf2;
}());
exports.Pbkdf2 = Pbkdf2;
//# sourceMappingURL=pbkdf2.js.map
@@ -0,0 +1 @@
{"version":3,"file":"pbkdf2.js","sourceRoot":"","sources":["../../../src/primitives/pbkdf2.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA8C;AA0C9C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH;IAAA;IAsDA,CAAC;IArDC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACiB,gBAAS,GAA7B,UAA8B,EACP;YADS,IAAI,UAAA,EAAE,QAAQ,cAAA,EAAE,IAAI,UAAA,EAAE,UAAU,gBAAA,EAAE,MAAM,YAAA;;;;;4BAIjD,qBAAM,eAAM,CAAC,MAAM,CAAC,SAAS,CAChD,KAAK,EACL,QAAQ,EACR,EAAE,IAAI,EAAE,QAAQ,EAAE,EAClB,KAAK,EACL,CAAC,YAAY,CAAC,CACf,EAAA;;wBANK,YAAY,GAAG,SAMpB;wBAEwB,qBAAM,eAAM,CAAC,MAAM,CAAC,UAAU,CACrD,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,MAAA,EAAE,IAAI,MAAA,EAAE,UAAU,YAAA,EAAE,EAC1C,YAAY,EACZ,MAAM,CACP,EAAA;;wBAJK,gBAAgB,GAAG,SAIxB;wBAGK,UAAU,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC,CAAC;wBAEpD,sBAAO,UAAU,EAAC;;;;KACnB;IACH,aAAC;AAAD,CAAC,AAtDD,IAsDC;AAtDY,wBAAM"}
@@ -0,0 +1,958 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Secp256k1 = void 0;
var common_1 = require("@web5/common");
var sha256_1 = require("@noble/hashes/sha256");
var secp256k1_1 = require("@noble/curves/secp256k1");
var utils_1 = require("@noble/curves/abstract/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `Secp256k1` class provides a comprehensive suite of utilities for working with
* the secp256k1 elliptic curve, commonly used in blockchain and cryptographic applications.
* This class includes methods for key generation, conversion, signing, verification, and
* Elliptic Curve Diffie-Hellman (ECDH) key agreement.
*
* The class supports conversions between raw byte formats and JSON Web Key (JWK) formats. It
* adheres to RFC6979 for ECDSA signing and verification and RFC6090 for ECDH.
*
* Key Features:
* - Key Generation: Generate secp256k1 private keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Public Key Derivation: Derive public keys from private keys.
* - ECDH Shared Secret Computation: Securely derive shared secrets using private and public keys.
* - ECDSA Signing and Verification: Sign data and verify signatures with secp256k1 keys.
* - Key Validation: Validate the mathematical correctness of secp256k1 keys.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments, and use `Uint8Array` for binary data handling.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await Secp256k1.generateKey();
*
* // Public Key Derivation
* const publicKey = await Secp256k1.computePublicKey({ key: privateKey });
* console.log(publicKey === await Secp256k1.getPublicKey({ key: privateKey })); // Output: true
*
* // ECDH Shared Secret Computation
* const sharedSecret = await Secp256k1.sharedSecret({
* privateKeyA: privateKey,
* publicKeyB: anotherPublicKey
* });
*
* // ECDSA Signing
* const signature = await Secp256k1.sign({
* key: privateKey,
* data: new TextEncoder().encode('Message')
* });
*
* // ECDSA Signature Verification
* const isValid = await Secp256k1.verify({
* key: publicKey,
* signature: signature,
* data: new TextEncoder().encode('Message')
* });
*
* // Key Conversion
* const publicKeyBytes = await Secp256k1.publicKeyToBytes({ publicKey });
* const privateKeyBytes = await Secp256k1.privateKeyToBytes({ privateKey });
* const compressedPublicKey = await Secp256k1.compressPublicKey({ publicKeyBytes });
* const uncompressedPublicKey = await Secp256k1.decompressPublicKey({ publicKeyBytes });
*
* // Key Validation
* const isPrivateKeyValid = await Secp256k1.validatePrivateKey({ privateKeyBytes });
* const isPublicKeyValid = await Secp256k1.validatePublicKey({ publicKeyBytes });
* ```
*/
var Secp256k1 = /** @class */ (function () {
function Secp256k1() {
}
/**
* Adjusts an ECDSA signature to a normalized, low-S form.
*
* @remarks
* All ECDSA signatures, regardless of the curve, consist of two components, `r` and `s`, both of
* which are integers. The curve's order (the total number of points on the curve) is denoted by
* `n`. In a valid ECDSA signature, both `r` and `s` must be in the range [1, n-1]. However, due
* to the mathematical properties of ECDSA, if `(r, s)` is a valid signature, then `(r, n - s)` is
* also a valid signature for the same message and public key. In other words, for every
* signature, there's a "mirror" signature that's equally valid. For these elliptic curves:
*
* - Low S Signature: A signature where the `s` component is in the lower half of the range,
* specifically less than or equal to `n/2`.
*
* - High S Signature: This is where the `s` component is in the upper half of the range, greater
* than `n/2`.
*
* The practical implication is that a third-party can forge a second valid signature for the same
* message by negating the `s` component of the original signature, without any knowledge of the
* private key. This is known as a "signature malleability" attack.
*
* This type of forgery is not a problem in all systems, but it can be an issue in systems that
* rely on digital signature uniqueness to ensure transaction integrity. For example, in Bitcoin,
* transaction malleability is an issue because it allows for the modification of transaction
* identifiers (and potentially, transactions themselves) after they're signed but before they're
* confirmed in a block. By enforcing low `s` values, the Bitcoin network reduces the likelihood of
* this occurring, making the system more secure and predictable.
*
* For this reason, it's common practice to normalize ECDSA signatures to a low-S form. This
* form is considered standard and preferable in some systems and is known as the "normalized"
* form of the signature.
*
* This method takes a signature, and if it's high-S, returns the normalized low-S form. If the
* signature is already low-S, it's returned unmodified. It's important to note that this
* method does not change the validity of the signature but makes it compliant with systems that
* enforce low-S signatures.
*
* @example
* ```ts
* const signature = new Uint8Array([...]); // Your ECDSA signature
* const adjustedSignature = await Secp256k1.adjustSignatureToLowS({ signature });
* // Now 'adjustedSignature' is in the low-S form.
* ```
*
* @param params - The parameters for the signature adjustment.
* @param params.signature - The ECDSA signature as a `Uint8Array`.
*
* @returns A Promise that resolves to the adjusted signature in low-S form as a `Uint8Array`.
*/
Secp256k1.adjustSignatureToLowS = function (_a) {
var signature = _a.signature;
return __awaiter(this, void 0, void 0, function () {
var signatureObject, adjustedSignatureObject, adjustedSignature;
return __generator(this, function (_b) {
signatureObject = secp256k1_1.secp256k1.Signature.fromCompact(signature);
if (signatureObject.hasHighS()) {
adjustedSignatureObject = signatureObject.normalizeS();
adjustedSignature = adjustedSignatureObject.toCompactRawBytes();
return [2 /*return*/, adjustedSignature];
}
else {
// Return the unmodified signature if it is already in low-S format.
return [2 /*return*/, signature];
}
return [2 /*return*/];
});
});
};
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a private key represented as a byte array (Uint8Array) and
* converts it into a JWK object. The conversion involves extracting the
* elliptic curve point (x and y coordinates) from the private key and encoding
* them into base64url format, alongside other JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'secp256k1'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The x-coordinate of the public key point, base64url-encoded.
* - `y`: The y-coordinate of the public key point, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual private key bytes
* const privateKey = await Secp256k1.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKeyBytes - The raw private key as a Uint8Array.
*
* @returns A Promise that resolves to the private key in JWK format.
*/
Secp256k1.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256k1.getCurvePoint({ keyBytes: privateKeyBytes })];
case 1:
point = _c.sent();
privateKey = {
kty: 'EC',
crv: 'secp256k1',
d: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a raw public key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a public key in a byte array (Uint8Array) format and
* transforms it to a JWK object. It involves decoding the elliptic curve point
* (x and y coordinates) from the raw public key bytes and encoding them into
* base64url format, along with setting appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'secp256k1'.
* - `x`: The x-coordinate of the public key point, base64url-encoded.
* - `y`: The y-coordinate of the public key point, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // Replace with actual public key bytes
* const publicKey = await Secp256k1.bytesToPublicKey({ publicKeyBytes });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKeyBytes - The raw public key as a Uint8Array.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Secp256k1.bytesToPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256k1.getCurvePoint({ keyBytes: publicKeyBytes })];
case 1:
point = _c.sent();
publicKey = {
kty: 'EC',
crv: 'secp256k1',
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a public key to its compressed form.
*
* @remarks
* This method takes a public key represented as a byte array and compresses it. Public key
* compression is a process that reduces the size of the public key by removing the y-coordinate,
* making it more efficient for storage and transmission. The compressed key retains the same
* level of security as the uncompressed key.
*
* @example
* ```ts
* const uncompressedPublicKeyBytes = new Uint8Array([...]); // Replace with actual uncompressed public key bytes
* const compressedPublicKey = await Secp256k1.compressPublicKey({
* publicKeyBytes: uncompressedPublicKeyBytes
* });
* ```
*
* @param params - The parameters for the public key compression.
* @param params.publicKeyBytes - The public key as a Uint8Array.
*
* @returns A Promise that resolves to the compressed public key as a Uint8Array.
*/
Secp256k1.compressPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(publicKeyBytes);
// Return the compressed form of the public key.
return [2 /*return*/, point.toRawBytes(true)];
});
});
};
/**
* Derives the public key in JWK format from a given private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The derivation process involves converting the private key to a raw
* byte array, then computing the elliptic curve point (x and y coordinates) from this private
* key. These coordinates are then encoded into base64url format to construct the public key in
* JWK format.
*
* The process ensures that the derived public key correctly corresponds to the given private key,
* adhering to the secp256k1 elliptic curve standards. This method is useful in cryptographic
* operations where a public key is needed for operations like signature verification, but only
* the private key is available.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing a secp256k1 private key
* const publicKey = await Secp256k1.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
Secp256k1.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, point, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256k1.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _c.sent();
return [4 /*yield*/, Secp256k1.getCurvePoint({ keyBytes: privateKeyBytes })];
case 2:
point = _c.sent();
publicKey = {
kty: 'EC',
crv: 'secp256k1',
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts an ASN.1 DER encoded ECDSA signature to a compact R+S format.
*
* @remarks
* This method is used for converting an ECDSA signature from the ASN.1 DER encoding to the more
* compact R+S format. This conversion is often required when dealing with ECDSA signatures in
* certain cryptographic standards such as JWS (JSON Web Signature).
*
* The method decodes the DER-encoded signature, extracts the R and S values, and concatenates
* them into a single byte array. This process involves handling the ASN.1 structure to correctly
* parse the R and S values, considering padding and integer encoding specifics of DER.
*
* @example
* ```ts
* const derSignature = new Uint8Array([...]); // Replace with your DER-encoded signature
* const signature = await Secp256k1.convertDerToCompactSignature({ derSignature });
* ```
*
* @param params - The parameters for the signature conversion.
* @param params.derSignature - The signature in ASN.1 DER format as a `Uint8Array`.
*
* @returns A Promise that resolves to the signature in compact R+S format as a `Uint8Array`.
*/
Secp256k1.convertDerToCompactSignature = function (_a) {
var derSignature = _a.derSignature;
return __awaiter(this, void 0, void 0, function () {
var signatureObject, compactSignature;
return __generator(this, function (_b) {
signatureObject = secp256k1_1.secp256k1.Signature.fromDER(derSignature);
compactSignature = signatureObject.toCompactRawBytes();
return [2 /*return*/, compactSignature];
});
});
};
/**
* Converts a public key to its uncompressed form.
*
* @remarks
* This method takes a compressed public key represented as a byte array and decompresses it.
* Public key decompression involves reconstructing the y-coordinate from the x-coordinate,
* resulting in the full public key. This method is used when the uncompressed key format is
* required for certain cryptographic operations or interoperability.
*
* @example
* ```ts
* const compressedPublicKeyBytes = new Uint8Array([...]); // Replace with actual compressed public key bytes
* const decompressedPublicKey = await Secp256k1.decompressPublicKey({
* publicKeyBytes: compressedPublicKeyBytes
* });
* ```
*
* @param params - The parameters for the public key decompression.
* @param params.publicKeyBytes - The public key as a Uint8Array.
*
* @returns A Promise that resolves to the uncompressed public key as a Uint8Array.
*/
Secp256k1.decompressPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(publicKeyBytes);
// Return the uncompressed form of the public key.
return [2 /*return*/, point.toRawBytes(false)];
});
});
};
/**
* Generates a secp256k1 private key in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new private key suitable for use with the secp256k1
* elliptic curve. The key is generated using cryptographically secure random
* number generation to ensure its uniqueness and security. The resulting
* private key adheres to the JWK format, specifically tailored for secp256k1,
* making it compatible with common cryptographic standards and easy to use in
* various cryptographic processes.
*
* The private key generated by this method includes the following components:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'secp256k1'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The x-coordinate of the public key point, derived from the private key, base64url-encoded.
* - `y`: The y-coordinate of the public key point, derived from the private key, base64url-encoded.
*
* The key is returned in a format suitable for direct use in signin and key agreement operations.
*
* @example
* ```ts
* const privateKey = await Secp256k1.generateKey();
* ```
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
Secp256k1.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, privateKey, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
privateKeyBytes = secp256k1_1.secp256k1.utils.randomPrivateKey();
return [4 /*yield*/, Secp256k1.bytesToPrivateKey({ privateKeyBytes: privateKeyBytes })];
case 1:
privateKey = _b.sent();
// Compute the JWK thumbprint and set as the key ID.
_a = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_a.kid = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from a secp256k1 private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key. The method sets the 'kid' (key ID) property using the JWK thumbprint if it is not
* already defined. This approach is used under the assumption that a private key in JWK format
* always contains the corresponding public key properties.
*
* Note: This method offers a significant performance advantage, being about 200 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing a secp256k1 private key
* const publicKey = await Secp256k1.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Secp256k1.getPublicKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var d, publicKey, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Verify the provided JWK represents an elliptic curve (EC) secp256k1 private key.
if (!((0, jwk_js_1.isEcPrivateJwk)(key) && key.crv === 'secp256k1')) {
throw new Error("Secp256k1: The provided key is not a secp256k1 private JWK.");
}
d = key.d, publicKey = __rest(key, ["d"]);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
publicKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a private key in JWK format and extracts its raw byte representation.
* It specifically focuses on the 'd' parameter of the JWK, which represents the private
* key component in base64url encoding. The method decodes this value into a byte array.
*
* This conversion is essential for operations that require the private key in its raw
* binary form, such as certain low-level cryptographic operations or when interfacing
* with systems and libraries that expect keys in a byte array format.
*
* @example
* ```ts
* const privateKey = { ... }; // An X25519 private key in JWK format
* const privateKeyBytes = await Secp256k1.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The private key in JWK format.
*
* @returns A Promise that resolves to the private key as a Uint8Array.
*/
Secp256k1.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid EC secp256k1 private key.
if (!(0, jwk_js_1.isEcPrivateJwk)(privateKey)) {
throw new Error("Secp256k1: The provided key is not a valid EC private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.d).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
/**
* Converts a public key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a public key in JWK format and converts it into its raw binary
* form. The conversion process involves decoding the 'x' and 'y' parameters of the JWK
* (which represent the x and y coordinates of the elliptic curve point, respectively)
* from base64url format into a byte array. The method then concatenates these values,
* along with a prefix indicating the key format, to form the full public key.
*
* This function is particularly useful for use cases where the public key is needed
* in its raw byte format, such as for certain cryptographic operations or when
* interfacing with systems that require raw key formats.
*
* @example
* ```ts
* const publicKey = { ... }; // A Jwk public key object
* const publicKeyBytes = await Secp256k1.publicKeyToBytes({ publicKey });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The public key in JWK format.
*
* @returns A Promise that resolves to the public key as a Uint8Array.
*/
Secp256k1.publicKeyToBytes = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var prefix, x, y, publicKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid EC secp256k1 public key, which must have a 'y' value.
if (!((0, jwk_js_1.isEcPublicJwk)(publicKey) && publicKey.y)) {
throw new Error("Secp256k1: The provided key is not a valid EC public key.");
}
prefix = new Uint8Array([0x04]);
x = common_1.Convert.base64Url(publicKey.x).toUint8Array();
y = common_1.Convert.base64Url(publicKey.y).toUint8Array();
publicKeyBytes = new Uint8Array(__spreadArray(__spreadArray(__spreadArray([], __read(prefix), false), __read(x), false), __read(y), false));
return [2 /*return*/, publicKeyBytes];
});
});
};
/**
* Computes an RFC6090-compliant Elliptic Curve Diffie-Hellman (ECDH) shared secret
* using secp256k1 private and public keys in JSON Web Key (JWK) format.
*
* @remarks
* This method facilitates the ECDH key agreement protocol, which is a method of securely
* deriving a shared secret between two parties based on their private and public keys.
* It takes the private key of one party (privateKeyA) and the public key of another
* party (publicKeyB) to compute a shared secret. The shared secret is derived from the
* x-coordinate of the elliptic curve point resulting from the multiplication of the
* public key with the private key.
*
* Note: When performing Elliptic Curve Diffie-Hellman (ECDH) key agreement,
* the resulting shared secret is a point on the elliptic curve, which
* consists of an x-coordinate and a y-coordinate. With a 256-bit curve like
* secp256k1, each of these coordinates is 32 bytes (256 bits) long. However,
* in the ECDH process, it's standard practice to use only the x-coordinate
* of the shared secret point as the resulting shared key. This is because
* the y-coordinate does not add to the entropy of the key, and both parties
* can independently compute the x-coordinate. Consquently, this implementation
* omits the y-coordinate for simplicity and standard compliance.
*
* @example
* ```ts
* const privateKeyA = { ... }; // A Jwk private key object for party A
* const publicKeyB = { ... }; // A Jwk public key object for party B
* const sharedSecret = await Secp256k1.sharedSecret({
* privateKeyA,
* publicKeyB
* });
* ```
*
* @param params - The parameters for the shared secret computation.
* @param params.privateKeyA - The private key in JWK format of one party.
* @param params.publicKeyB - The public key in JWK format of the other party.
*
* @returns A Promise that resolves to the computed shared secret as a Uint8Array.
*/
Secp256k1.sharedSecret = function (_a) {
var privateKeyA = _a.privateKeyA, publicKeyB = _a.publicKeyB;
return __awaiter(this, void 0, void 0, function () {
var privateKeyABytes, publicKeyBBytes, sharedSecret;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Ensure that keys from the same key pair are not specified.
if ('x' in privateKeyA && 'x' in publicKeyB && privateKeyA.x === publicKeyB.x) {
throw new Error("Secp256k1: ECDH shared secret cannot be computed from a single key pair's public and private keys.");
}
return [4 /*yield*/, Secp256k1.privateKeyToBytes({ privateKey: privateKeyA })];
case 1:
privateKeyABytes = _b.sent();
return [4 /*yield*/, Secp256k1.publicKeyToBytes({ publicKey: publicKeyB })];
case 2:
publicKeyBBytes = _b.sent();
sharedSecret = secp256k1_1.secp256k1.getSharedSecret(privateKeyABytes, publicKeyBBytes, true);
// Remove the leading byte that indicates the sign of the y-coordinate
// of the point on the elliptic curve. See note above.
return [2 /*return*/, sharedSecret.slice(1)];
}
});
});
};
/**
* Generates an RFC6979-compliant ECDSA signature of given data using a secp256k1 private key.
*
* @remarks
* This method signs the provided data with a specified private key using the ECDSA
* (Elliptic Curve Digital Signature Algorithm) signature algorithm, as defined in RFC6979.
* The data to be signed is first hashed using the SHA-256 algorithm, and this hash is then
* signed using the private key. The output is a digital signature in the form of a
* Uint8Array, which uniquely corresponds to both the data and the private key used for signing.
*
* This method is commonly used in cryptographic applications to ensure data integrity and
* authenticity. The signature can later be verified by parties with access to the corresponding
* public key, ensuring that the data has not been tampered with and was indeed signed by the
* holder of the private key.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data to be signed
* const privateKey = { ... }; // A Jwk object representing a secp256k1 private key
* const signature = await Secp256k1.sign({
* key: privateKey,
* data
* });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign, represented as a Uint8Array.
*
* @returns A Promise that resolves to the signature as a Uint8Array.
*/
Secp256k1.sign = function (_a) {
var data = _a.data, key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, digest, signatureObject, signature;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Secp256k1.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
digest = (0, sha256_1.sha256)(data);
signatureObject = secp256k1_1.secp256k1.sign(digest, privateKeyBytes);
signature = signatureObject.toCompactRawBytes();
return [2 /*return*/, signature];
}
});
});
};
/**
* Validates a given private key to ensure its compliance with the secp256k1 curve standards.
*
* @remarks
* This method checks whether a provided private key is a valid 32-byte number and falls within
* the range defined by the secp256k1 curve's order. It is essential for ensuring the private
* key's mathematical correctness in the context of secp256k1-based cryptographic operations.
*
* Note that this validation strictly pertains to the key's format and numerical validity; it does
* not assess whether the key corresponds to a known entity or its security status (e.g., whether
* it has been compromised).
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // A 32-byte private key
* const isValid = await Secp256k1.validatePrivateKey({ privateKeyBytes });
* console.log(isValid); // true or false based on the key's validity
* ```
*
* @param params - The parameters for the key validation.
* @param params.privateKeyBytes - The private key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the private key is valid.
*/
Secp256k1.validatePrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_b) {
return [2 /*return*/, secp256k1_1.secp256k1.utils.isValidPrivateKey(privateKeyBytes)];
});
});
};
/**
* Validates a given public key to confirm its mathematical correctness on the secp256k1 curve.
*
* @remarks
* This method checks if the provided public key represents a valid point on the secp256k1 curve.
* It decodes the key's Weierstrass points (x and y coordinates) and verifies their validity
* against the curve's parameters. A valid point must lie on the curve and meet specific
* mathematical criteria defined by the curve's equation.
*
* It's important to note that this method does not verify the key's ownership or whether it has
* been compromised; it solely focuses on the key's adherence to the curve's mathematical
* principles.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // A public key in byte format
* const isValid = await Secp256k1.validatePublicKey({ publicKeyBytes });
* console.log(isValid); // true if the key is valid on the secp256k1 curve, false otherwise
* ```
*
* @param params - The parameters for the key validation.
* @param params.publicKeyBytes - The public key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating the public key's validity on
* the secp256k1 curve.
*/
Secp256k1.validatePublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
try {
point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(publicKeyBytes);
// Check if points are on the Short Weierstrass curve.
point.assertValidity();
}
catch (error) {
return [2 /*return*/, false];
}
return [2 /*return*/, true];
});
});
};
/**
* Verifies an RFC6979-compliant ECDSA signature against given data and a secp256k1 public key.
*
* @remarks
* This method validates a digital signature to ensure that it was generated by the holder of the
* corresponding private key and that the signed data has not been altered. The signature
* verification is performed using the ECDSA (Elliptic Curve Digital Signature Algorithm) as
* specified in RFC6979. The data to be verified is first hashed using the SHA-256 algorithm, and
* this hash is then used along with the public key to verify the signature.
*
* The method returns a boolean value indicating whether the signature is valid. A valid signature
* proves that the signed data was indeed signed by the owner of the private key corresponding to
* the provided public key and that the data has not been tampered with since it was signed.
*
* Note: The verification process does not consider the malleability of low-s signatures, which
* may be relevant in certain contexts, such as Bitcoin transactions.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data that was signed
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const isSignatureValid = await Secp256k1.verify({
* key: publicKey,
* signature,
* data
* });
* console.log(isSignatureValid); // true if the signature is valid, false otherwise
* ```
*
* @param params - The parameters for the signature verification.
* @param params.key - The public key used for verification, represented in JWK format.
* @param params.signature - The signature to verify, represented as a Uint8Array.
* @param params.data - The data that was signed, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the signature is valid.
*/
Secp256k1.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, digest, isValid;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Secp256k1.publicKeyToBytes({ publicKey: key })];
case 1:
publicKeyBytes = _b.sent();
digest = (0, sha256_1.sha256)(data);
isValid = secp256k1_1.secp256k1.verify(signature, digest, publicKeyBytes, { lowS: false });
return [2 /*return*/, isValid];
}
});
});
};
/**
* Returns the elliptic curve point (x and y coordinates) for a given secp256k1 key.
*
* @remarks
* This method extracts the elliptic curve point from a given secp256k1 key, whether
* it's a private or a public key. For a private key, the method first computes the
* corresponding public key and then extracts the x and y coordinates. For a public key,
* it directly returns these coordinates. The coordinates are represented as Uint8Array.
*
* The x and y coordinates represent the key's position on the elliptic curve and can be
* used in various cryptographic operations, such as digital signatures or key agreement
* protocols.
*
* @example
* ```ts
* // For a private key
* const privateKey = new Uint8Array([...]); // A 32-byte private key
* const { x: xFromPrivateKey, y: yFromPrivateKey } = await Secp256k1.getCurvePoint({ keyBytes: privateKey });
*
* // For a public key
* const publicKey = new Uint8Array([...]); // A 33-byte or 65-byte public key
* const { x: xFromPublicKey, y: yFromPublicKey } = await Secp256k1.getCurvePoint({ keyBytes: publicKey });
* ```
*
* @param params - The parameters for the curve point decoding operation.
* @param params.keyBytes - The key for which to get the elliptic curve point.
* Can be either a private key or a public key.
* The key should be passed as a `Uint8Array`.
*
* @returns A Promise that resolves to an object with properties 'x' and 'y',
* each being a Uint8Array representing the x and y coordinates of the key point on the
* elliptic curve.
*/
Secp256k1.getCurvePoint = function (_a) {
var keyBytes = _a.keyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, x, y;
return __generator(this, function (_b) {
// If key is a private key, first compute the public key.
if (keyBytes.byteLength === 32) {
keyBytes = secp256k1_1.secp256k1.getPublicKey(keyBytes);
}
point = secp256k1_1.secp256k1.ProjectivePoint.fromHex(keyBytes);
x = (0, utils_1.numberToBytesBE)(point.x, 32);
y = (0, utils_1.numberToBytesBE)(point.y, 32);
return [2 /*return*/, { x: x, y: y }];
});
});
};
return Secp256k1;
}());
exports.Secp256k1 = Secp256k1;
//# sourceMappingURL=secp256k1.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,959 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.P256 = exports.Secp256r1 = void 0;
var common_1 = require("@web5/common");
var sha256_1 = require("@noble/hashes/sha256");
var p256_1 = require("@noble/curves/p256");
var utils_1 = require("@noble/curves/abstract/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `Secp256r1` class provides a comprehensive suite of utilities for working with
* the secp256r1 (aka P-256) elliptic curve, commonly used in blockchain and cryptographic
* applications. This class includes methods for key generation, conversion, signing, verification,
* and Elliptic Curve Diffie-Hellman (ECDH) key agreement.
*
* The class supports conversions between raw byte formats and JSON Web Key (JWK) formats. It
* adheres to RFC6979 for ECDSA signing and verification and RFC6090 for ECDH.
*
* Key Features:
* - Key Generation: Generate secp256r1 private keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Public Key Derivation: Derive public keys from private keys.
* - ECDH Shared Secret Computation: Securely derive shared secrets using private and public keys.
* - ECDSA Signing and Verification: Sign data and verify signatures with secp256r1 keys.
* - Key Validation: Validate the mathematical correctness of secp256r1 keys.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments, and use `Uint8Array` for binary data handling.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await Secp256r1.generateKey();
*
* // Public Key Derivation
* const publicKey = await Secp256r1.computePublicKey({ key: privateKey });
* console.log(publicKey === await Secp256r1.getPublicKey({ key: privateKey })); // Output: true
*
* // ECDH Shared Secret Computation
* const sharedSecret = await Secp256r1.sharedSecret({
* privateKeyA: privateKey,
* publicKeyB: anotherPublicKey
* });
*
* // ECDSA Signing
* const signature = await Secp256r1.sign({
* key: privateKey,
* data: new TextEncoder().encode('Message')
* });
*
* // ECDSA Signature Verification
* const isValid = await Secp256r1.verify({
* key: publicKey,
* signature: signature,
* data: new TextEncoder().encode('Message')
* });
*
* // Key Conversion
* const publicKeyBytes = await Secp256r1.publicKeyToBytes({ publicKey });
* const privateKeyBytes = await Secp256r1.privateKeyToBytes({ privateKey });
* const compressedPublicKey = await Secp256r1.compressPublicKey({ publicKeyBytes });
* const uncompressedPublicKey = await Secp256r1.decompressPublicKey({ publicKeyBytes });
*
* // Key Validation
* const isPrivateKeyValid = await Secp256r1.validatePrivateKey({ privateKeyBytes });
* const isPublicKeyValid = await Secp256r1.validatePublicKey({ publicKeyBytes });
* ```
*/
var Secp256r1 = /** @class */ (function () {
function Secp256r1() {
}
/**
* Adjusts an ECDSA signature to a normalized, low-S form.
*
* @remarks
* All ECDSA signatures, regardless of the curve, consist of two components, `r` and `s`, both of
* which are integers. The curve's order (the total number of points on the curve) is denoted by
* `n`. In a valid ECDSA signature, both `r` and `s` must be in the range [1, n-1]. However, due
* to the mathematical properties of ECDSA, if `(r, s)` is a valid signature, then `(r, n - s)` is
* also a valid signature for the same message and public key. In other words, for every
* signature, there's a "mirror" signature that's equally valid. For these elliptic curves:
*
* - Low S Signature: A signature where the `s` component is in the lower half of the range,
* specifically less than or equal to `n/2`.
*
* - High S Signature: This is where the `s` component is in the upper half of the range, greater
* than `n/2`.
*
* The practical implication is that a third-party can forge a second valid signature for the same
* message by negating the `s` component of the original signature, without any knowledge of the
* private key. This is known as a "signature malleability" attack.
*
* This type of forgery is not a problem in all systems, but it can be an issue in systems that
* rely on digital signature uniqueness to ensure transaction integrity. For example, in Bitcoin,
* transaction malleability is an issue because it allows for the modification of transaction
* identifiers (and potentially, transactions themselves) after they're signed but before they're
* confirmed in a block. By enforcing low `s` values, the Bitcoin network reduces the likelihood of
* this occurring, making the system more secure and predictable.
*
* For this reason, it's common practice to normalize ECDSA signatures to a low-S form. This
* form is considered standard and preferable in some systems and is known as the "normalized"
* form of the signature.
*
* This method takes a signature, and if it's high-S, returns the normalized low-S form. If the
* signature is already low-S, it's returned unmodified. It's important to note that this
* method does not change the validity of the signature but makes it compliant with systems that
* enforce low-S signatures.
*
* @example
* ```ts
* const signature = new Uint8Array([...]); // Your ECDSA signature
* const adjustedSignature = await Secp256r1.adjustSignatureToLowS({ signature });
* // Now 'adjustedSignature' is in the low-S form.
* ```
*
* @param params - The parameters for the signature adjustment.
* @param params.signature - The ECDSA signature as a `Uint8Array`.
*
* @returns A Promise that resolves to the adjusted signature in low-S form as a `Uint8Array`.
*/
Secp256r1.adjustSignatureToLowS = function (_a) {
var signature = _a.signature;
return __awaiter(this, void 0, void 0, function () {
var signatureObject, adjustedSignatureObject, adjustedSignature;
return __generator(this, function (_b) {
signatureObject = p256_1.secp256r1.Signature.fromCompact(signature);
if (signatureObject.hasHighS()) {
adjustedSignatureObject = signatureObject.normalizeS();
adjustedSignature = adjustedSignatureObject.toCompactRawBytes();
return [2 /*return*/, adjustedSignature];
}
else {
// Return the unmodified signature if it is already in low-S format.
return [2 /*return*/, signature];
}
return [2 /*return*/];
});
});
};
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a private key represented as a byte array (Uint8Array) and
* converts it into a JWK object. The conversion involves extracting the
* elliptic curve point (x and y coordinates) from the private key and encoding
* them into base64url format, alongside other JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'P-256'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The x-coordinate of the public key point, base64url-encoded.
* - `y`: The y-coordinate of the public key point, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual private key bytes
* const privateKey = await Secp256r1.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKeyBytes - The raw private key as a Uint8Array.
*
* @returns A Promise that resolves to the private key in JWK format.
*/
Secp256r1.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256r1.getCurvePoint({ keyBytes: privateKeyBytes })];
case 1:
point = _c.sent();
privateKey = {
kty: 'EC',
crv: 'P-256',
d: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a raw public key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a public key in a byte array (Uint8Array) format and
* transforms it to a JWK object. It involves decoding the elliptic curve point
* (x and y coordinates) from the raw public key bytes and encoding them into
* base64url format, along with setting appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'P-256'.
* - `x`: The x-coordinate of the public key point, base64url-encoded.
* - `y`: The y-coordinate of the public key point, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // Replace with actual public key bytes
* const publicKey = await Secp256r1.bytesToPublicKey({ publicKeyBytes });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKeyBytes - The raw public key as a Uint8Array.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Secp256r1.bytesToPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256r1.getCurvePoint({ keyBytes: publicKeyBytes })];
case 1:
point = _c.sent();
publicKey = {
kty: 'EC',
crv: 'P-256',
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a public key to its compressed form.
*
* @remarks
* This method takes a public key represented as a byte array and compresses it. Public key
* compression is a process that reduces the size of the public key by removing the y-coordinate,
* making it more efficient for storage and transmission. The compressed key retains the same
* level of security as the uncompressed key.
*
* @example
* ```ts
* const uncompressedPublicKeyBytes = new Uint8Array([...]); // Replace with actual uncompressed public key bytes
* const compressedPublicKey = await Secp256r1.compressPublicKey({
* publicKeyBytes: uncompressedPublicKeyBytes
* });
* ```
*
* @param params - The parameters for the public key compression.
* @param params.publicKeyBytes - The public key as a Uint8Array.
*
* @returns A Promise that resolves to the compressed public key as a Uint8Array.
*/
Secp256r1.compressPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
point = p256_1.secp256r1.ProjectivePoint.fromHex(publicKeyBytes);
// Return the compressed form of the public key.
return [2 /*return*/, point.toRawBytes(true)];
});
});
};
/**
* Derives the public key in JWK format from a given private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The derivation process involves converting the private key to a raw
* byte array, then computing the elliptic curve point (x and y coordinates) from this private
* key. These coordinates are then encoded into base64url format to construct the public key in
* JWK format.
*
* The process ensures that the derived public key correctly corresponds to the given private key,
* adhering to the secp256r1 elliptic curve standards. This method is useful in cryptographic
* operations where a public key is needed for operations like signature verification, but only
* the private key is available.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing a secp256r1 private key
* const publicKey = await Secp256r1.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
Secp256r1.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, point, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, Secp256r1.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _c.sent();
return [4 /*yield*/, Secp256r1.getCurvePoint({ keyBytes: privateKeyBytes })];
case 2:
point = _c.sent();
publicKey = {
kty: 'EC',
crv: 'P-256',
x: common_1.Convert.uint8Array(point.x).toBase64Url(),
y: common_1.Convert.uint8Array(point.y).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts an ASN.1 DER encoded ECDSA signature to a compact R+S format.
*
* @remarks
* This method is used for converting an ECDSA signature from the ASN.1 DER encoding to the more
* compact R+S format. This conversion is often required when dealing with ECDSA signatures in
* certain cryptographic standards such as JWS (JSON Web Signature).
*
* The method decodes the DER-encoded signature, extracts the R and S values, and concatenates
* them into a single byte array. This process involves handling the ASN.1 structure to correctly
* parse the R and S values, considering padding and integer encoding specifics of DER.
*
* @example
* ```ts
* const derSignature = new Uint8Array([...]); // Replace with your DER-encoded signature
* const signature = await Secp256r1.convertDerToCompactSignature({ derSignature });
* ```
*
* @param params - The parameters for the signature conversion.
* @param params.derSignature - The signature in ASN.1 DER format as a `Uint8Array`.
*
* @returns A Promise that resolves to the signature in compact R+S format as a `Uint8Array`.
*/
Secp256r1.convertDerToCompactSignature = function (_a) {
var derSignature = _a.derSignature;
return __awaiter(this, void 0, void 0, function () {
var signatureObject, compactSignature;
return __generator(this, function (_b) {
signatureObject = p256_1.secp256r1.Signature.fromDER(derSignature);
compactSignature = signatureObject.toCompactRawBytes();
return [2 /*return*/, compactSignature];
});
});
};
/**
* Converts a public key to its uncompressed form.
*
* @remarks
* This method takes a compressed public key represented as a byte array and decompresses it.
* Public key decompression involves reconstructing the y-coordinate from the x-coordinate,
* resulting in the full public key. This method is used when the uncompressed key format is
* required for certain cryptographic operations or interoperability.
*
* @example
* ```ts
* const compressedPublicKeyBytes = new Uint8Array([...]); // Replace with actual compressed public key bytes
* const decompressedPublicKey = await Secp256r1.decompressPublicKey({
* publicKeyBytes: compressedPublicKeyBytes
* });
* ```
*
* @param params - The parameters for the public key decompression.
* @param params.publicKeyBytes - The public key as a Uint8Array.
*
* @returns A Promise that resolves to the uncompressed public key as a Uint8Array.
*/
Secp256r1.decompressPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
point = p256_1.secp256r1.ProjectivePoint.fromHex(publicKeyBytes);
// Return the uncompressed form of the public key.
return [2 /*return*/, point.toRawBytes(false)];
});
});
};
/**
* Generates a secp256r1 private key in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new private key suitable for use with the secp256r1
* elliptic curve. The key is generated using cryptographically secure random
* number generation to ensure its uniqueness and security. The resulting
* private key adheres to the JWK format, specifically tailored for secp256r1,
* making it compatible with common cryptographic standards and easy to use in
* various cryptographic processes.
*
* The private key generated by this method includes the following components:
* - `kty`: Key Type, set to 'EC' for Elliptic Curve.
* - `crv`: Curve Name, set to 'P-256'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The x-coordinate of the public key point, derived from the private key, base64url-encoded.
* - `y`: The y-coordinate of the public key point, derived from the private key, base64url-encoded.
*
* The key is returned in a format suitable for direct use in signin and key agreement operations.
*
* @example
* ```ts
* const privateKey = await Secp256r1.generateKey();
* ```
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
Secp256r1.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, privateKey, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
privateKeyBytes = p256_1.secp256r1.utils.randomPrivateKey();
return [4 /*yield*/, Secp256r1.bytesToPrivateKey({ privateKeyBytes: privateKeyBytes })];
case 1:
privateKey = _b.sent();
// Compute the JWK thumbprint and set as the key ID.
_a = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_a.kid = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from a secp256r1 private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key. The method sets the 'kid' (key ID) property using the JWK thumbprint if it is not
* already defined. This approach is used under the assumption that a private key in JWK format
* always contains the corresponding public key properties.
*
* Note: This method offers a significant performance advantage, being about 200 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing a secp256r1 private key
* const publicKey = await Secp256r1.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
Secp256r1.getPublicKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var d, publicKey, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Verify the provided JWK represents an elliptic curve (EC) secp256r1 private key.
if (!((0, jwk_js_1.isEcPrivateJwk)(key) && key.crv === 'P-256')) {
throw new Error("Secp256r1: The provided key is not a 'P-256' private JWK.");
}
d = key.d, publicKey = __rest(key, ["d"]);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
publicKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a private key in JWK format and extracts its raw byte representation.
* It specifically focuses on the 'd' parameter of the JWK, which represents the private
* key component in base64url encoding. The method decodes this value into a byte array.
*
* This conversion is essential for operations that require the private key in its raw
* binary form, such as certain low-level cryptographic operations or when interfacing
* with systems and libraries that expect keys in a byte array format.
*
* @example
* ```ts
* const privateKey = { ... }; // An X25519 private key in JWK format
* const privateKeyBytes = await Secp256r1.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The private key in JWK format.
*
* @returns A Promise that resolves to the private key as a Uint8Array.
*/
Secp256r1.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid EC P-256 private key.
if (!(0, jwk_js_1.isEcPrivateJwk)(privateKey)) {
throw new Error("Secp256r1: The provided key is not a valid EC private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.d).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
/**
* Converts a public key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a public key in JWK format and converts it into its raw binary
* form. The conversion process involves decoding the 'x' and 'y' parameters of the JWK
* (which represent the x and y coordinates of the elliptic curve point, respectively)
* from base64url format into a byte array. The method then concatenates these values,
* along with a prefix indicating the key format, to form the full public key.
*
* This function is particularly useful for use cases where the public key is needed
* in its raw byte format, such as for certain cryptographic operations or when
* interfacing with systems that require raw key formats.
*
* @example
* ```ts
* const publicKey = { ... }; // A Jwk public key object
* const publicKeyBytes = await Secp256r1.publicKeyToBytes({ publicKey });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The public key in JWK format.
*
* @returns A Promise that resolves to the public key as a Uint8Array.
*/
Secp256r1.publicKeyToBytes = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var prefix, x, y, publicKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid EC P-256 public key, which must have a 'y' value.
if (!((0, jwk_js_1.isEcPublicJwk)(publicKey) && publicKey.y)) {
throw new Error("Secp256r1: The provided key is not a valid EC public key.");
}
prefix = new Uint8Array([0x04]);
x = common_1.Convert.base64Url(publicKey.x).toUint8Array();
y = common_1.Convert.base64Url(publicKey.y).toUint8Array();
publicKeyBytes = new Uint8Array(__spreadArray(__spreadArray(__spreadArray([], __read(prefix), false), __read(x), false), __read(y), false));
return [2 /*return*/, publicKeyBytes];
});
});
};
/**
* Computes an RFC6090-compliant Elliptic Curve Diffie-Hellman (ECDH) shared secret
* using secp256r1 private and public keys in JSON Web Key (JWK) format.
*
* @remarks
* This method facilitates the ECDH key agreement protocol, which is a method of securely
* deriving a shared secret between two parties based on their private and public keys.
* It takes the private key of one party (privateKeyA) and the public key of another
* party (publicKeyB) to compute a shared secret. The shared secret is derived from the
* x-coordinate of the elliptic curve point resulting from the multiplication of the
* public key with the private key.
*
* Note: When performing Elliptic Curve Diffie-Hellman (ECDH) key agreement,
* the resulting shared secret is a point on the elliptic curve, which
* consists of an x-coordinate and a y-coordinate. With a 256-bit curve like
* secp256r1, each of these coordinates is 32 bytes (256 bits) long. However,
* in the ECDH process, it's standard practice to use only the x-coordinate
* of the shared secret point as the resulting shared key. This is because
* the y-coordinate does not add to the entropy of the key, and both parties
* can independently compute the x-coordinate. Consquently, this implementation
* omits the y-coordinate for simplicity and standard compliance.
*
* @example
* ```ts
* const privateKeyA = { ... }; // A Jwk private key object for party A
* const publicKeyB = { ... }; // A Jwk public key object for party B
* const sharedSecret = await Secp256r1.sharedSecret({
* privateKeyA,
* publicKeyB
* });
* ```
*
* @param params - The parameters for the shared secret computation.
* @param params.privateKeyA - The private key in JWK format of one party.
* @param params.publicKeyB - The public key in JWK format of the other party.
*
* @returns A Promise that resolves to the computed shared secret as a Uint8Array.
*/
Secp256r1.sharedSecret = function (_a) {
var privateKeyA = _a.privateKeyA, publicKeyB = _a.publicKeyB;
return __awaiter(this, void 0, void 0, function () {
var privateKeyABytes, publicKeyBBytes, sharedSecret;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Ensure that keys from the same key pair are not specified.
if ('x' in privateKeyA && 'x' in publicKeyB && privateKeyA.x === publicKeyB.x) {
throw new Error("Secp256r1: ECDH shared secret cannot be computed from a single key pair's public and private keys.");
}
return [4 /*yield*/, Secp256r1.privateKeyToBytes({ privateKey: privateKeyA })];
case 1:
privateKeyABytes = _b.sent();
return [4 /*yield*/, Secp256r1.publicKeyToBytes({ publicKey: publicKeyB })];
case 2:
publicKeyBBytes = _b.sent();
sharedSecret = p256_1.secp256r1.getSharedSecret(privateKeyABytes, publicKeyBBytes, true);
// Remove the leading byte that indicates the sign of the y-coordinate
// of the point on the elliptic curve. See note above.
return [2 /*return*/, sharedSecret.slice(1)];
}
});
});
};
/**
* Generates an RFC6979-compliant ECDSA signature of given data using a secp256r1 private key.
*
* @remarks
* This method signs the provided data with a specified private key using the ECDSA
* (Elliptic Curve Digital Signature Algorithm) signature algorithm, as defined in RFC6979.
* The data to be signed is first hashed using the SHA-256 algorithm, and this hash is then
* signed using the private key. The output is a digital signature in the form of a
* Uint8Array, which uniquely corresponds to both the data and the private key used for signing.
*
* This method is commonly used in cryptographic applications to ensure data integrity and
* authenticity. The signature can later be verified by parties with access to the corresponding
* public key, ensuring that the data has not been tampered with and was indeed signed by the
* holder of the private key.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data to be signed
* const privateKey = { ... }; // A Jwk object representing a secp256r1 private key
* const signature = await Secp256r1.sign({
* key: privateKey,
* data
* });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign, represented as a Uint8Array.
*
* @returns A Promise that resolves to the signature as a Uint8Array.
*/
Secp256r1.sign = function (_a) {
var data = _a.data, key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, digest, signatureObject, signature;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Secp256r1.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
digest = (0, sha256_1.sha256)(data);
signatureObject = p256_1.secp256r1.sign(digest, privateKeyBytes);
signature = signatureObject.toCompactRawBytes();
return [2 /*return*/, signature];
}
});
});
};
/**
* Validates a given private key to ensure its compliance with the secp256r1 curve standards.
*
* @remarks
* This method checks whether a provided private key is a valid 32-byte number and falls within
* the range defined by the secp256r1 curve's order. It is essential for ensuring the private
* key's mathematical correctness in the context of secp256r1-based cryptographic operations.
*
* Note that this validation strictly pertains to the key's format and numerical validity; it does
* not assess whether the key corresponds to a known entity or its security status (e.g., whether
* it has been compromised).
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // A 32-byte private key
* const isValid = await Secp256r1.validatePrivateKey({ privateKeyBytes });
* console.log(isValid); // true or false based on the key's validity
* ```
*
* @param params - The parameters for the key validation.
* @param params.privateKeyBytes - The private key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the private key is valid.
*/
Secp256r1.validatePrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_b) {
return [2 /*return*/, p256_1.secp256r1.utils.isValidPrivateKey(privateKeyBytes)];
});
});
};
/**
* Validates a given public key to confirm its mathematical correctness on the secp256r1 curve.
*
* @remarks
* This method checks if the provided public key represents a valid point on the secp256r1 curve.
* It decodes the key's Weierstrass points (x and y coordinates) and verifies their validity
* against the curve's parameters. A valid point must lie on the curve and meet specific
* mathematical criteria defined by the curve's equation.
*
* It's important to note that this method does not verify the key's ownership or whether it has
* been compromised; it solely focuses on the key's adherence to the curve's mathematical
* principles.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // A public key in byte format
* const isValid = await Secp256r1.validatePublicKey({ publicKeyBytes });
* console.log(isValid); // true if the key is valid on the secp256r1 curve, false otherwise
* ```
*
* @param params - The parameters for the key validation.
* @param params.publicKeyBytes - The public key to validate, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating the public key's validity on
* the secp256r1 curve.
*/
Secp256r1.validatePublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var point;
return __generator(this, function (_b) {
try {
point = p256_1.secp256r1.ProjectivePoint.fromHex(publicKeyBytes);
// Check if points are on the Short Weierstrass curve.
point.assertValidity();
}
catch (error) {
return [2 /*return*/, false];
}
return [2 /*return*/, true];
});
});
};
/**
* Verifies an RFC6979-compliant ECDSA signature against given data and a secp256r1 public key.
*
* @remarks
* This method validates a digital signature to ensure that it was generated by the holder of the
* corresponding private key and that the signed data has not been altered. The signature
* verification is performed using the ECDSA (Elliptic Curve Digital Signature Algorithm) as
* specified in RFC6979. The data to be verified is first hashed using the SHA-256 algorithm, and
* this hash is then used along with the public key to verify the signature.
*
* The method returns a boolean value indicating whether the signature is valid. A valid signature
* proves that the signed data was indeed signed by the owner of the private key corresponding to
* the provided public key and that the data has not been tampered with since it was signed.
*
* Note: The verification process does not consider the malleability of low-s signatures, which
* may be relevant in certain contexts, such as Bitcoin transactions.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage'); // Data that was signed
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const isSignatureValid = await Secp256r1.verify({
* key: publicKey,
* signature,
* data
* });
* console.log(isSignatureValid); // true if the signature is valid, false otherwise
* ```
*
* @param params - The parameters for the signature verification.
* @param params.key - The public key used for verification, represented in JWK format.
* @param params.signature - The signature to verify, represented as a Uint8Array.
* @param params.data - The data that was signed, represented as a Uint8Array.
*
* @returns A Promise that resolves to a boolean indicating whether the signature is valid.
*/
Secp256r1.verify = function (_a) {
var key = _a.key, signature = _a.signature, data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, digest, isValid;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, Secp256r1.publicKeyToBytes({ publicKey: key })];
case 1:
publicKeyBytes = _b.sent();
digest = (0, sha256_1.sha256)(data);
isValid = p256_1.secp256r1.verify(signature, digest, publicKeyBytes, { lowS: false });
return [2 /*return*/, isValid];
}
});
});
};
/**
* Returns the elliptic curve point (x and y coordinates) for a given secp256r1 key.
*
* @remarks
* This method extracts the elliptic curve point from a given secp256r1 key, whether
* it's a private or a public key. For a private key, the method first computes the
* corresponding public key and then extracts the x and y coordinates. For a public key,
* it directly returns these coordinates. The coordinates are represented as Uint8Array.
*
* The x and y coordinates represent the key's position on the elliptic curve and can be
* used in various cryptographic operations, such as digital signatures or key agreement
* protocols.
*
* @example
* ```ts
* // For a private key
* const privateKey = new Uint8Array([...]); // A 32-byte private key
* const { x: xFromPrivateKey, y: yFromPrivateKey } = await Secp256r1.getCurvePoint({ keyBytes: privateKey });
*
* // For a public key
* const publicKey = new Uint8Array([...]); // A 33-byte or 65-byte public key
* const { x: xFromPublicKey, y: yFromPublicKey } = await Secp256r1.getCurvePoint({ keyBytes: publicKey });
* ```
*
* @param params - The parameters for the curve point decoding operation.
* @param params.keyBytes - The key for which to get the elliptic curve point.
* Can be either a private key or a public key.
* The key should be passed as a `Uint8Array`.
*
* @returns A Promise that resolves to an object with properties 'x' and 'y',
* each being a Uint8Array representing the x and y coordinates of the key point on the
* elliptic curve.
*/
Secp256r1.getCurvePoint = function (_a) {
var keyBytes = _a.keyBytes;
return __awaiter(this, void 0, void 0, function () {
var point, x, y;
return __generator(this, function (_b) {
// If key is a private key, first compute the public key.
if (keyBytes.byteLength === 32) {
keyBytes = p256_1.secp256r1.getPublicKey(keyBytes);
}
point = p256_1.secp256r1.ProjectivePoint.fromHex(keyBytes);
x = (0, utils_1.numberToBytesBE)(point.x, 32);
y = (0, utils_1.numberToBytesBE)(point.y, 32);
return [2 /*return*/, { x: x, y: y }];
});
});
};
return Secp256r1;
}());
exports.Secp256r1 = Secp256r1;
exports.P256 = Secp256r1;
//# sourceMappingURL=secp256r1.js.map
File diff suppressed because one or more lines are too long
+93
View File
@@ -0,0 +1,93 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Sha256 = void 0;
var sha256_1 = require("@noble/hashes/sha256");
/**
* The `Sha256` class provides an interface for generating SHA-256 hash digests.
*
* This class utilizes the '@noble/hashes/sha256' function to generate hash digests
* of the provided data. The SHA-256 algorithm is widely used in cryptographic
* applications to produce a fixed-size 256-bit (32-byte) hash.
*
* The methods of this class are asynchronous and return Promises. They use the Uint8Array
* type for input data and the resulting digest, ensuring a consistent interface
* for binary data processing.
*
* @example
* ```ts
* const data = new Uint8Array([...]);
* const hash = await Sha256.digest({ data });
* ```
*/
var Sha256 = /** @class */ (function () {
function Sha256() {
}
/**
* Generates a SHA-256 hash digest for the given data.
*
* @remarks
* This method produces a hash digest using the SHA-256 algorithm. The resultant digest
* is deterministic, meaning the same data will always produce the same hash, but
* is computationally infeasible to regenerate the original data from the hash.
*
* @example
* ```ts
* const data = new Uint8Array([...]);
* const hash = await Sha256.digest({ data });
* ```
*
* @param params - The parameters for the hashing operation.
* @param params.data - The data to hash, represented as a Uint8Array.
*
* @returns A Promise that resolves to the SHA-256 hash digest of the provided data as a Uint8Array.
*/
Sha256.digest = function (_a) {
var data = _a.data;
return __awaiter(this, void 0, void 0, function () {
var hash;
return __generator(this, function (_b) {
hash = (0, sha256_1.sha256)(data);
return [2 /*return*/, hash];
});
});
};
return Sha256;
}());
exports.Sha256 = Sha256;
//# sourceMappingURL=sha256.js.map
@@ -0,0 +1 @@
{"version":3,"file":"sha256.js","sourceRoot":"","sources":["../../../src/primitives/sha256.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAA8C;AAE9C;;;;;;;;;;;;;;;;GAgBG;AACH;IAAA;IA2BA,CAAC;IA1BC;;;;;;;;;;;;;;;;;;OAkBG;IACiB,aAAM,GAA1B,UAA2B,EAE1B;YAF4B,IAAI,UAAA;;;;gBAGzB,IAAI,GAAG,IAAA,eAAM,EAAC,IAAI,CAAC,CAAC;gBAE1B,sBAAO,IAAI,EAAC;;;KACb;IACH,aAAC;AAAD,CAAC,AA3BD,IA2BC;AA3BY,wBAAM"}
+498
View File
@@ -0,0 +1,498 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.X25519 = void 0;
var common_1 = require("@web5/common");
var ed25519_1 = require("@noble/curves/ed25519");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `X25519` class provides a comprehensive suite of utilities for working with the X25519
* elliptic curve, widely used for key agreement protocols and cryptographic applications. It
* provides methods for key generation, conversion, and Elliptic Curve Diffie-Hellman (ECDH)
* key agreement, all aligned with standard cryptographic practices.
*
* The class supports conversions between raw byte formats and JSON Web Key (JWK) formats,
* making it versatile for various cryptographic tasks. It adheres to RFC6090 for ECDH, ensuring
* secure and effective handling of keys and cryptographic operations.
*
* Key Features:
* - Key Generation: Generate X25519 private keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Public Key Derivation: Derive public keys from private keys.
* - ECDH Shared Secret Computation: Securely derive shared secrets using private and public keys.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await X25519.generateKey();
*
* // Public Key Derivation
* const publicKey = await X25519.computePublicKey({ key: privateKey });
* console.log(publicKey === await X25519.getPublicKey({ key: privateKey })); // Output: true
*
* // ECDH Shared Secret Computation
* const sharedSecret = await X25519.sharedSecret({
* privateKeyA: privateKey,
* publicKeyB: anotherPublicKey
* });
*
* // Key Conversion
* const publicKeyBytes = await X25519.publicKeyToBytes({ publicKey });
* const privateKeyBytes = await X25519.privateKeyToBytes({ privateKey });
* ```
*/
var X25519 = /** @class */ (function () {
function X25519() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a private key as a byte array (Uint8Array) for the X25519 elliptic curve
* and transforms it into a JWK object. The process involves first deriving the public key from
* the private key, then encoding both the private and public keys into base64url format.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'X25519'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The derived public key, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual private key bytes
* const privateKey = await X25519.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKeyBytes - The raw private key as a Uint8Array.
*
* @returns A Promise that resolves to the private key in JWK format.
*/
X25519.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
publicKeyBytes = ed25519_1.x25519.getPublicKey(privateKeyBytes);
privateKey = {
kty: 'OKP',
crv: 'X25519',
d: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a raw public key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method accepts a public key as a byte array (Uint8Array) for the X25519 elliptic curve
* and transforms it into a JWK object. The conversion process involves encoding the public
* key bytes into base64url format.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'X25519'.
* - `x`: The public key, base64url-encoded.
*
* This method is useful for converting raw public keys into a standardized
* JSON format, facilitating their use in cryptographic operations and making
* them easy to share and store.
*
* @example
* ```ts
* const publicKeyBytes = new Uint8Array([...]); // Replace with actual public key bytes
* const publicKey = await X25519.bytesToPublicKey({ publicKeyBytes });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKeyBytes - The raw public key as a Uint8Array.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
X25519.bytesToPublicKey = function (_a) {
var publicKeyBytes = _a.publicKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
publicKey = {
kty: 'OKP',
crv: 'X25519',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url(),
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Derives the public key in JWK format from a given X25519 private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The derivation process involves converting the private key to a
* raw byte array and then computing the corresponding public key on the Curve25519 curve.
* The public key is then encoded into base64url format to construct a JWK representation.
*
* The process ensures that the derived public key correctly corresponds to the given private key,
* adhering to the Curve25519 elliptic curve in Twisted Edwards form standards. This method is
* useful in cryptographic operations where a public key is needed for operations like signature
* verification, but only the private key is available.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing an X25519 private key
* const publicKey = await X25519.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
X25519.computePublicKey = function (_a) {
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, publicKeyBytes, publicKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0: return [4 /*yield*/, X25519.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _c.sent();
publicKeyBytes = ed25519_1.x25519.getPublicKey(privateKeyBytes);
publicKey = {
kty: 'OKP',
crv: 'X25519',
x: common_1.Convert.uint8Array(publicKeyBytes).toBase64Url()
};
// Compute the JWK thumbprint and set as the key ID.
_b = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Generates an X25519 private key in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new private key suitable for use with the X25519 elliptic curve.
* The key generation process involves using cryptographically secure random number generation
* to ensure the uniqueness and security of the key. The resulting private key adheres to the
* JWK format making it compatible with common cryptographic standards and easy to use in various
* cryptographic processes.
*
* The generated private key in JWK format includes the following components:
* - `kty`: Key Type, set to 'OKP' for Octet Key Pair.
* - `crv`: Curve Name, set to 'X25519'.
* - `d`: The private key component, base64url-encoded.
* - `x`: The derived public key, base64url-encoded.
*
* The key is returned in a format suitable for direct use in key agreement operations.
*
* @example
* ```ts
* const privateKey = await X25519.generateKey();
* ```
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
X25519.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, privateKey, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
privateKeyBytes = ed25519_1.x25519.utils.randomPrivateKey();
return [4 /*yield*/, X25519.bytesToPrivateKey({ privateKeyBytes: privateKeyBytes })];
case 1:
privateKey = _b.sent();
// Compute the JWK thumbprint and set as the key ID.
_a = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 2:
// Compute the JWK thumbprint and set as the key ID.
_a.kid = _b.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an X25519 private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key. The method sets the 'kid' (key ID) property using the JWK thumbprint if it is not
* already defined. This approach is used under the assumption that a private key in JWK format
* always contains the corresponding public key properties.
*
* Note: This method offers a significant performance advantage, being about 500 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const privateKey = { ... }; // A Jwk object representing an X25519 private key
* const publicKey = await X25519.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
X25519.getPublicKey = function (_a) {
var _b;
var key = _a.key;
return __awaiter(this, void 0, void 0, function () {
var d, publicKey, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// Verify the provided JWK represents an octet key pair (OKP) X25519 private key.
if (!((0, jwk_js_1.isOkpPrivateJwk)(key) && key.crv === 'X25519')) {
throw new Error("X25519: The provided key is not an X25519 private JWK.");
}
d = key.d, publicKey = __rest(key, ["d"]);
if (!((_b =
// If the key ID is undefined, set it to the JWK thumbprint.
publicKey.kid) !== null && _b !== void 0)) return [3 /*break*/, 1];
_c = _b;
return [3 /*break*/, 3];
case 1:
// If the key ID is undefined, set it to the JWK thumbprint.
_d = publicKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: publicKey })];
case 2:
_c = (_d.kid = _e.sent());
_e.label = 3;
case 3:
// If the key ID is undefined, set it to the JWK thumbprint.
_c;
return [2 /*return*/, publicKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a private key in JWK format and extracts its raw byte representation.
*
* This method accepts a public key in JWK format and converts it into its raw binary
* form. The conversion process involves decoding the 'd' parameter of the JWK
* from base64url format into a byte array.
*
* This conversion is essential for operations that require the private key in its raw
* binary form, such as certain low-level cryptographic operations or when interfacing
* with systems and libraries that expect keys in a byte array format.
*
* @example
* ```ts
* const privateKey = { ... }; // An X25519 private key in JWK format
* const privateKeyBytes = await X25519.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the private key conversion.
* @param params.privateKey - The private key in JWK format.
*
* @returns A Promise that resolves to the private key as a Uint8Array.
*/
X25519.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid OKP private key.
if (!(0, jwk_js_1.isOkpPrivateJwk)(privateKey)) {
throw new Error("X25519: The provided key is not a valid OKP private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.d).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
/**
* Converts a public key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method accepts a public key in JWK format and converts it into its raw binary form.
* The conversion process involves decoding the 'x' parameter of the JWK (which represent the
* x coordinate of the elliptic curve point) from base64url format into a byte array.
*
* This conversion is essential for operations that require the public key in its raw
* binary form, such as certain low-level cryptographic operations or when interfacing
* with systems and libraries that expect keys in a byte array format.
*
* @example
* ```ts
* const publicKey = { ... }; // An X25519 public key in JWK format
* const publicKeyBytes = await X25519.publicKeyToBytes({ publicKey });
* ```
*
* @param params - The parameters for the public key conversion.
* @param params.publicKey - The public key in JWK format.
*
* @returns A Promise that resolves to the public key as a Uint8Array.
*/
X25519.publicKeyToBytes = function (_a) {
var publicKey = _a.publicKey;
return __awaiter(this, void 0, void 0, function () {
var publicKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid OKP public key.
if (!(0, jwk_js_1.isOkpPublicJwk)(publicKey)) {
throw new Error("X25519: The provided key is not a valid OKP public key.");
}
publicKeyBytes = common_1.Convert.base64Url(publicKey.x).toUint8Array();
return [2 /*return*/, publicKeyBytes];
});
});
};
/**
* Computes an RFC6090-compliant Elliptic Curve Diffie-Hellman (ECDH) shared secret
* using secp256k1 private and public keys in JSON Web Key (JWK) format.
*
* @remarks
* This method facilitates the ECDH key agreement protocol, which is a method of securely
* deriving a shared secret between two parties based on their private and public keys.
* It takes the private key of one party (privateKeyA) and the public key of another
* party (publicKeyB) to compute a shared secret. The shared secret is derived from the
* x-coordinate of the elliptic curve point resulting from the multiplication of the
* public key with the private key.
*
* Note: When performing Elliptic Curve Diffie-Hellman (ECDH) key agreement,
* the resulting shared secret is a point on the elliptic curve, which
* consists of an x-coordinate and a y-coordinate. With a 256-bit curve like
* secp256k1, each of these coordinates is 32 bytes (256 bits) long. However,
* in the ECDH process, it's standard practice to use only the x-coordinate
* of the shared secret point as the resulting shared key. This is because
* the y-coordinate does not add to the entropy of the key, and both parties
* can independently compute the x-coordinate. Consquently, this implementation
* omits the y-coordinate for simplicity and standard compliance.
*
* @example
* ```ts
* const privateKeyA = { ... }; // A Jwk object for party A
* const publicKeyB = { ... }; // A PublicKeyJwk object for party B
* const sharedSecret = await Secp256k1.sharedSecret({
* privateKeyA,
* publicKeyB
* });
* ```
*
* @param params - The parameters for the shared secret computation.
* @param params.privateKeyA - The private key in JWK format of one party.
* @param params.publicKeyB - The public key in JWK format of the other party.
*
* @returns A Promise that resolves to the computed shared secret as a Uint8Array.
*/
X25519.sharedSecret = function (_a) {
var privateKeyA = _a.privateKeyA, publicKeyB = _a.publicKeyB;
return __awaiter(this, void 0, void 0, function () {
var privateKeyABytes, publicKeyBBytes, sharedSecret;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
// Ensure that keys from the same key pair are not specified.
if ('x' in privateKeyA && 'x' in publicKeyB && privateKeyA.x === publicKeyB.x) {
throw new Error("X25519: ECDH shared secret cannot be computed from a single key pair's public and private keys.");
}
return [4 /*yield*/, X25519.privateKeyToBytes({ privateKey: privateKeyA })];
case 1:
privateKeyABytes = _b.sent();
return [4 /*yield*/, X25519.publicKeyToBytes({ publicKey: publicKeyB })];
case 2:
publicKeyBBytes = _b.sent();
sharedSecret = ed25519_1.x25519.getSharedSecret(privateKeyABytes, publicKeyBBytes);
return [2 /*return*/, sharedSecret];
}
});
});
};
return X25519;
}());
exports.X25519 = X25519;
//# sourceMappingURL=x25519.js.map
@@ -0,0 +1 @@
{"version":3,"file":"x25519.js","sourceRoot":"","sources":["../../../src/primitives/x25519.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,340 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XChaCha20Poly1305 = exports.POLY1305_TAG_LENGTH = void 0;
var common_1 = require("@web5/common");
var chacha_1 = require("@noble/ciphers/chacha");
var utils_1 = require("@noble/ciphers/webcrypto/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* Constant defining the length of the authentication tag in bytes for XChaCha20-Poly1305.
*
* @remarks
* The `POLY1305_TAG_LENGTH` is set to 16 bytes (128 bits), which is the standard size for the
* Poly1305 authentication tag in XChaCha20-Poly1305 encryption. This tag length ensures
* a strong level of security for message authentication, verifying the integrity and
* authenticity of the data during decryption.
*/
exports.POLY1305_TAG_LENGTH = 16;
/**
* The `XChaCha20Poly1305` class provides a suite of utilities for cryptographic operations
* using the XChaCha20-Poly1305 algorithm, a combination of the XChaCha20 stream cipher and the
* Poly1305 message authentication code (MAC). This class encompasses methods for key generation,
* encryption, decryption, and conversions between raw byte arrays and JSON Web Key (JWK) formats.
*
* XChaCha20-Poly1305 is renowned for its high security and efficiency, especially in scenarios
* involving large data volumes or where data integrity and confidentiality are paramount. The
* extended nonce size of XChaCha20 reduces the risks of nonce reuse, while Poly1305 provides
* a strong MAC ensuring data integrity.
*
* Key Features:
* - Key Generation: Generate XChaCha20-Poly1305 symmetric keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Encryption: Encrypt data using XChaCha20-Poly1305, returning both ciphertext and MAC tag.
* - Decryption: Decrypt data and verify integrity using the XChaCha20-Poly1305 algorithm.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await XChaCha20Poly1305.generateKey();
*
* // Encryption
* const data = new TextEncoder().encode('Messsage');
* const nonce = utils.randomBytes(24); // 24-byte nonce
* const additionalData = new TextEncoder().encode('Associated data');
* const { ciphertext, tag } = await XChaCha20Poly1305.encrypt({
* data,
* nonce,
* additionalData,
* key: privateKey
* });
*
* // Decryption
* const decryptedData = await XChaCha20Poly1305.decrypt({
* data: ciphertext,
* nonce,
* tag,
* additionalData,
* key: privateKey
* });
*
* // Key Conversion
* const privateKeyBytes = await XChaCha20Poly1305.privateKeyToBytes({ privateKey });
* ```
*/
var XChaCha20Poly1305 = /** @class */ (function () {
function XChaCha20Poly1305() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a symmetric key represented as a byte array (Uint8Array) and converts it into
* a JWK object for use with the XChaCha20-Poly1305 algorithm. The process involves encoding the
* key into base64url format and setting the appropriate JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
* - `k`: The symmetric key, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
* const privateKey = await XChaCha20Poly1305.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
*
* @returns A Promise that resolves to the symmetric key in JWK format.
*/
XChaCha20Poly1305.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
privateKey = {
k: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'oct'
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Decrypts the provided data using XChaCha20-Poly1305.
*
* @remarks
* This method performs XChaCha20-Poly1305 decryption on the given encrypted data using the
* specified key, nonce, and authentication tag. It supports optional additional authenticated
* data (AAD) for enhanced security. The nonce must be 24 bytes long, consistent with XChaCha20's
* specifications.
*
* @example
* ```ts
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const nonce = new Uint8Array(24); // 24-byte nonce
* const additionalData = new Uint8Array([...]); // Optional AAD
* const key = { ... }; // A Jwk object representing the XChaCha20-Poly1305 key
* const decryptedData = await XChaCha20Poly1305.decrypt({
* data: encryptedData,
* nonce,
* additionalData,
* key
* });
* ```
*
* @param params - The parameters for the decryption operation.
* @param params.data - The encrypted data to decrypt including the authentication tag,
* represented as a Uint8Array.
* @param params.key - The key to use for decryption, represented in JWK format.
* @param params.nonce - The nonce used during the encryption process.
* @param params.additionalData - Optional additional authenticated data.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
XChaCha20Poly1305.decrypt = function (_a) {
var data = _a.data, key = _a.key, nonce = _a.nonce, additionalData = _a.additionalData;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, xc20p, plaintext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, XChaCha20Poly1305.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
xc20p = (0, chacha_1.xchacha20poly1305)(privateKeyBytes, nonce, additionalData);
plaintext = xc20p.decrypt(data);
return [2 /*return*/, plaintext];
}
});
});
};
/**
* Encrypts the provided data using XChaCha20-Poly1305.
*
* @remarks
* This method performs XChaCha20-Poly1305 encryption on the given data using the specified key
* and nonce. It supports optional additional authenticated data (AAD) for enhanced security. The
* nonce must be 24 bytes long, as per XChaCha20's specifications. The method returns the
* encrypted data along with an authentication tag as a Uint8Array, ensuring both confidentiality
* and integrity of the data.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage');
* const nonce = utils.randomBytes(24); // 24-byte nonce
* const additionalData = new TextEncoder().encode('Associated data'); // Optional AAD
* const key = { ... }; // A Jwk object representing an XChaCha20-Poly1305 key
* const encryptedData = await XChaCha20Poly1305.encrypt({
* data,
* nonce,
* additionalData,
* key
* });
* ```
*
* @param params - The parameters for the encryption operation.
* @param params.data - The data to encrypt, represented as a Uint8Array.
* @param params.key - The key to use for encryption, represented in JWK format.
* @param params.nonce - A 24-byte nonce for the encryption process.
* @param params.additionalData - Optional additional authenticated data.
*
* @returns A Promise that resolves to a byte array containing the encrypted data and the
* authentication tag.
*/
XChaCha20Poly1305.encrypt = function (_a) {
var data = _a.data, key = _a.key, nonce = _a.nonce, additionalData = _a.additionalData;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, xc20p, ciphertext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, XChaCha20Poly1305.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
xc20p = (0, chacha_1.xchacha20poly1305)(privateKeyBytes, nonce, additionalData);
ciphertext = xc20p.encrypt(data);
return [2 /*return*/, ciphertext];
}
});
});
};
/**
* Generates a symmetric key for XChaCha20-Poly1305 in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new symmetric key suitable for use with the XChaCha20-Poly1305 algorithm.
* The key is generated using cryptographically secure random number generation to ensure its
* uniqueness and security. The XChaCha20-Poly1305 algorithm requires a 256-bit key (32 bytes),
* and this method adheres to that specification.
*
* Key components included in the JWK:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKey = await XChaCha20Poly1305.generateKey();
* ```
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
XChaCha20Poly1305.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, _a, alg, ext, key_ops, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.generateKey({ name: 'AES-CTR', length: 256 }, true, ['encrypt'])];
case 1:
webCryptoKey = _c.sent();
return [4 /*yield*/, webCrypto.exportKey('jwk', webCryptoKey)];
case 2:
_a = _c.sent(), alg = _a.alg, ext = _a.ext, key_ops = _a.key_ops, privateKey = __rest(_a, ["alg", "ext", "key_ops"]);
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
* It decodes the 'k' parameter of the JWK value, which represents the symmetric key in base64url
* encoding, into a byte array.
*
* @example
* ```ts
* const privateKey = { ... }; // A symmetric key in JWK format
* const privateKeyBytes = await XChaCha20Poly1305.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKey - The symmetric key in JWK format.
*
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
*/
XChaCha20Poly1305.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid oct private key.
if (!(0, jwk_js_1.isOctPrivateJwk)(privateKey)) {
throw new Error("XChaCha20Poly1305: The provided key is not a valid oct private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.k).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
return XChaCha20Poly1305;
}());
exports.XChaCha20Poly1305 = XChaCha20Poly1305;
//# sourceMappingURL=xchacha20-poly1305.js.map
@@ -0,0 +1 @@
{"version":3,"file":"xchacha20-poly1305.js","sourceRoot":"","sources":["../../../src/primitives/xchacha20-poly1305.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,316 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XChaCha20 = void 0;
var common_1 = require("@web5/common");
var chacha_1 = require("@noble/ciphers/chacha");
var utils_1 = require("@noble/ciphers/webcrypto/utils");
var jwk_js_1 = require("../jose/jwk.js");
/**
* The `XChaCha20` class provides a comprehensive suite of utilities for cryptographic operations
* using the XChaCha20 symmetric encryption algorithm. This class includes methods for key
* generation, encryption, decryption, and conversions between raw byte arrays and JSON Web Key
* (JWK) formats. XChaCha20 is an extended nonce variant of ChaCha20, a stream cipher designed for
* high-speed encryption with substantial security margins.
*
* The XChaCha20 algorithm is particularly well-suited for encrypting large volumes of data or
* data streams, especially where random access is required. The class adheres to standard
* cryptographic practices, ensuring robustness and security in its implementations.
*
* Key Features:
* - Key Generation: Generate XChaCha20 symmetric keys in JWK format.
* - Key Conversion: Transform keys between raw byte arrays and JWK formats.
* - Encryption: Encrypt data using XChaCha20 with the provided symmetric key.
* - Decryption: Decrypt data encrypted with XChaCha20 using the corresponding symmetric key.
*
* The methods in this class are asynchronous, returning Promises to accommodate various
* JavaScript environments.
*
* @example
* ```ts
* // Key Generation
* const privateKey = await XChaCha20.generateKey();
*
* // Encryption
* const data = new TextEncoder().encode('Messsage');
* const nonce = utils.randomBytes(24); // 24-byte nonce for XChaCha20
* const encryptedData = await XChaCha20.encrypt({
* data,
* nonce,
* key: privateKey
* });
*
* // Decryption
* const decryptedData = await XChaCha20.decrypt({
* data: encryptedData,
* nonce,
* key: privateKey
* });
*
* // Key Conversion
* const privateKeyBytes = await XChaCha20.privateKeyToBytes({ privateKey });
* ```
*/
var XChaCha20 = /** @class */ (function () {
function XChaCha20() {
}
/**
* Converts a raw private key in bytes to its corresponding JSON Web Key (JWK) format.
*
* @remarks
* This method takes a symmetric key represented as a byte array (Uint8Array) and
* converts it into a JWK object for use with the XChaCha20 symmetric encryption algorithm. The
* conversion process involves encoding the key into base64url format and setting the appropriate
* JWK parameters.
*
* The resulting JWK object includes the following properties:
* - `kty`: Key Type, set to 'oct' for Octet Sequence (representing a symmetric key).
* - `k`: The symmetric key, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKeyBytes = new Uint8Array([...]); // Replace with actual symmetric key bytes
* const privateKey = await XChaCha20.bytesToPrivateKey({ privateKeyBytes });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKeyBytes - The raw symmetric key as a Uint8Array.
*
* @returns A Promise that resolves to the symmetric key in JWK format.
*/
XChaCha20.bytesToPrivateKey = function (_a) {
var privateKeyBytes = _a.privateKeyBytes;
return __awaiter(this, void 0, void 0, function () {
var privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
privateKey = {
k: common_1.Convert.uint8Array(privateKeyBytes).toBase64Url(),
kty: 'oct'
};
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 1:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Decrypts the provided data using XChaCha20.
*
* @remarks
* This method performs XChaCha20 decryption on the given encrypted data using the specified key
* and nonce. The nonce should be the same as used in the encryption process and must be 24 bytes
* long. The method returns the decrypted data as a Uint8Array.
*
* @example
* ```ts
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const nonce = new Uint8Array(24); // 24-byte nonce used during encryption
* const key = { ... }; // A Jwk object representing the XChaCha20 key
* const decryptedData = await XChaCha20.decrypt({
* data: encryptedData,
* nonce,
* key
* });
* ```
*
* @param params - The parameters for the decryption operation.
* @param params.data - The encrypted data to decrypt, represented as a Uint8Array.
* @param params.key - The key to use for decryption, represented in JWK format.
* @param params.nonce - The nonce used during the encryption process.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
XChaCha20.decrypt = function (_a) {
var data = _a.data, key = _a.key, nonce = _a.nonce;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, ciphertext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, XChaCha20.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
ciphertext = (0, chacha_1.xchacha20)(privateKeyBytes, nonce, data);
return [2 /*return*/, ciphertext];
}
});
});
};
/**
* Encrypts the provided data using XChaCha20.
*
* @remarks
* This method performs XChaCha20 encryption on the given data using the specified key and nonce.
* The nonce must be 24 bytes long, ensuring a high level of security through a vast nonce space,
* reducing the risks associated with nonce reuse. The method returns the encrypted data as a
* Uint8Array.
*
* @example
* ```ts
* const data = new TextEncoder().encode('Messsage');
* const nonce = utils.randomBytes(24); // 24-byte nonce for XChaCha20
* const key = { ... }; // A Jwk object representing an XChaCha20 key
* const encryptedData = await XChaCha20.encrypt({
* data,
* nonce,
* key
* });
* ```
*
* @param params - The parameters for the encryption operation.
* @param params.data - The data to encrypt, represented as a Uint8Array.
* @param params.key - The key to use for encryption, represented in JWK format.
* @param params.nonce - A 24-byte nonce for the encryption process.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
XChaCha20.encrypt = function (_a) {
var data = _a.data, key = _a.key, nonce = _a.nonce;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes, plaintext;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, XChaCha20.privateKeyToBytes({ privateKey: key })];
case 1:
privateKeyBytes = _b.sent();
plaintext = (0, chacha_1.xchacha20)(privateKeyBytes, nonce, data);
return [2 /*return*/, plaintext];
}
});
});
};
/**
* Generates a symmetric key for XChaCha20 in JSON Web Key (JWK) format.
*
* @remarks
* This method creates a new symmetric key suitable for use with the XChaCha20 encryption
* algorithm. The key is generated using cryptographically secure random number generation
* to ensure its uniqueness and security. The XChaCha20 algorithm requires a 256-bit key
* (32 bytes), and this method adheres to that specification.
*
* Key components included in the JWK:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const privateKey = await XChaCha20.generateKey();
* ```
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
XChaCha20.generateKey = function () {
return __awaiter(this, void 0, void 0, function () {
var webCrypto, webCryptoKey, _a, alg, ext, key_ops, privateKey, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
webCrypto = (0, utils_1.getWebcryptoSubtle)();
return [4 /*yield*/, webCrypto.generateKey({ name: 'AES-CTR', length: 256 }, true, ['encrypt'])];
case 1:
webCryptoKey = _c.sent();
return [4 /*yield*/, webCrypto.exportKey('jwk', webCryptoKey)];
case 2:
_a = _c.sent(), alg = _a.alg, ext = _a.ext, key_ops = _a.key_ops, privateKey = __rest(_a, ["alg", "ext", "key_ops"]);
// Compute the JWK thumbprint and set as the key ID.
_b = privateKey;
return [4 /*yield*/, (0, jwk_js_1.computeJwkThumbprint)({ jwk: privateKey })];
case 3:
// Compute the JWK thumbprint and set as the key ID.
_b.kid = _c.sent();
return [2 /*return*/, privateKey];
}
});
});
};
/**
* Converts a private key from JSON Web Key (JWK) format to a raw byte array (Uint8Array).
*
* @remarks
* This method takes a symmetric key in JWK format and extracts its raw byte representation.
* It decodes the 'k' parameter of the JWK value, which represents the symmetric key in base64url
* encoding, into a byte array.
*
* @example
* ```ts
* const privateKey = { ... }; // A symmetric key in JWK format
* const privateKeyBytes = await XChaCha20.privateKeyToBytes({ privateKey });
* ```
*
* @param params - The parameters for the symmetric key conversion.
* @param params.privateKey - The symmetric key in JWK format.
*
* @returns A Promise that resolves to the symmetric key as a Uint8Array.
*/
XChaCha20.privateKeyToBytes = function (_a) {
var privateKey = _a.privateKey;
return __awaiter(this, void 0, void 0, function () {
var privateKeyBytes;
return __generator(this, function (_b) {
// Verify the provided JWK represents a valid oct private key.
if (!(0, jwk_js_1.isOctPrivateJwk)(privateKey)) {
throw new Error("XChaCha20: The provided key is not a valid oct private key.");
}
privateKeyBytes = common_1.Convert.base64Url(privateKey.k).toUint8Array();
return [2 /*return*/, privateKeyBytes];
});
});
};
return XChaCha20;
}());
exports.XChaCha20 = XChaCha20;
//# sourceMappingURL=xchacha20.js.map
@@ -0,0 +1 @@
{"version":3,"file":"xchacha20.js","sourceRoot":"","sources":["../../../src/primitives/xchacha20.ts"],"names":[],"mappings":"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"}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=cipher.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"cipher.js","sourceRoot":"","sources":["../../../src/types/cipher.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=crypto-api.js.map
@@ -0,0 +1 @@
{"version":3,"file":"crypto-api.js","sourceRoot":"","sources":["../../../src/types/crypto-api.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=hasher.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"hasher.js","sourceRoot":"","sources":["../../../src/types/hasher.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=identifier.js.map
@@ -0,0 +1 @@
{"version":3,"file":"identifier.js","sourceRoot":"","sources":["../../../src/types/identifier.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-compressor.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-compressor.js","sourceRoot":"","sources":["../../../src/types/key-compressor.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-converter.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-converter.js","sourceRoot":"","sources":["../../../src/types/key-converter.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-deriver.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-deriver.js","sourceRoot":"","sources":["../../../src/types/key-deriver.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-generator.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-generator.js","sourceRoot":"","sources":["../../../src/types/key-generator.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-io.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"key-io.js","sourceRoot":"","sources":["../../../src/types/key-io.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=key-wrapper.js.map
@@ -0,0 +1 @@
{"version":3,"file":"key-wrapper.js","sourceRoot":"","sources":["../../../src/types/key-wrapper.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=params-direct.js.map
@@ -0,0 +1 @@
{"version":3,"file":"params-direct.js","sourceRoot":"","sources":["../../../src/types/params-direct.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=params-enclosed.js.map
@@ -0,0 +1 @@
{"version":3,"file":"params-enclosed.js","sourceRoot":"","sources":["../../../src/types/params-enclosed.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=params-kms.js.map
@@ -0,0 +1 @@
{"version":3,"file":"params-kms.js","sourceRoot":"","sources":["../../../src/types/params-kms.ts"],"names":[],"mappings":""}
+3
View File
@@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=signer.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"signer.js","sourceRoot":"","sources":["../../../src/types/signer.ts"],"names":[],"mappings":""}
+198
View File
@@ -0,0 +1,198 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.randomUuid = exports.randomBytes = exports.isWebCryptoSupported = exports.getJoseSignatureAlgorithmFromPublicKey = exports.checkValidProperty = exports.checkRequiredProperty = void 0;
var crypto_1 = require("@noble/hashes/crypto");
var utils_1 = require("@noble/hashes/utils");
/**
* Checks whether the properties object provided contains the specified property.
*
* @example
* ```ts
* const obj = { a: 'Bob', t: 30 };
* checkRequiredProperty({ property: 'a', inObject: obj }); // No error
* checkRequiredProperty({ property: 'z', inObject: obj }); // Throws TypeError
* ```
*
* @param params - The parameters for the check.
* @param params.property - Property key to check for.
* @param params.properties - Properties object to check within.
* @returns void
* @throws {TypeError} If the property is not a key in the properties object.
*/
function checkRequiredProperty(params) {
if (!params || params.property === undefined || params.inObject === undefined) {
throw new TypeError("One or more required parameters missing: 'property, properties'");
}
var property = params.property, inObject = params.inObject;
if (!(property in inObject)) {
throw new TypeError("Required parameter missing: '".concat(property, "'"));
}
}
exports.checkRequiredProperty = checkRequiredProperty;
/**
* Checks whether the property specified is a member of the list of valid properties.
*
* @example
* ```ts
* const property = 'color';
* const allowedProperties = ['size', 'shape', 'color'];
* checkValidProperty({ property, allowedProperties }); // No error
* checkValidProperty({ property: 'weight', allowedProperties }); // Throws TypeError
* ```
*
* @param property Property key to check for.
* @param allowedProperties Properties Array, Map, or Set to check within.
* @returns void
* @throws {TypeError} If the property is not a member of the allowedProperties Array, Map, or Set.
*/
function checkValidProperty(params) {
if (!params || params.property === undefined || params.allowedProperties === undefined) {
throw new TypeError("One or more required parameters missing: 'property, allowedProperties'");
}
var property = params.property, allowedProperties = params.allowedProperties;
if ((Array.isArray(allowedProperties) && !allowedProperties.includes(property)) ||
(allowedProperties instanceof Set && !allowedProperties.has(property)) ||
(allowedProperties instanceof Map && !allowedProperties.has(property))) {
var validProperties = Array.from((allowedProperties instanceof Map) ? allowedProperties.keys() : allowedProperties).join(', ');
throw new TypeError("Out of range: '".concat(property, "'. Must be one of '").concat(validProperties, "'"));
}
}
exports.checkValidProperty = checkValidProperty;
/**
* Determines the JOSE algorithm identifier of the digital signature algorithm based on the `alg` or
* `crv` property of a {@link Jwk | JWK}.
*
* If the `alg` property is present, its value takes precedence and is returned. Otherwise, the
* `crv` property is used to determine the algorithm.
*
* @see {@link https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms | JOSE Algorithms}
* @see {@link https://datatracker.ietf.org/doc/draft-ietf-jose-fully-specified-algorithms/ | Fully-Specified Algorithms for JOSE and COSE}
*
* @example
* ```ts
* const publicKey: Jwk = {
* "kty": "OKP",
* "crv": "Ed25519",
* "x": "FEJG7OakZi500EydXxuE8uMc8uaAzEJkmQeG8khXANw"
* }
* const algorithm = getJoseSignatureAlgorithmFromPublicKey(publicKey);
* console.log(algorithm); // Output: "EdDSA"
* ```
*
* @param publicKey - A JWK containing the `alg` and/or `crv` properties.
* @returns The name of the algorithm associated with the key.
* @throws Error if the algorithm cannot be determined from the provided input.
*/
function getJoseSignatureAlgorithmFromPublicKey(publicKey) {
var curveToJoseAlgorithm = {
'Ed25519': 'EdDSA',
'P-256': 'ES256',
'P-384': 'ES384',
'P-521': 'ES512',
'secp256k1': 'ES256K',
};
// If the key contains an `alg` property that matches a JOSE registered algorithm identifier,
// return its value.
if (publicKey.alg && Object.values(curveToJoseAlgorithm).includes(publicKey.alg)) {
return publicKey.alg;
}
// If the key contains a `crv` property, return the corresponding algorithm.
if (publicKey.crv && Object.keys(curveToJoseAlgorithm).includes(publicKey.crv)) {
return curveToJoseAlgorithm[publicKey.crv];
}
throw new Error("Unable to determine algorithm based on provided input: alg=".concat(publicKey.alg, ", crv=").concat(publicKey.crv, ". ") +
"Supported 'alg' values: ".concat(Object.values(curveToJoseAlgorithm).join(', '), ". ") +
"Supported 'crv' values: ".concat(Object.keys(curveToJoseAlgorithm).join(', '), "."));
}
exports.getJoseSignatureAlgorithmFromPublicKey = getJoseSignatureAlgorithmFromPublicKey;
/**
* Checks if the Web Crypto API is supported in the current runtime environment.
*
* @remarks
* The function uses `globalThis` to provide a universal reference to the global
* scope, regardless of the environment. `globalThis` is a standard feature introduced
* in ECMAScript 2020 that is agnostic to the underlying JavaScript environment, making
* the code portable across browser, Node.js, and Web Workers environments.
*
* In a web browser, `globalThis` is equivalent to the `window` object. In Node.js, it
* is equivalent to the `global` object, and in Web Workers, it corresponds to `self`.
*
* This method checks for the `crypto` object and its `subtle` property on the global scope
* to determine the availability of the Web Crypto API. If both are present, the API is
* supported; otherwise, it is not.
*
* @example
* ```ts
* if (isWebCryptoSupported()) {
* console.log('Crypto operations can be performed');
* } else {
* console.log('Crypto operations are not supported in this environment');
* }
* ```
*
* @returns A boolean indicating whether the Web Crypto API is supported in the current environment.
*/
function isWebCryptoSupported() {
if (globalThis.crypto && globalThis.crypto.subtle) {
return true;
}
else {
return false;
}
}
exports.isWebCryptoSupported = isWebCryptoSupported;
/**
* Generates secure pseudorandom values of the specified length using
* `crypto.getRandomValues`, which defers to the operating system.
*
* @remarks
* This function is a wrapper around `randomBytes` from the '@noble/hashes'
* package. It's designed to be cryptographically strong, suitable for
* generating initialization vectors, nonces, and other random values.
*
* @see {@link https://www.npmjs.com/package/@noble/hashes | @noble/hashes on NPM} for more
* information about the underlying implementation.
*
* @example
* ```ts
* const bytes = randomBytes(32); // Generates 32 random bytes
* ```
*
* @param bytesLength - The number of bytes to generate.
* @returns A Uint8Array containing the generated random bytes.
*/
function randomBytes(bytesLength) {
return (0, utils_1.randomBytes)(bytesLength);
}
exports.randomBytes = randomBytes;
/**
* Generates a UUID (Universally Unique Identifier) using a
* cryptographically strong random number generator following
* the version 4 format, as specified in RFC 4122.
*
* A version 4 UUID is a randomly generated UUID. The 13th character
* is set to '4' to denote version 4, and the 17th character is one
* of '8', '9', 'A', or 'B' to comply with the variant 1 format of
* UUIDs (the high bits are set to '10').
*
* The UUID is a 36 character string, including hyphens, and looks like this:
* xxxxxxxx-xxxx-4xxx-axxx-xxxxxxxxxxxx
*
* Note that while UUIDs are not guaranteed to be unique, they are
* practically unique" given the large number of possible UUIDs and
* the randomness of generation.
*
* @example
* ```ts
* const uuid = randomUuid();
* console.log(uuid); // Outputs a version 4 UUID, e.g., '123e4567-e89b-12d3-a456-426655440000'
* ```
*
* @returns A string containing a randomly generated, 36 character long v4 UUID.
*/
function randomUuid() {
var uuid = crypto_1.crypto.randomUUID();
return uuid;
}
exports.randomUuid = randomUuid;
//# sourceMappingURL=utils.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"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"}
+124
View File
@@ -0,0 +1,124 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { AesCtr } from '../primitives/aes-ctr.js';
import { CryptoAlgorithm } from './crypto-algorithm.js';
/**
* The `AesCtrAlgorithm` class provides a concrete implementation for cryptographic operations using
* the AES algorithm in Counter (CTR) mode. This class implements both {@link Cipher | `Cipher`} and
* { @link KeyGenerator | `KeyGenerator`} interfaces, providing key generation, encryption, and
* decryption features.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
export class AesCtrAlgorithm extends CryptoAlgorithm {
/**
* Decrypts the provided data using AES-CTR.
*
* @remarks
* This method performs AES-CTR decryption on the given encrypted data using the specified key.
* Similar to the encryption process, it requires an initial counter block and the length
* of the counter block, along with the encrypted data and the decryption key. The method
* returns the decrypted data as a Uint8Array.
*
* @example
* ```ts
* const aesCtr = new AesCtrAlgorithm();
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block used during encryption
* const key = { ... }; // A Jwk object representing the same AES key used for encryption
* const decryptedData = await aesCtr.decrypt({
* data: encryptedData,
* counter,
* key,
* length: 128 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
decrypt(params) {
return __awaiter(this, void 0, void 0, function* () {
const plaintext = AesCtr.decrypt(params);
return plaintext;
});
}
/**
* Encrypts the provided data using AES-CTR.
*
* @remarks
* This method performs AES-CTR encryption on the given data using the specified key.
* It requires the initial counter block and the length of the counter block, alongside
* the data and key. The method is designed to work asynchronously and returns the
* encrypted data as a Uint8Array.
*
* @example
* ```ts
* const aesCtr = new AesCtrAlgorithm();
* const data = new TextEncoder().encode('Messsage');
* const counter = new Uint8Array(16); // 16-byte (128-bit) counter block
* const key = { ... }; // A Jwk object representing an AES key
* const encryptedData = await aesCtr.encrypt({
* data,
* counter,
* key,
* length: 128 // Length of the counter in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
encrypt(params) {
return __awaiter(this, void 0, void 0, function* () {
const ciphertext = AesCtr.encrypt(params);
return ciphertext;
});
}
/**
* Generates a symmetric key for AES in Counter (CTR) mode in JSON Web Key (JWK) format.
*
* @remarks
* This method generates a symmetric AES key for use in CTR mode, based on the specified
* `algorithm` parameter which determines the key length. It uses cryptographically secure random
* number generation to ensure the uniqueness and security of the key. The key is returned in JWK
* format.
*
* The generated key includes the following components:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const aesCtr = new AesCtrAlgorithm();
* const privateKey = await aesCtr.generateKey({ algorithm: 'A256CTR' });
* ```
*
* @param params - The parameters for the key generation.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
generateKey({ algorithm }) {
return __awaiter(this, void 0, void 0, function* () {
// Map algorithm name to key length.
const length = { A128CTR: 128, A192CTR: 192, A256CTR: 256 }[algorithm];
// Generate a random private key.
const privateKey = yield AesCtr.generateKey({ length });
// Set the `alg` property based on the specified algorithm.
privateKey.alg = algorithm;
return privateKey;
});
}
}
//# sourceMappingURL=aes-ctr.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-ctr.js","sourceRoot":"","sources":["../../../src/algorithms/aes-ctr.ts"],"names":[],"mappings":";;;;;;;;;AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA4BxD;;;;;;;;GAQG;AACH,MAAM,OAAO,eAAgB,SAAQ,eAAe;IAIlD;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACU,OAAO,CAAC,MACS;;YAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEzC,OAAO,SAAS,CAAC;QACnB,CAAC;KAAA;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACU,OAAO,CAAC,MACS;;YAE5B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAE1C,OAAO,UAAU,CAAC;QACpB,CAAC;KAAA;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACU,WAAW,CAAC,EAAE,SAAS,EACX;;YAEvB,oCAAoC;YACpC,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAoB,CAAC;YAE1F,iCAAiC;YACjC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAExD,2DAA2D;YAC3D,UAAU,CAAC,GAAG,GAAG,SAAS,CAAC;YAE3B,OAAO,UAAU,CAAC;QACpB,CAAC;KAAA;CACF"}
+132
View File
@@ -0,0 +1,132 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { CryptoAlgorithm } from './crypto-algorithm.js';
import { AesGcm } from '../primitives/aes-gcm.js';
/**
* The `AesGcmAlgorithm` class provides a concrete implementation for cryptographic operations using
* the AES algorithm in Galois/Counter Mode (GCM). This class implements both
* {@link Cipher | `Cipher`} and { @link KeyGenerator | `KeyGenerator`} interfaces, providing
* key generation, encryption, and decryption features.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
export class AesGcmAlgorithm extends CryptoAlgorithm {
/**
* Decrypts the provided data using AES-GCM.
*
* @remarks
* This method performs AES-GCM decryption on the given encrypted data using the specified key.
* It requires an initialization vector (IV), the encrypted data along with the decryption key,
* and optionally, additional authenticated data (AAD). The method returns the decrypted data as a
* Uint8Array. The optional `tagLength` parameter specifies the size in bits of the authentication
* tag used when encrypting the data. If not specified, the default tag length of 128 bits is
* used.
*
* @example
* ```ts
* const aesGcm = new AesGcmAlgorithm();
* const encryptedData = new Uint8Array([...]); // Encrypted data
* const iv = new Uint8Array([...]); // Initialization vector used during encryption
* const additionalData = new Uint8Array([...]); // Optional additional authenticated data
* const key = { ... }; // A Jwk object representing the AES key
* const decryptedData = await aesGcm.decrypt({
* data: encryptedData,
* iv,
* additionalData,
* key,
* tagLength: 128 // Optional tag length in bits
* });
* ```
*
* @param params - The parameters for the decryption operation.
*
* @returns A Promise that resolves to the decrypted data as a Uint8Array.
*/
decrypt(params) {
return __awaiter(this, void 0, void 0, function* () {
const plaintext = AesGcm.decrypt(params);
return plaintext;
});
}
/**
* Encrypts the provided data using AES-GCM.
*
* @remarks
* This method performs AES-GCM encryption on the given data using the specified key.
* It requires an initialization vector (IV), the encrypted data along with the decryption key,
* and optionally, additional authenticated data (AAD). The method returns the encrypted data as a
* Uint8Array. The optional `tagLength` parameter specifies the size in bits of the authentication
* tag generated in the encryption operation and used for authentication in the corresponding
* decryption. If not specified, the default tag length of 128 bits is used.
*
* @example
* ```ts
* const aesGcm = new AesGcmAlgorithm();
* const data = new TextEncoder().encode('Messsage');
* const iv = new Uint8Array([...]); // Initialization vector
* const additionalData = new Uint8Array([...]); // Optional additional authenticated data
* const key = { ... }; // A Jwk object representing an AES key
* const encryptedData = await aesGcm.encrypt({
* data,
* iv,
* additionalData,
* key,
* tagLength: 128 // Optional tag length in bits
* });
* ```
*
* @param params - The parameters for the encryption operation.
*
* @returns A Promise that resolves to the encrypted data as a Uint8Array.
*/
encrypt(params) {
return __awaiter(this, void 0, void 0, function* () {
const ciphertext = AesGcm.encrypt(params);
return ciphertext;
});
}
/**
* Generates a symmetric key for AES in Galois/Counter Mode (GCM) in JSON Web Key (JWK) format.
*
* @remarks
* This method generates a symmetric AES key for use in GCM mode, based on the specified
* `algorithm` parameter which determines the key length. It uses cryptographically secure random
* number generation to ensure the uniqueness and security of the key. The key is returned in JWK
* format.
*
* The generated key includes the following components:
* - `kty`: Key Type, set to 'oct' for Octet Sequence.
* - `k`: The symmetric key component, base64url-encoded.
* - `kid`: Key ID, generated based on the JWK thumbprint.
*
* @example
* ```ts
* const aesGcm = new AesGcmAlgorithm();
* const privateKey = await aesGcm.generateKey({ algorithm: 'A256GCM' });
* ```
*
* @param params - The parameters for the key generation.
*
* @returns A Promise that resolves to the generated symmetric key in JWK format.
*/
generateKey({ algorithm }) {
return __awaiter(this, void 0, void 0, function* () {
// Map algorithm name to key length.
const length = { A128GCM: 128, A192GCM: 192, A256GCM: 256 }[algorithm];
// Generate a random private key.
const privateKey = yield AesGcm.generateKey({ length });
// Set the `alg` property based on the specified algorithm.
privateKey.alg = algorithm;
return privateKey;
});
}
}
//# sourceMappingURL=aes-gcm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"aes-gcm.js","sourceRoot":"","sources":["../../../src/algorithms/aes-gcm.ts"],"names":[],"mappings":";;;;;;;;;AAKA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAuB,MAAM,0BAA0B,CAAC;AAmDvE;;;;;;;;GAQG;AACH,MAAM,OAAO,eAAgB,SAAQ,eAAe;IAIlD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,OAAO,CAAC,MACS;;YAE5B,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAEzC,OAAO,SAAS,CAAC;QACnB,CAAC;KAAA;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,OAAO,CAAC,MACS;;YAE5B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAE1C,OAAO,UAAU,CAAC;QACpB,CAAC;KAAA;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACU,WAAW,CAAC,EAAE,SAAS,EACX;;YAEvB,oCAAoC;YACpC,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAoB,CAAC;YAE1F,iCAAiC;YACjC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;YAExD,2DAA2D;YAC3D,UAAU,CAAC,GAAG,GAAG,SAAS,CAAC;YAE3B,OAAO,UAAU,CAAC;QACpB,CAAC;KAAA;CACF"}
@@ -0,0 +1,6 @@
/**
* Base class for all cryptographic algorithm implementations.
*/
export class CryptoAlgorithm {
}
//# sourceMappingURL=crypto-algorithm.js.map
@@ -0,0 +1 @@
{"version":3,"file":"crypto-algorithm.js","sourceRoot":"","sources":["../../../src/algorithms/crypto-algorithm.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAgB,eAAe;CAAG"}
+237
View File
@@ -0,0 +1,237 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Secp256k1 } from '../primitives/secp256k1.js';
import { Secp256r1 } from '../primitives/secp256r1.js';
import { CryptoAlgorithm } from './crypto-algorithm.js';
import { isEcPrivateJwk, isEcPublicJwk } from '../jose/jwk.js';
/**
* The `EcdsaAlgorithm` class provides a concrete implementation for cryptographic operations using
* the Elliptic Curve Digital Signature Algorithm (ECDSA). This class implements both
* {@link Signer | `Signer`} and { @link AsymmetricKeyGenerator | `AsymmetricKeyGenerator`}
* interfaces, providing private key generation, public key derivation, and creation/verification
* of signatures.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
export class EcdsaAlgorithm extends CryptoAlgorithm {
/**
* Derives the public key in JWK format from a given private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The process ensures that the derived public key correctly corresponds to
* the given private key.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await ecdsa.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
computePublicKey({ key }) {
return __awaiter(this, void 0, void 0, function* () {
if (!isEcPrivateJwk(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
switch (key.crv) {
case 'secp256k1': {
const publicKey = yield Secp256k1.computePublicKey({ key });
publicKey.alg = 'ES256K';
return publicKey;
}
case 'P-256': {
const publicKey = yield Secp256r1.computePublicKey({ key });
publicKey.alg = 'ES256';
return publicKey;
}
default: {
throw new Error(`Unsupported curve: ${key.crv}`);
}
}
});
}
/**
* Generates a new private key with the specified algorithm in JSON Web Key (JWK) format.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const privateKey = await ecdsa.generateKey({ algorithm: 'ES256K' });
* ```
*
* @param params - The parameters for key generation.
* @param params.algorithm - The algorithm to use for key generation.
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
generateKey({ algorithm }) {
return __awaiter(this, void 0, void 0, function* () {
switch (algorithm) {
case 'ES256K':
case 'secp256k1': {
const privateKey = yield Secp256k1.generateKey();
privateKey.alg = 'ES256K';
return privateKey;
}
case 'ES256':
case 'secp256r1': {
const privateKey = yield Secp256r1.generateKey();
privateKey.alg = 'ES256';
return privateKey;
}
}
});
}
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an ECDSA private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key.
*
* Note: This method offers a significant performance advantage, being about 200 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await ecdsa.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
getPublicKey({ key }) {
return __awaiter(this, void 0, void 0, function* () {
if (!isEcPrivateJwk(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
switch (key.crv) {
case 'secp256k1': {
const publicKey = yield Secp256k1.getPublicKey({ key });
publicKey.alg = 'ES256K';
return publicKey;
}
case 'P-256': {
const publicKey = yield Secp256r1.getPublicKey({ key });
publicKey.alg = 'ES256';
return publicKey;
}
default: {
throw new Error(`Unsupported curve: ${key.crv}`);
}
}
});
}
/**
* Generates an ECDSA signature of given data using a private key.
*
* @remarks
* This method uses the signature algorithm determined by the given `algorithm` to sign the
* provided data.
*
* The signature can later be verified by parties with access to the corresponding
* public key, ensuring that the data has not been tampered with and was indeed signed by the
* holder of the private key.
*
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const data = new TextEncoder().encode('Message');
* const privateKey = { ... }; // A Jwk object representing a private key
* const signature = await ecdsa.sign({
* key: privateKey,
* data
* });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign.
*
* @returns A Promise resolving to the digital signature as a `Uint8Array`.
*/
sign({ key, data }) {
return __awaiter(this, void 0, void 0, function* () {
if (!isEcPrivateJwk(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) private key.');
switch (key.crv) {
case 'secp256k1': {
return yield Secp256k1.sign({ key, data });
}
case 'P-256': {
return yield Secp256r1.sign({ key, data });
}
default: {
throw new Error(`Unsupported curve: ${key.crv}`);
}
}
});
}
/**
* Verifies an ECDSA signature associated with the provided data using the provided key.
*
* @remarks
* This method uses the signature algorithm determined by the `crv` property of the provided key
* to check the validity of a digital signature against the original data. It confirms whether the
* signature was created by the holder of the corresponding private key and that the data has not
* been tampered with.
*s
* @example
* ```ts
* const ecdsa = new EcdsaAlgorithm();
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const data = new TextEncoder().encode('Message');
* const isValid = await ecdsa.verify({
* key: publicKey,
* signature,
* data
* });
* ```
*
* @param params - The parameters for the verification operation.
* @param params.key - The key to use for verification.
* @param params.signature - The signature to verify.
* @param params.data - The data to verify.
*
* @returns A Promise resolving to a boolean indicating whether the signature is valid.
*/
verify({ key, signature, data }) {
return __awaiter(this, void 0, void 0, function* () {
if (!isEcPublicJwk(key))
throw new TypeError('Invalid key provided. Must be an elliptic curve (EC) public key.');
switch (key.crv) {
case 'secp256k1': {
return yield Secp256k1.verify({ key, signature, data });
}
case 'P-256': {
return yield Secp256r1.verify({ key, signature, data });
}
default: {
throw new Error(`Unsupported curve: ${key.crv}`);
}
}
});
}
}
//# sourceMappingURL=ecdsa.js.map
@@ -0,0 +1 @@
{"version":3,"file":"ecdsa.js","sourceRoot":"","sources":["../../../src/algorithms/ecdsa.ts"],"names":[],"mappings":"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"}
+213
View File
@@ -0,0 +1,213 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Ed25519 } from '../primitives/ed25519.js';
import { CryptoAlgorithm } from './crypto-algorithm.js';
import { isOkpPrivateJwk, isOkpPublicJwk } from '../jose/jwk.js';
/**
* The `EdDsaAlgorithm` class provides a concrete implementation for cryptographic operations using
* the Edwards-curve Digital Signature Algorithm (EdDSA). This class implements both
* {@link Signer | `Signer`} and { @link AsymmetricKeyGenerator | `AsymmetricKeyGenerator`}
* interfaces, providing private key generation, public key derivation, and creation/verification
* of signatures.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
export class EdDsaAlgorithm extends CryptoAlgorithm {
/**
* Derives the public key in JWK format from a given private key.
*
* @remarks
* This method takes a private key in JWK format and derives its corresponding public key,
* also in JWK format. The process ensures that the derived public key correctly corresponds to
* the given private key.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await eddsa.computePublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for the public key derivation.
* @param params.key - The private key in JWK format from which to derive the public key.
*
* @returns A Promise that resolves to the derived public key in JWK format.
*/
computePublicKey({ key }) {
return __awaiter(this, void 0, void 0, function* () {
if (!isOkpPrivateJwk(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
switch (key.crv) {
case 'Ed25519': {
const publicKey = yield Ed25519.computePublicKey({ key });
publicKey.alg = 'EdDSA';
return publicKey;
}
default: {
throw new Error(`Unsupported curve: ${key.crv}`);
}
}
});
}
/**
* Generates a new private key with the specified algorithm in JSON Web Key (JWK) format.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const privateKey = await eddsa.generateKey({ algorithm: 'Ed25519' });
* ```
*
* @param params - The parameters for key generation.
* @param params.algorithm - The algorithm to use for key generation.
*
* @returns A Promise that resolves to the generated private key in JWK format.
*/
generateKey({ algorithm }) {
return __awaiter(this, void 0, void 0, function* () {
switch (algorithm) {
case 'Ed25519': {
const privateKey = yield Ed25519.generateKey();
privateKey.alg = 'EdDSA';
return privateKey;
}
}
});
}
/**
* Retrieves the public key properties from a given private key in JWK format.
*
* @remarks
* This method extracts the public key portion from an EdDSA private key in JWK format. It does
* so by removing the private key property 'd' and making a shallow copy, effectively yielding the
* public key.
*
* Note: This method offers a significant performance advantage, being about 100 times faster
* than `computePublicKey()`. However, it does not mathematically validate the private key, nor
* does it derive the public key from the private key. It simply extracts existing public key
* properties from the private key object. This makes it suitable for scenarios where speed is
* critical and the private key's integrity is already assured.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const privateKey = { ... }; // A Jwk object representing a private key
* const publicKey = await eddsa.getPublicKey({ key: privateKey });
* ```
*
* @param params - The parameters for retrieving the public key properties.
* @param params.key - The private key in JWK format.
*
* @returns A Promise that resolves to the public key in JWK format.
*/
getPublicKey({ key }) {
return __awaiter(this, void 0, void 0, function* () {
if (!isOkpPrivateJwk(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
switch (key.crv) {
case 'Ed25519': {
const publicKey = yield Ed25519.getPublicKey({ key });
publicKey.alg = 'EdDSA';
return publicKey;
}
default: {
throw new Error(`Unsupported curve: ${key.crv}`);
}
}
});
}
/**
* Generates an EdDSA signature of given data using a private key.
*
* @remarks
* This method uses the signature algorithm determined by the given `algorithm` to sign the
* provided data.
*
* The signature can later be verified by parties with access to the corresponding
* public key, ensuring that the data has not been tampered with and was indeed signed by the
* holder of the private key.
*
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const data = new TextEncoder().encode('Message');
* const privateKey = { ... }; // A Jwk object representing a private key
* const signature = await eddsa.sign({
* key: privateKey,
* data
* });
* ```
*
* @param params - The parameters for the signing operation.
* @param params.key - The private key to use for signing, represented in JWK format.
* @param params.data - The data to sign.
*
* @returns A Promise resolving to the digital signature as a `Uint8Array`.
*/
sign({ key, data }) {
return __awaiter(this, void 0, void 0, function* () {
if (!isOkpPrivateJwk(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) private key.');
switch (key.crv) {
case 'Ed25519': {
return yield Ed25519.sign({ key, data });
}
default: {
throw new Error(`Unsupported curve: ${key.crv}`);
}
}
});
}
/**
* Verifies an EdDSA signature associated with the provided data using the provided key.
*
* @remarks
* This method uses the signature algorithm determined by the `crv` property of the provided key
* to check the validity of a digital signature against the original data. It confirms whether the
* signature was created by the holder of the corresponding private key and that the data has not
* been tampered with.
*s
* @example
* ```ts
* const eddsa = new EdDsaAlgorithm();
* const publicKey = { ... }; // Public key in JWK format corresponding to the private key that signed the data
* const signature = new Uint8Array([...]); // Signature to verify
* const data = new TextEncoder().encode('Message');
* const isValid = await eddsa.verify({
* key: publicKey,
* signature,
* data
* });
* ```
*
* @param params - The parameters for the verification operation.
* @param params.key - The key to use for verification.
* @param params.signature - The signature to verify.
* @param params.data - The data to verify.
*
* @returns A Promise resolving to a boolean indicating whether the signature is valid.
*/
verify({ key, signature, data }) {
return __awaiter(this, void 0, void 0, function* () {
if (!isOkpPublicJwk(key))
throw new TypeError('Invalid key provided. Must be an octet key pair (OKP) public key.');
switch (key.crv) {
case 'Ed25519': {
return yield Ed25519.verify({ key, signature, data });
}
default: {
throw new Error(`Unsupported curve: ${key.crv}`);
}
}
});
}
}
//# sourceMappingURL=eddsa.js.map
@@ -0,0 +1 @@
{"version":3,"file":"eddsa.js","sourceRoot":"","sources":["../../../src/algorithms/eddsa.ts"],"names":[],"mappings":"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"}
+57
View File
@@ -0,0 +1,57 @@
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Sha256 } from '../primitives/sha256.js';
import { CryptoAlgorithm } from './crypto-algorithm.js';
/**
* The `Sha2Algorithm` class is an implementation of the {@link Hasher | `Hasher`} interface for the
* SHA-2 family of cryptographic hash functions. The `digest` method takes the algorithm identifier
* of the hash function and arbitrary data as input and returns the hash digest of the data.
*
* This class is typically accessed through implementations that extend the
* {@link CryptoApi | `CryptoApi`} interface.
*/
export class Sha2Algorithm extends CryptoAlgorithm {
/**
* Generates a hash digest of the provided data.
*
* @remarks
* A digest is the output of the hash function. It's a fixed-size string of bytes
* that uniquely represents the data input into the hash function. The digest is often used for
* data integrity checks, as any alteration in the input data results in a significantly
* different digest.
*
* It takes the algorithm identifier of the hash function and data to digest as input and returns
* the digest of the data.
*
* @example
* ```ts
* const sha2 = new Sha2Algorithm();
* const data = new TextEncoder().encode('Messsage');
* const digest = await sha2.digest({ data });
* ```
*
* @param params - The parameters for the digest operation.
* @param params.algorithm - The name of hash function to use.
* @param params.data - The data to digest.
*
* @returns A Promise which will be fulfilled with the hash digest.
*/
digest({ algorithm, data }) {
return __awaiter(this, void 0, void 0, function* () {
switch (algorithm) {
case 'SHA-256': {
const hash = yield Sha256.digest({ data });
return hash;
}
}
});
}
}
//# sourceMappingURL=sha-2.js.map
@@ -0,0 +1 @@
{"version":3,"file":"sha-2.js","sourceRoot":"","sources":["../../../src/algorithms/sha-2.ts"],"names":[],"mappings":";;;;;;;;;AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAcxD;;;;;;;GAOG;AACH,MAAM,OAAO,aAAc,SAAQ,eAAe;IAGhD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,MAAM,CAAC,EAAE,SAAS,EAAE,IAAI,EAAoB;;YACvD,QAAQ,SAAS,EAAE;gBAEjB,KAAK,SAAS,CAAC,CAAC;oBACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC3C,OAAO,IAAI,CAAC;iBACb;aACF;QAEH,CAAC;KAAA;CACF"}
+25
View File
@@ -0,0 +1,25 @@
export * from './local-key-manager.js';
export * as utils from './utils.js';
export * from './algorithms/aes-ctr.js';
export * from './algorithms/aes-gcm.js';
export * from './algorithms/crypto-algorithm.js';
export * from './algorithms/ecdsa.js';
export * from './algorithms/eddsa.js';
export * from './algorithms/sha-2.js';
export * from './jose/jwe.js';
export * from './jose/jwk.js';
export * from './jose/jws.js';
export * from './jose/jwt.js';
export * from './jose/utils.js';
export * from './primitives/aes-ctr.js';
export * from './primitives/aes-gcm.js';
export * from './primitives/concat-kdf.js';
export * from './primitives/ed25519.js';
export * from './primitives/secp256r1.js';
export * from './primitives/pbkdf2.js';
export * from './primitives/secp256k1.js';
export * from './primitives/sha256.js';
export * from './primitives/x25519.js';
export * from './primitives/xchacha20.js';
export * from './primitives/xchacha20-poly1305.js';
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AAEpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,kCAAkC,CAAC;AACjD,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AAEtC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAEhC,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,oCAAoC,CAAC"}
+2
View File
@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=jwe.js.map

Some files were not shown because too many files have changed in this diff Show More