KeeeX Cryptography helper
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
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 IVencryptImmediate()
encrypt a single buffer and return a block containing both the encrypted
buffer and the IV as one bufferdecryptRawImmediate()
decrypt an ecrypted buffer with the provided IVdecryptImmediate()
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 encryptioncreateDecryptionContext()
is the decryption equivalent of createEncryptionContext()
Hash functions
digestImmediate()
compute the hash of a bufferdigestString()
compute the hash of a stringdigest()
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 bufferhmac()
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 keyimportCryptoKey()
create a key object from user-provided materialderiveKey()
uses a PBKDF2 function to derivate a key from a passwordderiveKeyRaw()
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.