public static function sign(KeyPair $keyPair, $data, $algorithm = "keccak-512")
    {
        // shortcuts + use Buffer always
        $data = self::prepareInputBuffer($data);

        // shortcuts
        $secretKey = $keyPair->getSecretKey()->getBinary();
        $publicKey = $keyPair->getPublicKey()->getBinary();

        // use Buffer always
        $data = self::prepareInputBuffer($data);
        $message   = $data->getBinary();

        // step 1: crypto_hash_sha512(az, sk, 32);
        $privHash = self::hash($algorithm, $keyPair->getSecretKey()->getBinary(), true);

        // clamp bits for secret key + size secure
        $safePriv = Buffer::clampBits($privHash, 64);
        $bufferPriv = new Buffer($safePriv, 64);

        // step 2: generate `r` for scalar multiplication
        // `r = H(priv[32..64], data)`
        $hashData = $bufferPriv->slice(32)->getBinary() . $data->getBinary();
        $r = self::hash($algorithm, $hashData, true);

        // step 3: generate encoded version of `r` for `s` creation
        // `R = rB`
        $r = Ed25519::sc_reduce($r);
        $encodedR = Ed25519::ge_p3_tobytes(
            Ed25519::ge_scalarmult_base($r)
        );

        // step 4: create `s` with: encodedR || public key || data
        // `S = H(R,A,m)`
        $hramData = $encodedR . $publicKey . $data->getBinary();
        $hramHash = self::hash($algorithm, $hramData, true);

        // step 5: safe secret generation for `encodedS` which is the 
        // HIGH part of the signature in scalar form.
        // `S = H(R,A,m)a`
        // `S = (r + H(R,A,m)a)`
        $hram = Ed25519::sc_reduce($hramHash);
        $az   = $safePriv;
        $encodedS = Ed25519::sc_muladd($hram, $az, $r);

        // size secure encodedR and encodedS
        $bufferR = new Buffer($encodedR, 32);
        $bufferS = new Buffer($encodedS, 32);

        // step 6: signature[0:63] = r[0:31] || s[0:31]
        $sig = $bufferR->getBinary() . $bufferS->getBinary();

        // size secure signature
        $bufferSig = new Buffer($sig, 64);

        // step 7: check that signature is canonical
        // - s != 0
        // - ed25519 reduced `s` should be identical to `s`.
        // `S = (r + H(R,A,m)a) mod L`

        // make sure `s` != 0
        $sigZero = new Buffer(null, 32);
        if ($encodedS === $sigZero->getBinary()) {
            // re-issue signature because `s = 0`
            return false;
        }

        // create 64-bytes size-secured Buffer.
        $bufSignature = new Buffer($sig, 64);
        return $bufSignature;
    }