npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@do-ob/crypto

v1.0.0

Published

Common cross-platform pre-configured cryptography methods using Node.js and Web Crypto API

Downloads

10

Readme

Cross-Platform Crypto Methods

This library contains of a set of preconfigured cryptographic methods using native Web Crypto API. It is tested and designed to be used in both the browser and Node.JS environments.

This package has ZERO dependencies by solely leveraging the environment's native crypto libraries.

Installation

The package can be installed using npm, yarn or pnpm.

npm install @do-ob/crypto
yarn add @do-ob/crypto
pnpm add @do-ob/crypto

WebCrypto Usage

Import the cross-platform Web Crypto object.

For documentation on the Web Crypto API, see MDN Web Crypto API.

import { webcrypto } from '@do-ob/crypto';

(async () => {
  const wc = await webcrypto();

  // Use the native webcrypto API
})();

Encoding Modules

The library includes a set of modules that can be used to encode and decode data for transit or other uses.

Base64

Encode strings to and from base64.

import { base64 } from '@do-ob/crypto';

// Encode strings to base64
const encoded = base64.encode('Hello, World!');
/**
 * Or encode a Uint8Array
 * const encoded = base64.encode(new Uint8Array([1, 2, 3, 4, 5]));
 */

// Decode base64 to string
const decoded = base64.decode(encoded);

Encode a JSON object to and from base64. JSON encodings are unpadded.

import { base64 } from '@do-ob/crypto';

const obj = { hello: 'world' };

// Encode JSON object to base64
const encoded = base64.encodeJson(obj);

// Decode base64 to JSON object
const decoded = base64.decodeJson(encoded);
// decoded = { hello: 'world' }

Random

Generate random base64 encoded string of a given length.

import { random } from '@do-ob/crypto';

// Generates an encoded string of 32 characters.
const challenge = random.chars(32);

Encryption Modules

The library includes a set of encryption modules that can be used to encrypt, decrypt, sign, or verify data.

Hash

Hash data using the default SHA-256.

You can optionally select the following algorithms: SHA-1 (for non-crypto applications), SHA-256, SHA-384, or SHA-512.

import { hash } from '@do-ob/crypto';

// Hash a string using SHA-256
const hashed = await hash('Hello, World!');

// Hash a string using SHA-512
const hashed = await hash('Hello, World!', 'SHA-512');

Symmetric Encryption

Encrypt and decrypt data using AES-GCM (256).

import { sym } from '@do-ob/crypto';

// Generate a new key.
const key = await sym.generate();

/**
 * Encrypt data
 * 
 * If a key is not provided, a singlton key for this runtime instance will be used.
 */
const encrypted = await sym.encrypt('Hello, World!', key);

/**
 * Decrypt data
 * 
 * If a key is not provided, a singlton key for this runtime instance will be used.
 */
const decrypted = await sym.decrypt(encrypted, key);
/**
 * decrypted = 'Hello, World!'
 * 
 * If the data cannot be decrypted, the method will return undefined.
 */

Asymmetric Encryption

Encrypt and decrypt data using RSA-OAEP (4096).

import { asym } from '@do-ob/crypto';

// Generate a new key pair for encryption and decryption.
const encryptorKeyPair = await asym.generate('encryptor');

/**
 * Encrypt data
 * 
 * If a public key is not provided, a key from the singlton key pair for this runtime instance will be used.
 */
const encrypted = await asym.encrypt('Hello, World!', encryptorKeyPair.publicKey);

/**
 * Decrypt data
 * 
 * If a private key is not provided, a key from the singlton key pair for this runtime instance will be used.
 */
const decrypted = await asym.decrypt(encrypted, encryptorKeyPair.privateKey);
/**
 * decrypted = 'Hello, World!'
 * 
 * If the data cannot be decrypted, the method will return undefined.
 */

Asymmetric Signatures

Sign and verify data using ECDSA + P-256 + SHA-256.

import { asym } from '@do-ob/crypto';

// Generate a new key pair for signing and verification.
const signerKeyPair = await asym.generate('signer');

/**
 * Sign data
 * 
 * If a private key is not provided, a key from the singlton key pair for this runtime instance will be used.
 */
const signature = await asym.sign('Hello, World!', signerKeyPair.privateKey);

/**
 * Verify data
 * 
 * If a public key is not provided, a key from the singlton key pair for this runtime instance will be used.
 */
const verified = await asym.verify('Hello, World!', signature, signerKeyPair.publicKey);
/**
 * verified = true
 * 
 * If the data cannot be verified, the method will return false.
 */

Key Management

This module can be used to export or wrap keys.

Using Smith to Export and Import Keys

import { smith } from '@do-ob/crypto';

// Generate a new symetric key.
const newSymKey = await sym.generate();
// Generate a new asymetric encryptor key.
const newAsymEncryptorKey = await asym.generate('encryptor');
// Generate a new asymetric signer key.
const newAsymSignerKey = await asym.generate('signer');

// Export the keys, returning a base64 encoded JWK (a string).
const jwkSym = await smith.export(newSymKey, 'symEncryptor');
const jwkAsymEncryptor = await smith.export(newAsymEncryptorKey, 'asymEncryptor');
const jwkAsymSigner = await smith.export(newAsymSignerKey, 'asymSigner');

// Import the keys back into a CryptoKey object.
const importedSymKey = await smith.import(jwkSym);
const importedAsymEncryptorKey = await smith.import(jwkAsymEncryptor);
const importedAsymSignerKey = await smith.import(jwkAsymSigner);

Import keys obtained from a CredentialsContainer while using the Web Authentication API.

import { smith } from '@do-ob/crypto';

// Get the public key from the Web Authentication API.
const credential = await navigator.credentials.create({ publicKey: { /** Public Key Credential Options... **/ } });

const publicKeyBuffer = credential.response.getPublicKey(); // SPKI ArrayBuffer
const publicKeyAlgorithm = credential.response.getPublicKeyAlgorithm(); // -7 or -257

// Imports the public key into a CryptoKey object whcih can now be used to verify signatures.
const publicKey = await smith.importWebauthn(publicKeyBuffer, publicKeyAlgorithm);

Using Smith to Wrap and Unwrap Keys

import { smith } from '@do-ob/crypto';

// Generate a new symetric key.
const newSymKey = await sym.generate();
// Generate a new asymetric encryptor key.
const newAsymEncryptorKey = await asym.generate('encryptor');
// Generate a new asymetric signer key.
const newAsymSignerKey = await asym.generate('signer');

// Wrap the keys with a password, returning a base64 encoded JWK (a string).
const wrappedSymKey = await smith.wrap(newSymKey, 'MyPassword', 'symEncryptor');
const wrappedAsymEncryptorKey = await smith.wrap(newAsymEncryptorKey, 'MyPassword', 'asymEncryptor');
const wrappedAsymSignerKey = await smith.wrap(newAsymSignerKey, 'MyPassword', 'asymSigner');

// Unwrap the keys with the password.
const unwrappedSymKey = await smith.unwrap(wrappedSym, 'MyPassword');
const unwrappedAsymEncryptorKey = await smith.unwrap(wrappedAsymEncryptorKey, 'MyPassword');
const unwrappedAsymSignerKey = await smith.unwrap(wrappedAsymSignerKey, 'MyPassword');

JWT Tokens

This module can be used to create and verify asymetric JWT tokens.

import { token } from '@do-ob/crypto';

// Generate a new asymetric key pair for signing and verification.
const signerKeyPair = await asym.generate('signer');

// Create a numeric date to set the expiration for 30 minutes from now.
const exp = Date.now() + 1800000;

// Create a new JWT token.
const jwt = await token.sign({ hello: 'world', exp }, signerKeyPair.privateKey);

// Verify a JWT token.
const verified = await token.verify(jwt, signerKeyPair.publicKey);
/**
 * verified = { hello: 'world' }
 * 
 * If the token cannot be verified, the method will return an error code.
 */
switch (verified) {
  case token.TokenError.InvalidFormat:
    // Token is poorly formatted.
    break;
  case token.TokenError.InvalidHeader:
    // Token header is invalid.
    break;
  case token.TokenError.InvalidPayload:
    // Token payload is invalid.
    break;
  case token.TokenError.InvalidSignature:
    // Token signature is invalid.
    break;
  case token.TokenError.Expired:
    // Token has expired.
    break;
  case token.TokenError.CantParse:
    // Token's JSON cannot be parsed.
    break;
}

// Can also decode a JWT token without verifying it.
const decoded = token.decode(jwt);
/**
 * decoded = { hello: 'world' }
 * 
 * If the token cannot be decoded, the method will also return token.TokenError error code.
 */

Sessions

This module can be used to create and verify session encryptions.

For the web, these sessions should only be stored in a secure HttpOnly cookie.

import { session } from '@do-ob/crypto';

// Generate a new symetric key.
const newSymKey = await sym.generate();

// Create a numeric date to set the expiration for 1 day from now.
const exp = Date.now() + 86400000;

// Encrypt a new session.
const session = await session.encrypt({ hello: 'world', exp }, newSymKey);

// Decrypt a session.
const decrypted = await session.decrypt(session, newSymKey);

/**
 * decrypted = { hello: 'world' }
 * 
 * If the session cannot be decrypted, the method will return a SessionError.
 */
switch (decrypted) {
  case session.SessionError.DecryptionFailed:
    // Session is could not be decrypted.
    break;
  case session.SessionError.Expired:
    // Session has expired.
    break;
  case session.SessionError.CantParse:
    // Session's JSON cannot be parsed.
    break;
}

License

This project is licensed under the MIT License - see the LICENSE file for details.

References