3.7.2 • Published 8 months ago

@keeex/crypto v3.7.2

Weekly downloads
-
License
SEE LICENSE IN LI...
Repository
-
Last release
8 months ago

KeeeX Cryptography helper

Bugs Code Smells Maintainability Rating Security Rating Vulnerabilities Technical Debt Coverage

This library provides some cryptographic functions. There is a pure JavaScript implementation available, but it is recommended to import environment-specific implementations for better performances.

If randomness is required, it is mandatory to use a specific implementation, as the pure JavaScript one can't guarantee secure randomness.

Supported platforms

The following implementations are available, each in its own package to avoid conflicts :

  • @keeex/crypto-provider-browser: based on Subtle Crypto available in most web browsers
  • @keeex/crypto-provider-node: based on Node's crypto module
  • @keeex/crypto-provider-reactnative: based on native crypto module for both Android and iOS

There is also a pure JavaScript implementation available by calling usePureJSProvider() instead of importing one of these packages. This implementation does not provide a safe random number generation.

Aside from the purejs one, all implementations provides at least a secure source of randomness. Some feature/algorithms might not be supported natively everywhere; providers usually fallback to the JavaScript implementation for these parts.

Older versions of the library provided automatic fallback to the JavaScript implementation, but this was removed in favor of handling them in each provider to reduce bundle size.

Supported algorithms

The following algorithms are supported for each classes of cryptographic algorithms:

Random functions

The library provide a source of random bytes.

Digest

  • SHA-224
  • SHA-256
  • SHA-512
  • RIPEMD-160
  • KeeeX Multihash (see below)

Hmac

  • SHA-256
  • SHA-512

Key derivation

  • PBKDF2 based on SHA-256 or SHA-512

Symmetric encryption

  • AES-CTR (128, 192, 256)
  • AES-CBC (128, 192, 256)

What is used in the pure JavaScript implementation

The random source when using the pure JavaScript library is not safe for cryptographic uses; it is merely provided as a way to start developping. In production environment a proper cryptographic provider with a safe random source is mandatory.

Node, browser and others

The library is provided in the @keeex/crypto/lib directory, and the rest of this document is based on that. This version is built with recent JavaScript implementation in mind. To improve compatibility with web browsers, a transpiled version is available in @keeex/crypto/web. It's interface is entirely identical, to the lib one but it can be used more safely with older JavaScript engines.

Specific implementations

To use a specific provider, import them. Providers automatically register themselves when loaded.

Using cryptographic functions

Wether you use a specific provider or the default one, you can directly call functions from the appropriate modules:

  • @keeex/crypto/lib/cipher for symmetric encryption
  • @keeex/crypto/lib/digest for hash functions
  • @keeex/crypto/lib/hmac for hmac
  • @keeex/crypto/lib/keys for key handling
  • @keeex/crypto/lib/random for random source

Stream API

A stream API is available for some algorithms. For now it is only available for Node and cipher functions.

Stream cipher

It is possible to create an encryption stream by creating an instance of the Encrypt class available as @keeex/crypto/lib/stream/cipher/encrypt default export. The encryption key must be provided as the encryptionKey field of the constructor's option parameter. The stream can then be used as a Transform stream, accepting plaintext input and outputting encrypted data. A small header containing the IV is automatically added so the user does not have to take care of it.

To decrypt, a similar procedure is available using Decrypt instead of Encrypt.

The data format used by stream encryption is compatible with the one used in encryptImmediate().

Available classes of algorithms

Cipher functions

  • encryptRawImmediate() encrypt a single buffer and return the encrypted buffer and the IV
  • encryptImmediate() encrypt a single buffer and return a block containing both the encrypted buffer and the IV as one buffer
  • decryptRawImmediate() decrypt an ecrypted buffer with the provided IV
  • decryptImmediate() decrypt an encrypted buffer previously produced by a call to encryptImmediate()
  • createEncryptionContext() create a context which can be updated multiple time with more input for encryption
  • createDecryptionContext() is the decryption equivalent of createEncryptionContext()

Hash functions

  • digestImmediate() compute the hash of a buffer
  • digestString() compute the hash of a string
  • digest() return a hasher to process input by chunk.

The hasher provides two method: update() that accept an Uint8Array and digest(). Both return promises, and digest() return a promise that resolve with an Uint8Array.

KeeeX Multihash

This library implements KeeeX's multihash algorithm, which intend to strenghten the use of digest function by reducing the odds of an attacker producing a "legitimate" fake input that have the same digest.

To chain multiple digest in this fashion, you can pass an array of algorithms to any of the three digest functions above.

The output will be, assuming three algorithms H3, H2 and H1: H(D)=H3(D|H2(D|H1(D))).

Hmac functions

  • hmacImmediate() compute the HMAC of a single buffer
  • hmac() is similar to digest() but with a key provided for HMAC computations

Key handling

Key objects returned by these functions are opaque objects intended for use only with the appropriate crypto call from this library.

  • generateCryptoKey() generate a random key
  • importCryptoKey() create a key object from user-provided material
  • deriveKey() uses a PBKDF2 function to derivate a key from a password
  • deriveKeyRaw() uses a PBKDF2 function to derivate an Uint8Array from a password

Random source

  • randomBytes() provides the requested number of random bytes

Implementing a provider

A crypto provider is basically an object matching the CryptoProvider interface. It is responsible for implementing all the required functions and fallbacks, as applicable.

The majorVersion property of the provider must match the major version of this package.

Digest provider

For digest implementations, at least one of digestImmediate() or digest() must be implemented. If only one is provided, the other will be used as a fallback.

Random provider

The randomBytes() implementation is mandatory.

Cipher provider

Similar to digest, cipher can be provided either with an "immediate" method that take the full input at once, or with a "chunk" based approach which takes sequential blocks of input to produce output.

For the following three groups of functions, if one is missing the other is used as a fallback.

For generating IV, either getIVSize() or generateIV() are required. For encryption, one of encryptRawImmediate() or createEncryptionContext() is required. For decryption, one of decryptRawImmediate() or createDecryptionContext() is required.

Note that encryption is based on CryptoKey instances, so there's a tight coupling between these and the various key generation functions.

Key provider

The importCryptoKey() and deriveKeyRaw() functions are mandatory. Other functions (generateCryptoKey() and deriveKey()) can be provided, but can also be implemented by fallbacks using the other two.

Hmac provider

The hmacImmediate() function is optional, as it can be bridged using regular digest code. Same for hmac().

Testing

The core crypto library (shared implementations and general data handling) can be tested locally using npm test. It runs against the built-in pure JavaScript implementation.

To test other cryptographic providers, import them in the regular fashion and call runTest(). Depending on the environment provided, stream features might be skipped for testing.