Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libsodium support #2

Open
starekrow opened this issue Dec 9, 2017 · 3 comments
Open

libsodium support #2

starekrow opened this issue Dec 9, 2017 · 3 comments

Comments

@starekrow
Copy link
Owner

It would be nice to have optional support for libsodium as an alternative to the openssl extension, since libsodium is moving into core.

This could be hacked in place, or done by isolating the crypto use in CryptoKey. Either way might complicate cipher selection (needs research).

@KJLJon
Copy link
Contributor

KJLJon commented Dec 9, 2017

I think isolating the crypto and defaulting it to keep the package easy to use.

Let me know your thoughts, and I can work on implementing it

Here is a quick idea of what I am thinking

starekrow\lockbox\CryptoKey::Lock()

public function Lock( $message )
{
	if (!$this->data) {
		return false;
	}
	$cryptoLibrary = $this->getCryptoLibrary()
	$ciphertext_raw = $cryptoLibrary->encrypt($message, $this->getEncryptionKey());
	$hmac = $cryptoLibrary->generateHmac($ciphertext_raw, $this->getHmacKey());
	
	$ciphertext = base64_encode($iv.$hmac.$ciphertext_raw);
	
	return $ciphertext;
}

Interface so anyone can swap it out with their own implementation

I was debating if the encryption interface should be separate from the hmac interface.

interface CryptoLibraryInterface
{
    public function generateRandomBytes($length);

    public function encrypt($message);
    public function decrypt($message);

    public function setEncryptionCipher($cipher);
    public function getEncryptionCipher();
    public function getEncryptionKeyLength();
    public function getEncryptionKey();
    public function setEncryptionKey($key);

    public function generateHmac($message);
    public function isHmacValid($hmac, $message);

    public function setHmacAlgorithm($algo);
    public function getHmacAlgorithm();
    public function getHmacKeyLength();
    public function getHmacKey();
    public function setHmacKey($key);
}

Abstract class to implement common functions

abstract class AbstractCryptoLibrary implements CryptoLibraryInterface
{
    private $hmacKey;
    private $encryptionKey;
    private $cipher;
    
    public function setEncryptionCipher($cipher)
    {
        $this->cipher = $cipher;
    }
    
    public function getEncryptionCipher()
    {
        return $this->cipher;
    }
    
    public function setEncryptionKey($key)
    {
        $this->encryptionKey = $key;
    }
    
    public function getEncryptionKey()
    {
        if (isset($this->encryptionKey) === false) {
            $keyLength = $this->getEncryptionKeyLength();
            $key = $this->generateRandomBytes($keyLength);
            $this->setEncryptionKey($key);
        }
        
        return $this->encryptionKey;
    }
    
    public function isHmacValid($hmac, $message) {
        return $this->generateHmac($message) === $hmac;
    }
    
    //... rest of the common functions
}

OpenSSL version:

class OpenSSLCryptoLibrary extends AbstractCryptoLibrary
{
    public function generateRandomBytes($length)
    {
        return openssl_random_pseudo_bytes($length);
    }
    //... rest of the openssl specific functions
}

@starekrow
Copy link
Owner Author

Hmm. I think it would work out better to move the abstraction deeper, along these lines:

public function hash( $alg, $data );
public function hmac( $alg, $key, $data );
public function hkdf( $alg, $ikm, $len, $salt, $info );
public function encrypt( $alg, $key, $iv, $data );
public function decrypt( $alg, $key, $iv, $data );
public function hashcmp( $h1, $h2 );
public function random( $count );

Just a couple of assumptions (always binary strings, no wierd operational modes) cleans up the interface a lot. This then becomes a useful and clean building block for any number of related problems. It also leaves all the decisions of what to do inside CryptoKey instead of burying or splitting them.

Still need to work out how to handle algorithm names and discovery. It should be as permissive as possible without tolerating ambiguous input.

@starekrow
Copy link
Owner Author

FYI all, I'm building this out now. I'm going with a static API and a driver model, should be pretty slick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants