Dhole Cryptography

Secure, easy-to-use, cross-platform cryptography interface powered by libsodium.
const {
    Asymmetric,
    AsymmetricSecretKey
} = require('dhole-crypto');

(async function () {
    let foxSecret = await AsymmetricSecretKey.generate();
    let foxPublic = foxSecret.getPublicKey();

    let wolfSecret = await AsymmetricSecretKey.generate();
    let wolfPublic = wolfSecret.getPublicKey();

    let message = "Only you can decrypt this message, and you can verify I sent it.";
    let encrypted = await Asymmetric.encrypt(message, foxPublic, wolfSecret);
    let decrypted = await Asymmetric.decrypt(encrypted, foxSecret, wolfPublic);
    console.log(decrypted);
})();

Get Dhole for your Node.js project:

npm install dhole-crypto

Also available on Github.

<?php
use Soatok\DholeCrypto\Asymmetric;
use Soatok\DholeCrypto\Key\AsymmetricSecretKey;
use ParagonIE\HiddenString\HiddenString;

$foxSecret = AsymmetricSecretKey::generate();
$foxPublic = $foxSecret->getPublicKey();

$wolfSecret = AsymmetricSecretKey::generate();
$wolfPublic = $wolfSecret->getPublicKey();

$message = new HiddenString("Only you can decrypt this message, and you can verify I sent it.");
$encrypt = Asymmetric::encrypt($message, $wolfPublic, $foxSecret);
$decrypt = Asymmetric::decrypt($encrypt, $wolfSecret, $foxPublic);
echo $decrypt->getString();

Get Dhole for your PHP project:

composer require soatok/dhole-cryptography

Also available on Github.

What is Dhole Cryptography?

Dhole Cryptography is a cross-platform libsodium wrapper that solves the most fundamental security problems (encryption, signatures, password storage, key management) while being as easy as possible for developer to use, then gets out of your way.

Why Use Dhole Instead of Sodium?

Strictly speaking, if you use Dhole, you are using Sodium!

Sodium is a great library and is very hard to misuse, but it doesn't abstract enough complexity away to make it easy to use.

Dhole eliminates this unnecessary complexity while still providing the same security and secure-by-default philosophy:

Need to encrypt a string?

Your code will look like ciphertext = Symmetric.encrypt(plaintext, key). You don't even need to know what a nonce is. You don't need to worry about output encoding and binary-safe storage. Ciphertexts are encoded with a URL-safe variant of Base64 and contain an authenticated header which contains version metadata (for forward compatibility).

Decryption looks exactly like you'd expect.: plaintext = Symmetric.decrypt(cipher, key)

What about asymmetric (public key) encryption?

You've got options!

  • Authenticated Public-Key Encryption: Asymmetric.encrypt(plaintext, alicePublic, bobSecret) and Asymmetric.decrypt(ciphertext, aliceSecret, bobPublic).
  • Anonymous Public-Key Encryption: Asymmetric.seal(plaintext, alicePublic) and Asymmetric.unseal(ciphertext, aliceSecret).

No boilerplate code needed. Just simple APIs and portable ciphertexts that won't get chewed up by binary-unsafe transport/storage mechanisms.

What else does Dhole make easy?

Digital Signatures

The API is as simple and minimalistic as you'd expect.

  • signature = Asymmetric.sign(message, secretKey)
  • Asymmetric.verify(message, publicKey, signature)

Digital signatures are RFC 8032-compatible Ed25519 with an additional 32 bytes of randomness (to mitigate fault attacks at a protocol level).

Symmetric-key authentication

No surprises here either.

  • tag = Symmetric.auth(message, secretKey)
  • Symmetric.verify(message, sharedKey, tag)
Password storage

Secure and forward-compatible password hashing combined with symmetric encryption.

const {
    Password,
    SymmetricKey
} = require('dhole-crypto');

(async function () {
    /** @var {SymmetricKey} symmetricKey */
    let pwHandler = new Password(symmetricKey);
    let password = 'correct horse battery staple';
    let pwhash = await pwHandler.hash(password);

    if (await pwHandler.verify(password, pwhash)) {
        if (await pwHandler.needsRehash(pwhash)) {
            pwhash = await pwHandler.hash(password);
            // Store updated pwhash in database...
        }
        console.log('Access granted.');
    }
})();

The hash(), needsRehash(), and verify() API was inspired by PHP's design.

For security people: Passwords are hashed with Argon2id (and salted), then encrypted with XChaCha20-Poly1305. If you keep your encryption key on separate hardware from the database server, the encryption adds a security gain above just storing plaintext hashes.

Key management

Dhole works on key objects rather than binary strings. To simplify various use-cases, we provide a Keyring API that allows keys to be serialized as binary-safe strings and loaded from said strings.

const {
    AsymmetricSecretKey,
    Keyring,
    SymmetricKey
} = require('dhole-crypto');

(async function () {
    let foxSecret = await AsymmetricSecretKey.generate();
    let foxPublic = foxSecret.getPublicKey();
    let symmetric = await SymmetricKey.generate();

    // Load a serializer
    let ring = new Keyring();

    // Serialize to string
    let sk = await ring.save(foxSecret);
    let pk = await ring.save(foxPublic);
    let key = await ring.save(symmetric);

    // Load from string
    let loadSk = await ring.load(sk);
    let loadPk = await ring.load(pk);
    let loadSym = await ring.load(key);
})();

Keywrap support is also included. If you pass a SymmetricKey to the Keyring constructor, it will encrypt all serialized keys.

What is a dhole anyway?

From the San Diego Zoo website:

Dholes are dogs! The dhole (pronounced "dole") is also known as the Asiatic wild dog, red dog, and whistling dog. It is about the size of a German shepherd but looks more like a long-legged fox. This highly elusive and skilled jumper is classified with wolves, coyotes, jackals, and foxes in the taxonomic family Canidae.

Their moniker "whistling dog" comes from their use of high-pitched whistles to communicate while hunting. They're totally bad-ass, and their communication strategy is a good analogy for effective encryption in the animal kingdom.

They're also of personal significance to Soatok, the author of this library.

Yes, this was made by a furry.

Other Inquiries

Language Support

If you'd like Dhole to be implemented in a programming language you want to use, feel free to contact Soatok.

If you'd like to do this work yourself, we have test vectors available. For a detailed unit test example, please refer to this directory.

Commercial Licenses

Dhole is published under the very permissive ISC license. You can freely use Dhole in your own works at no cost to you.

If you'd like to support Dhole's development, Soatok is willing to offer you a commercial license. His up-to-date contact information is available on this page.

Other Ways to Support Development