// Path: app/src/main/java/pro/dbro/ble/crypto/SodiumShaker.java
// public class SodiumShaker {
//     private static final String TAG = "Identity";
// 
//     public static final int crypto_sign_PUBLICKEYBYTES = 32;
//     private static final int crypto_sign_SECRETKEYBYTES = 64;
//     public static final int crypto_sign_BYTES = 64;
// 
//     static {
//         // Load native libraries
//         NaCl.sodium();
//         // Initialize libsodium
//         if (Sodium.sodium_init() == -1) {
//             throw new IllegalStateException("sodiun_init failed!");
//         }
//     }
// 
//     public static KeyPair generateKeyPair() {
//         byte[] pk = new byte[crypto_sign_PUBLICKEYBYTES];
//         byte[] sk = new byte[crypto_sign_SECRETKEYBYTES];
// 
//         Sodium.crypto_sign_ed25519_keypair(pk, sk);
//         return new KeyPair(pk, sk);
//     }
// 
//     public static byte[] generateSignatureForMessage(@NonNull byte[] secret_key, @NonNull byte[] message, int message_len) {
//         if (secret_key.length != crypto_sign_SECRETKEYBYTES) throw new IllegalArgumentException("secret_key is incorrect length");
//         byte[] signature = new byte[crypto_sign_BYTES];
//         int[] signature_len = new int[0];
// 
//         Sodium.crypto_sign_ed25519_detached(signature, signature_len, message, message_len, secret_key);
// 
//         return signature;
//     }
// 
//     /**
//      * Very that signature and public_key verify message
//      *
//      * @param public_key the public key corresponding to signature
//      * @param signature the signature of message decipherable with public_key
//      * @param message the data with signature
//      */
//     public static boolean verifySignature(@NonNull byte[] public_key, @NonNull byte[] signature, @NonNull byte[] message) {
//         // Verify signature
// 
//         if (Sodium.crypto_sign_ed25519_verify_detached(signature, message, message.length, public_key) != 0) {
//             /* Incorrect signature! */
//             return false;
//         }
//         return true;
//     }
// }


import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Date;
import pro.dbro.ble.crypto.SodiumShaker;
            int readIndex     = 0;
            byte[] timestamp  = new byte[Long.SIZE / 8];
            byte[] public_key = new byte[SodiumShaker.crypto_sign_PUBLICKEYBYTES];
            byte[] alias      = new byte[ALIAS_LENGTH];
            byte[] signature  = new byte[SodiumShaker.crypto_sign_BYTES];
            byte[] signedData = new byte[IDENTITY_RESPONSE_LENGTH - SodiumShaker.crypto_sign_BYTES];

            readIndex += assertBufferVersion(identity, readIndex);
            readIndex += assertBufferType(identity, IdentityPacket.TYPE, readIndex);
            readIndex += getBytesFromBuffer(identity, timestamp, readIndex);
            readIndex += getBytesFromBuffer(identity, public_key, readIndex);
            readIndex += getBytesFromBuffer(identity, alias, readIndex);
            readIndex += getBytesFromBuffer(identity, signature, readIndex);

            System.arraycopy(identity, 0, signedData, 0, signedData.length);
            boolean validSignature = SodiumShaker.verifySignature(public_key, signature, signedData);
            if (!validSignature)
                throw new IllegalStateException("Identity signature does not match content!");

            return new IdentityPacket(public_key, new String(alias, "UTF-8"), getDateFromTimestampBuffer(timestamp), identity);
        } catch (UnsupportedEncodingException e) {
            Log.e(TAG, "Failed to generate Identity response. Are there invalid UTF-8 characters in the user alias?");
            e.printStackTrace();
        }
        return null;
    }

    @Nullable
    public MessagePacket deserializeMessageWithIdentity(@NonNull byte[] message, @NonNull IdentityPacket identity) {
        if (message.length != MESSAGE_RESPONSE_LENGTH)
// Path: app/src/main/java/pro/dbro/ble/crypto/SodiumShaker.java
// public class SodiumShaker {
//     private static final String TAG = "Identity";
// 
//     public static final int crypto_sign_PUBLICKEYBYTES = 32;
//     private static final int crypto_sign_SECRETKEYBYTES = 64;
//     public static final int crypto_sign_BYTES = 64;
// 
//     static {
//         // Load native libraries
//         NaCl.sodium();
//         // Initialize libsodium
//         if (Sodium.sodium_init() == -1) {
//             throw new IllegalStateException("sodiun_init failed!");
//         }
//     }
// 
//     public static KeyPair generateKeyPair() {
//         byte[] pk = new byte[crypto_sign_PUBLICKEYBYTES];
//         byte[] sk = new byte[crypto_sign_SECRETKEYBYTES];
// 
//         Sodium.crypto_sign_ed25519_keypair(pk, sk);
//         return new KeyPair(pk, sk);
//     }
// 
//     public static byte[] generateSignatureForMessage(@NonNull byte[] secret_key, @NonNull byte[] message, int message_len) {
//         if (secret_key.length != crypto_sign_SECRETKEYBYTES) throw new IllegalArgumentException("secret_key is incorrect length");
//         byte[] signature = new byte[crypto_sign_BYTES];
//         int[] signature_len = new int[0];
// 
//         Sodium.crypto_sign_ed25519_detached(signature, signature_len, message, message_len, secret_key);
// 
//         return signature;
//     }
// 
//     /**
//      * Very that signature and public_key verify message
//      *
//      * @param public_key the public key corresponding to signature
//      * @param signature the signature of message decipherable with public_key
//      * @param message the data with signature
//      */
//     public static boolean verifySignature(@NonNull byte[] public_key, @NonNull byte[] signature, @NonNull byte[] message) {
//         // Verify signature
// 
//         if (Sodium.crypto_sign_ed25519_verify_detached(signature, message, message.length, public_key) != 0) {
//             /* Incorrect signature! */
//             return false;
//         }
//         return true;
//     }
// }


// Path: app/src/main/java/pro/dbro/ble/protocol/BLEProtocol.java
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Date;
import pro.dbro.ble.crypto.SodiumShaker;

            int readIndex     = 0;
            byte[] timestamp  = new byte[Long.SIZE / 8];
            byte[] public_key = new byte[SodiumShaker.crypto_sign_PUBLICKEYBYTES];
            byte[] alias      = new byte[ALIAS_LENGTH];
            byte[] signature  = new byte[SodiumShaker.crypto_sign_BYTES];
            byte[] signedData = new byte[IDENTITY_RESPONSE_LENGTH - SodiumShaker.crypto_sign_BYTES];

            readIndex += assertBufferVersion(identity, readIndex);
            readIndex += assertBufferType(identity, IdentityPacket.TYPE, readIndex);
            readIndex += getBytesFromBuffer(identity, timestamp, readIndex);
            readIndex += getBytesFromBuffer(identity, public_key, readIndex);
            readIndex += getBytesFromBuffer(identity, alias, readIndex);
            readIndex += getBytesFromBuffer(identity, signature, readIndex);

            System.arraycopy(identity, 0, signedData, 0, signedData.length);
            boolean validSignature = SodiumShaker.verifySignature(public_key, signature, signedData);
            if (!validSignature)
                throw new IllegalStateException("Identity signature does not match content!");

            return new IdentityPacket(public_key, new String(alias, "UTF-8"), getDateFromTimestampBuffer(timestamp), identity);
        } catch (UnsupportedEncodingException e) {
            Log.e(TAG, "Failed to generate Identity response. Are there invalid UTF-8 characters in the user alias?");
            e.printStackTrace();
        }
        return null;
    }

    @Nullable
    public MessagePacket deserializeMessageWithIdentity(@NonNull byte[] message, @NonNull IdentityPacket identity) {
        if (message.length != MESSAGE_RESPONSE_LENGTH)
            throw new IllegalArgumentException(String.format("Message response is illegal length. Got %d expected %d", message.length, MESSAGE_RESPONSE_LENGTH));