Add benchmark and examples
diff --git a/benchmark/bench_d_schnorr.c b/benchmark/bench_d_schnorr.c
index edf4226..9523191 100644
--- a/benchmark/bench_d_schnorr.c
+++ b/benchmark/bench_d_schnorr.c
@@ -27,6 +27,10 @@
 #define MIN_TIME    5.0
 #define MIN_ITERS   10
 
+// ID and AD
+char *ID_str = "unique_identifier_123";
+char *AD_hex = "d7d3155616778fb436a1eb2070892205";
+
 // Proof input V = s.R + l.G
 char *S_hex = "803ccd21cddad626e15f21b1ad787949e9beef08e6e68a9e00df59dec16ed290";
 char *L_hex = "0c5afd75c3d8255e6c91dc4aac664337e1a87f74b40f35746fb8a81311715b31";
@@ -57,6 +61,12 @@
     char v[SFS_SECP256K1+1];
     octet V = {0, sizeof(v), v};
 
+    char id[32];
+    octet ID = {0, sizeof(id), id};
+
+    char ad[32];
+    octet AD = {0, sizeof(ad), ad};
+
     char a[SGS_SECP256K1];
     octet A = {0, sizeof(a), a};
 
@@ -76,6 +86,9 @@
     octet U = {0, sizeof(u), u};
 
     // Load values
+    OCT_jstring(&ID, ID_str);
+    OCT_fromHex(&AD, AD_hex);
+
     OCT_fromHex(&S, S_hex);
     OCT_fromHex(&L, L_hex);
     OCT_fromHex(&R, R_hex);
@@ -113,7 +126,7 @@
     start=clock();
     do
     {
-        SCHNORR_D_challenge(&R, &V, &C, &E);
+        SCHNORR_D_challenge(&R, &V, &C, &ID, &AD, &E);
         iterations++;
         elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
     }
diff --git a/benchmark/bench_factoring_zk.c b/benchmark/bench_factoring_zk.c
index 0a7445c..fa46877 100644
--- a/benchmark/bench_factoring_zk.c
+++ b/benchmark/bench_factoring_zk.c
@@ -27,6 +27,9 @@
 #define MIN_TIME 5.0
 #define MIN_ITERS 10
 
+char *ID_str = "unique_identifier_123";
+char *AD_hex = "d7d3155616778fb436a1eb2070892205";
+
 char *P_hex = "e008507e09c24d756280f3d94912fb9ac16c0a8a1757ee01a350736acfc7f65880f87eca55d6680253383fc546d03fd9ebab7d8fa746455180888cb7c17edf58d3327296468e5ab736374bc9a0fa02606ed5d3a4a5fb1677891f87fbf3c655c3e0549a86b17b7ddce07c8f73e253105e59f5d3ed2c7ba5bdf8495df40ae71a7f";
 char *Q_hex = "dbffe278edd44c2655714e5a4cc82e66e46063f9ab69df9d0ed20eb3d7f2d8c7d985df71c28707f32b961d160ca938e9cf909cd77c4f8c630aec34b67714cbfd4942d7147c509db131bc2d6a667eb30df146f64b710f8f5247848b0a75738a38772e31014fd63f0b769209928d586499616dcc90700b393156e12eea7e15a835";
 char *N_hex = "c0870b552afb6c8c09f79e39ad6ca17ca93085c2cd7a726ade69574961ff9ce8ad33c7dda2e0703a3b0010c2e5bb7552c74164ce8dd011d85e5969090df53fe10e39cbe530704da32ff07228a6b6da34a5929e8a231c3080d812dc6e93affd81682339a6aee192927c582da8941bebf46e13c4ea3918a1477951fa66d367e70d8551b1869316d48317e0702d7bce242a326000f3dc763c44eba2044a1df713a94c1339edd464b145dcadf94e6e61be73dc270c878e1a28be720df2209202d00e101c3b255b757eaf547acd863d51eb676b851511b3dadeda926714719dceddd3af7908893ae65f2b95ee5c4d36cc6862cbe6886a62d7c1e2d0db48c399a6d44b";
@@ -49,6 +52,12 @@
     char n[FS_2048];
     octet N = {0, sizeof(n), n};
 
+    char id[32];
+    octet ID = {0, sizeof(id), id};
+
+    char ad[32];
+    octet AD = {0, sizeof(ad), ad};
+
     char r[FS_2048];
     octet R = {0, sizeof(r), r};
 
@@ -59,6 +68,9 @@
     octet Y = {0, sizeof(y), y};
 
     // Load values
+    OCT_jstring(&ID, ID_str);
+    OCT_fromHex(&AD, AD_hex);
+
     OCT_fromHex(&P, P_hex);
     OCT_fromHex(&Q, Q_hex);
     OCT_fromHex(&N, N_hex);
@@ -73,7 +85,7 @@
     start = clock();
     do
     {
-        FACTORING_ZK_prove(NULL, &P, &Q, &R, &E, &Y);
+        FACTORING_ZK_prove(NULL, &P, &Q, &ID, &AD, &R, &E, &Y);
         iterations++;
         elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
     }
@@ -87,7 +99,7 @@
     start = clock();
     do
     {
-        rc = FACTORING_ZK_verify(&N, &E, &Y);
+        rc = FACTORING_ZK_verify(&N, &E, &Y, &ID, &AD);
         iterations++;
         elapsed = (clock() - start) / (double)CLOCKS_PER_SEC;
     }
diff --git a/benchmark/bench_schnorr.c b/benchmark/bench_schnorr.c
index 91185ff..49ae5da 100644
--- a/benchmark/bench_schnorr.c
+++ b/benchmark/bench_schnorr.c
@@ -27,6 +27,9 @@
 #define MIN_TIME    5.0
 #define MIN_ITERS   10
 
+char *ID_str = "unique_identifier_123";
+char *AD_hex = "d7d3155616778fb436a1eb2070892205";
+
 char *R_hex = "803ccd21cddad626e15f21b1ad787949e9beef08e6e68a9e00df59dec16ed290";
 char *X_hex = "fab4ce512dff74bd9c71c89a14de5b877af45dca0329ee3fcb72611c0784fef3";
 char *V_hex = "032cf4b348c9d00718f01ed98923e164df53b5e8bc4c2250662ed2df784e1784f4";
@@ -45,6 +48,12 @@
     char v[SFS_SECP256K1+1];
     octet V = {0, sizeof(v), v};
 
+    char id[32];
+    octet ID = {0, sizeof(id), id};
+
+    char ad[32];
+    octet AD = {0, sizeof(ad), ad};
+
     char r[SGS_SECP256K1];
     octet R = {0, sizeof(r), r};
 
@@ -58,6 +67,9 @@
     octet P = {0, sizeof(p), p};
 
     // Load values
+    OCT_jstring(&ID, ID_str);
+    OCT_fromHex(&AD, AD_hex);
+
     OCT_fromHex(&R, R_hex);
     OCT_fromHex(&X, X_hex);
     OCT_fromHex(&V, V_hex);
@@ -85,7 +97,7 @@
     start=clock();
     do
     {
-        SCHNORR_challenge(&V, &C, &E);
+        SCHNORR_challenge(&V, &C, &ID, &AD, &E);
         iterations++;
         elapsed=(clock()-start)/(double)CLOCKS_PER_SEC;
     }
diff --git a/examples/example_d_schnorr.c b/examples/example_d_schnorr.c
index 552f157..cca1a59 100644
--- a/examples/example_d_schnorr.c
+++ b/examples/example_d_schnorr.c
@@ -44,6 +44,12 @@
     char v[SFS_SECP256K1+1];
     octet V = {0, sizeof(v), v};
 
+    char id[32];
+    octet ID = {0, sizeof(id), id};
+
+    char ad[32];
+    octet AD = {0, sizeof(ad), ad};
+
     char a[SGS_SECP256K1];
     octet A = {0, sizeof(a), a};
 
@@ -71,6 +77,10 @@
     ECP_SECP256K1_generator(&G);
     ECP_SECP256K1_generator(&ECPR);
 
+    // Generate ID and AD
+    OCT_rand(&ID, &RNG, ID.len);
+    OCT_rand(&AD, &RNG, AD.len);
+
     // Generate public R
     BIG_256_56_randomnum(r, q, &RNG);
     ECP_SECP256K1_mul(&ECPR, r);
@@ -91,14 +101,18 @@
     ECP_SECP256K1_toOctet(&V, &G, 1);
 
     printf("Double Schnorr's Proof of knowledge of a DLOG. V = s.R + l.G\n");
-    printf("\ts = ");
+    printf("\ts  = ");
     OCT_output(&S);
-    printf("\tl = ");
+    printf("\tl  = ");
     OCT_output(&L);
-    printf("\tR = ");
+    printf("\tR  = ");
     OCT_output(&R);
-    printf("\tV = ");
+    printf("\tV  = ");
     OCT_output(&V);
+    printf("\tID = ");
+    OCT_output(&ID);
+    printf("\tAD = ");
+    OCT_output(&AD);
 
     printf("\nGenerate a commitment C = a.R + b.G\n");
     rc = SCHNORR_D_commit(&RNG, &R, &A, &B, &C);
@@ -116,7 +130,7 @@
     OCT_output(&C);
 
     printf("\nGenerate a challenge from the public parameters\n");
-    SCHNORR_D_challenge(&R, &V, &C, &E);
+    SCHNORR_D_challenge(&R, &V, &C, &ID, &AD, &E);
 
     printf("\te = ");
     OCT_output(&E);
diff --git a/examples/example_factoring_zk.c b/examples/example_factoring_zk.c
index 3a4741a..f36aaf3 100644
--- a/examples/example_factoring_zk.c
+++ b/examples/example_factoring_zk.c
@@ -36,6 +36,12 @@
     char n[FS_2048];
     octet N = {0, sizeof(n), n};
 
+    char id[32];
+    octet ID = {0, sizeof(id), id};
+
+    char ad[32];
+    octet AD = {0, sizeof(ad), ad};
+
     char e[FACTORING_ZK_B];
     octet E = {0, sizeof(e), e};
 
@@ -47,6 +53,10 @@
     csprng RNG;
     RAND_seed(&RNG, 32, seed);
 
+    // Generate ID and AD
+    OCT_rand(&ID, &RNG, ID.len);
+    OCT_rand(&AD, &RNG, AD.len);
+
     // Load RSA modulus
     OCT_fromHex(&P, P_hex);
     OCT_fromHex(&Q, Q_hex);
@@ -62,7 +72,7 @@
 
     // ZK proof
     printf("\nGenerate proof\n");
-    FACTORING_ZK_prove(&RNG, &P, &Q, NULL, &E, &Y);
+    FACTORING_ZK_prove(&RNG, &P, &Q, &ID, &AD, NULL, &E, &Y);
 
     printf("\tE = ");
     OCT_output(&E);
@@ -73,7 +83,7 @@
 
     // Verify proof
     printf("\nVerify prove (E, Y) for integer N\n");
-    if(FACTORING_ZK_verify(&N, &E, &Y) == FACTORING_ZK_OK)
+    if(FACTORING_ZK_verify(&N, &E, &Y, &ID, &AD) == FACTORING_ZK_OK)
     {
         printf("\tSuccess!\n");
     }
diff --git a/examples/example_full.c b/examples/example_full.c
index c45dd69..0727b5f 100644
--- a/examples/example_full.c
+++ b/examples/example_full.c
@@ -49,6 +49,10 @@
 char *B_P_hex = "efa013403e9ea93daf97f1dd4b42eba602410e048852b20cd448d51793ac2ee725e79eaac82d22cdd6cfb966cba62904a26da47d7a6085fba194e24eddbc92f66a0bd990c8cb9abf98fff48d52d33215d68f6f030cd9440f85987b2ab44332646ea38bc218fedc83a24cf57b7615c0fc9289778f7ba60f4ed71c7c3c571054fb";
 char *B_Q_hex = "f95b9d7027be3950de9a050eba7301d5234ad89bf260d47e94a724b49759ab9a8fca22fe484e5e5ddf0845734cd3322d271e146e1e6eed6e16a2740c294097cd65deeacbfa563cce42065720836d421bcfd73c6dcab3aa0c4d480ac445e9ba11fb7825559b29ab4f9f6f079acbd0dc5c38702f386b3c95107540195a4508401b";
 
+// Unique identifiers for actors
+char *alice_id = "alice_unique_id";
+char *bob_id   = "bob_unique_id";
+
 int generate_key_material(csprng *RNG, key_material *km, octet *P, octet *Q)
 {
     int rc;
@@ -118,7 +122,7 @@
     return MPC_OK;
 }
 
-void key_material_zkp(csprng *RNG, key_material *km, octet *C, octet *P, octet *E, octet *Y)
+void key_material_zkp(csprng *RNG, key_material *km, octet *C, octet *P, octet *E, octet *Y, octet *ID, octet *AD)
 {
     char r[EGS_SECP256K1];
     octet R = {0, sizeof(r), r};
@@ -135,7 +139,7 @@
     /* Prove knowledge of DLOG PK = s.G */
 
     SCHNORR_commit(RNG, &R, C);
-    SCHNORR_challenge(km->PK, C, &S_E);
+    SCHNORR_challenge(km->PK, C, ID, AD, &S_E);
     SCHNORR_prove(&R, &S_E, km->SK, P);
 
     printf("\n\tProve knowledge of ECDSA sk\n");
@@ -145,6 +149,10 @@
     OCT_output(&S_E);
     printf("\t\tP = ");
     OCT_output(P);
+    printf("\t\tID = ");
+    OCT_output(ID);
+    printf("\t\tAD = ");
+    OCT_output(AD);
 
     OCT_clear(&R);
 
@@ -153,7 +161,7 @@
     FF_2048_toOctet(&M_P, km->paillier_sk.p, HFLEN_2048);
     FF_2048_toOctet(&M_Q, km->paillier_sk.q, HFLEN_2048);
 
-    FACTORING_ZK_prove(RNG, &M_P, &M_Q, NULL, E, Y);
+    FACTORING_ZK_prove(RNG, &M_P, &M_Q, ID, AD, NULL, E, Y);
 
     printf("\n\tProve knowledge of the Paillier Secret Key\n");
     printf("\t\tE = ");
@@ -165,7 +173,7 @@
     OCT_clear(&M_Q);
 }
 
-int key_material_verify_zkp(key_material *km, octet *C, octet *P, octet *E, octet *Y)
+int key_material_verify_zkp(key_material *km, octet *C, octet *P, octet *E, octet *Y, octet *ID, octet *AD)
 {
     int rc;
 
@@ -178,7 +186,7 @@
     /* Verify Schnorr Proof for counterparty PK */
     printf("\n\tVerify Proof of knowledge of ECDSA sk\n");
 
-    SCHNORR_challenge(km->CPK, C, &S_E);
+    SCHNORR_challenge(km->CPK, C, ID, AD, &S_E);
     rc = SCHNORR_verify(km->CPK, C, &S_E, P);
     if (rc != SCHNORR_OK)
     {
@@ -192,7 +200,7 @@
 
     PAILLIER_PK_toOctet(&N, &km->paillier_cpk);
 
-    rc = FACTORING_ZK_verify(&N, E, Y);
+    rc = FACTORING_ZK_verify(&N, E, Y, ID, AD);
     if (rc != FACTORING_ZK_OK)
     {
         return rc;
@@ -206,7 +214,8 @@
 /* Key Setup.
  *
  * Step 1.  Generate ECDSA key pair, Paillier key pair and Bit Commitment modulus
- * Setp 1A. Commit to ECDSA public Key, generating commitment and decommitment values.
+ * Setp 1A. Commit to ECDSA public Key, generating commitment and decommitment values. Send nonce
+ *          for liveliness.
  * Step 1B. Transmit Paillier public key, Bit Commitment public modulus and the commitment value
  *
  * Upon receipt of the commitment value from the other party:
@@ -227,6 +236,15 @@
     char safe_q[HFS_2048];
     octet SAFE_Q = {0, sizeof(safe_q), safe_q};
 
+    // Octets for NIZKP ID and AD
+    char id[2][32];
+    octet A_ID = {0, sizeof(id[0]), id[0]};
+    octet B_ID = {0, sizeof(id[1]), id[1]};
+
+    char ad[2][32];
+    octet A_AD = {0, sizeof(ad[0]), ad[0]};
+    octet B_AD = {0, sizeof(ad[1]), ad[1]};
+
     // Octets for Non Malleable Commitments
     char commit_r[2][SHA256];
     octet A_COMMIT_R = {0, sizeof(commit_r[0]), commit_r[0]};
@@ -257,10 +275,13 @@
     char paillier_pk[FS_2048];
     octet PAILLIER_PK = {0, sizeof(paillier_pk), paillier_pk};
 
-    /* Alice - generate key material and commitment */
+    /* Alice - generate key material, commitment and AD*/
 
     printf("\n[Alice] Generate key material\n");
 
+    OCT_jstring(&A_ID, alice_id);
+    OCT_rand(&B_AD, RNG, B_AD.len);
+
     OCT_fromHex(&SAFE_P, A_P_hex);
     OCT_fromHex(&SAFE_Q, A_Q_hex);
 
@@ -287,10 +308,13 @@
     PAILLIER_PK_fromOctet(&bob_km->paillier_cpk, &PAILLIER_PK);
     COMMITMENTS_BC_export_public_modulus(&bob_km->bc_cpm, &alice_km->bc_sm);
 
-    /* Bob - generate key material and commitment */
+    /* Bob - generate key material, commitment and AD */
 
     printf("\n[Bob] Generate key material\n");
 
+    OCT_jstring(&B_ID, bob_id);
+    OCT_rand(&A_AD, RNG, A_AD.len);
+
     OCT_fromHex(&SAFE_P, B_P_hex);
     OCT_fromHex(&SAFE_Q, B_Q_hex);
 
@@ -372,21 +396,21 @@
     /* Alice - generate key material ZKP */
 
     printf("\n[Alice] Prove correctness of key material\n");
-    key_material_zkp(RNG, alice_km, &A_KZKP_C, &A_KZKP_P, &A_KZKP_E, &A_KZKP_Y);
+    key_material_zkp(RNG, alice_km, &A_KZKP_C, &A_KZKP_P, &A_KZKP_E, &A_KZKP_Y, &A_ID, &A_AD);
 
     printf("\n[Alice] Transmit C, P, E, Y\n");
 
     /* Bob - generate key material ZKP */
 
     printf("\n[Bob] Prove correctness of key material\n");
-    key_material_zkp(RNG, bob_km, &B_KZKP_C, &B_KZKP_P, &B_KZKP_E, &B_KZKP_Y);
+    key_material_zkp(RNG, bob_km, &B_KZKP_C, &B_KZKP_P, &B_KZKP_E, &B_KZKP_Y, &B_ID, &B_AD);
 
     printf("\n[Bob] Transmit C, P, E, Y\n");
 
     /* Alice/Bob - verify key material ZKP */
 
     printf("\n[Alice] Verify Key Material ZKP\n");
-    rc = key_material_verify_zkp(alice_km, &B_KZKP_C, &B_KZKP_P, &B_KZKP_E, &B_KZKP_Y);
+    rc = key_material_verify_zkp(alice_km, &B_KZKP_C, &B_KZKP_P, &B_KZKP_E, &B_KZKP_Y, &B_ID, &B_AD);
     if (rc != MPC_OK)
     {
         printf("\n FAILURE invalid ZKP for Bob key material. rc %d\n", rc);
@@ -394,7 +418,7 @@
     }
 
     printf("\n[Bob] Verify Key Material ZKP\n");
-    rc = key_material_verify_zkp(bob_km, &A_KZKP_C, &A_KZKP_P, &A_KZKP_E, &A_KZKP_Y);
+    rc = key_material_verify_zkp(bob_km, &A_KZKP_C, &A_KZKP_P, &A_KZKP_E, &A_KZKP_Y, &A_ID, &A_AD);
     if (rc != MPC_OK)
     {
         printf("\n FAILURE invalid ZKP for Alice key material. rc %d\n", rc);
@@ -763,7 +787,8 @@
 /* Phase 5 interactive proof of consistency of the signature shares
  *
  * Step 1.  Each player generates random values phi and rho and commitments
- *          V, A and commits to the value (V, A)
+ *          V, A and commits to the value (V, A). It also generates a nonce
+ *          for liveliness
  * Step 2.  The values (V, A) are decommited and the players prove they are
  *          well formed
  * Step 2A. The well formedness proofs are transmitted and verified
@@ -803,6 +828,15 @@
     octet T2 = {0, sizeof(t[1]), t[1]};
     octet *T[2] = {&T1, &T2};
 
+    // Octets for NIZKP ID and AD
+    char id[2][32];
+    octet A_ID = {0, sizeof(id[0]), id[0]};
+    octet B_ID = {0, sizeof(id[1]), id[1]};
+
+    char ad[2][32];
+    octet A_AD = {0, sizeof(ad[0]), ad[0]};
+    octet B_AD = {0, sizeof(ad[1]), ad[1]};
+
     // Octets for Non Malleable Commitments
     char double_ecp[2 * EFS_SECP256K1 + 2];
     octet DOUBLE_ECP = {0, sizeof(double_ecp), double_ecp};
@@ -857,6 +891,9 @@
 
     printf("\n[Alice] Generate commitment (V, A) for Phase5 proof and nm commit to it\n");
 
+    OCT_jstring(&A_ID, alice_id);
+    OCT_rand(&B_AD, RNG, B_AD.len);
+
     rc = MPC_PHASE5_commit(RNG, RP1, S1, &PHI1, &RHO1, &V1, &A1);
     if (rc != MPC_OK)
     {
@@ -891,6 +928,9 @@
 
     printf("\n[Bob] Generate commitment (V, A) for Phase5 proof and nm commit to it\n");
 
+    OCT_jstring(&B_ID, bob_id);
+    OCT_rand(&A_AD, RNG, A_AD.len);
+
     rc = MPC_PHASE5_commit(RNG, RP2, S2, &PHI2, &RHO2, &V2, &A2);
     if (rc != MPC_OK)
     {
@@ -956,7 +996,7 @@
     printf("\n[Alice] Generate DSchnorr Proof for PHI, SK, V\n");
 
     SCHNORR_D_commit(RNG, RP1, &SCHNORR_A1, &SCHNORR_B1, &SCHNORR_D1);
-    SCHNORR_D_challenge(RP1, &V1, &SCHNORR_D1, &SCHNORR_E1);
+    SCHNORR_D_challenge(RP1, &V1, &SCHNORR_D1, &A_ID, &A_AD, &SCHNORR_E1);
     SCHNORR_D_prove(&SCHNORR_A1, &SCHNORR_B1, &SCHNORR_E1, S1, &PHI1, &SCHNORR_T1, &SCHNORR_U1);
 
     printf("\tD = ");
@@ -971,7 +1011,7 @@
     printf("\n[Alice] Generate Schnorr Proof for A, RHO\n");
 
     SCHNORR_commit(RNG, &SCHNORR_R1, &SCHNORR_C1);
-    SCHNORR_challenge(&A1, &SCHNORR_C1, &SCHNORR_E1);
+    SCHNORR_challenge(&A1, &SCHNORR_C1, &A_ID, &A_AD, &SCHNORR_E1);
     SCHNORR_prove(&SCHNORR_R1, &SCHNORR_E1, &RHO1, &SCHNORR_P1);
 
     printf("\tC = ");
@@ -986,7 +1026,7 @@
     printf("\n[Bob] Generate DSchnorr Proof for PHI, SK, V\n");
 
     SCHNORR_D_commit(RNG, RP2, &SCHNORR_A2, &SCHNORR_B2, &SCHNORR_D2);
-    SCHNORR_D_challenge(RP2, &V2, &SCHNORR_D2, &SCHNORR_E2);
+    SCHNORR_D_challenge(RP2, &V2, &SCHNORR_D2, &B_ID, &B_AD, &SCHNORR_E2);
     SCHNORR_D_prove(&SCHNORR_A2, &SCHNORR_B2, &SCHNORR_E2, S2, &PHI2, &SCHNORR_T2, &SCHNORR_U2);
 
     printf("\tC = ");
@@ -1001,7 +1041,7 @@
     printf("\n[Bob] Generate Schnorr Proof for A, RHO\n");
 
     SCHNORR_commit(RNG, &SCHNORR_R2, &SCHNORR_C2);
-    SCHNORR_challenge(&A2, &SCHNORR_C2, &SCHNORR_E2);
+    SCHNORR_challenge(&A2, &SCHNORR_C2, &B_ID, &B_AD, &SCHNORR_E2);
     SCHNORR_prove(&SCHNORR_R2, &SCHNORR_E2, &RHO2, &SCHNORR_P2);
 
     printf("\tC = ");
@@ -1017,7 +1057,7 @@
 
     printf("\tVerify Proof for V\n");
 
-    SCHNORR_D_challenge(RP2, &V2, &SCHNORR_D2, &SCHNORR_E2);
+    SCHNORR_D_challenge(RP2, &V2, &SCHNORR_D2, &B_ID, &B_AD, &SCHNORR_E2);
     printf("\t\tE = ");
     OCT_output(&SCHNORR_E2);
 
@@ -1032,7 +1072,7 @@
 
     printf("\n\tVerify Proof for A\n");
 
-    SCHNORR_challenge(&A2, &SCHNORR_C2, &SCHNORR_E2);
+    SCHNORR_challenge(&A2, &SCHNORR_C2, &B_ID, &B_AD, &SCHNORR_E2);
     printf("\t\tE = ");
     OCT_output(&SCHNORR_E2);
 
@@ -1049,7 +1089,7 @@
 
     printf("\tVerify Proof for V\n");
 
-    SCHNORR_D_challenge(RP1, &V1, &SCHNORR_D1, &SCHNORR_E1);
+    SCHNORR_D_challenge(RP1, &V1, &SCHNORR_D1, &A_ID, &A_AD, &SCHNORR_E1);
     printf("\t\tE = ");
     OCT_output(&SCHNORR_E1);
 
@@ -1064,7 +1104,7 @@
 
     printf("\n\tVerify Proof for A\n");
 
-    SCHNORR_challenge(&A1, &SCHNORR_C1, &SCHNORR_E1);
+    SCHNORR_challenge(&A1, &SCHNORR_C1, &A_ID, &A_AD, &SCHNORR_E1);
     printf("\t\tE = ");
     OCT_output(&SCHNORR_E1);
 
@@ -1180,6 +1220,7 @@
 /* Signature.
  *
  * Step 1.  Each player generates random k, gamma and commits to gamma.G
+ *          It also generates a nonce for liveliness
  * Step 2.  Each player performs a MTA with shares k_i, gamma_j
  * Step 2A. Each player performs a MTAWC with shares k_i, sk_j
  * Step 3.  Each player sums the output of the MTA runs with the product k_i * gamma_i
@@ -1212,6 +1253,15 @@
     octet GAMMAPT1 = {0, sizeof(gammapt[0]), gammapt[0]};
     octet GAMMAPT2 = {0, sizeof(gammapt[1]), gammapt[1]};
 
+    // Octets for NIZKP ID and AD
+    char id[2][32];
+    octet A_ID = {0, sizeof(id[0]), id[0]};
+    octet B_ID = {0, sizeof(id[1]), id[1]};
+
+    char ad[2][32];
+    octet A_AD = {0, sizeof(ad[0]), ad[0]};
+    octet B_AD = {0, sizeof(ad[1]), ad[1]};
+
     // Octets for Non Malleable Commitments
     char commit_r[2][SHA256];
     octet A_COMMIT_R = {0, sizeof(commit_r[0]), commit_r[0]};
@@ -1288,6 +1338,9 @@
 
     printf("\n[Alice] Generate random K and GAMMA and commit to GAMMA.G\n");
 
+    OCT_jstring(&A_ID, alice_id);
+    OCT_rand(&B_AD, RNG, B_AD.len);
+
     BIG_256_56_randomnum(k1, q, RNG);
     BIG_256_56_toBytes(K1.val, k1);
     K1.len = EGS_SECP256K1;
@@ -1318,6 +1371,9 @@
 
     printf("\n[Bob] Generate random K and GAMMA and commit to GAMMA.G\n");
 
+    OCT_jstring(&B_ID, bob_id);
+    OCT_rand(&A_AD, RNG, A_AD.len);
+
     BIG_256_56_randomnum(k2, q, RNG);
     BIG_256_56_toBytes(K2.val, k2);
     K2.len = EGS_SECP256K1;
@@ -1403,7 +1459,7 @@
     printf("\n[Alice] Generate Schnorr Proof for DLOG GAMMA, GAMMA.G\n");
 
     SCHNORR_commit(RNG, &SCHNORR_R1, &SCHNORR_C1);
-    SCHNORR_challenge(&GAMMAPT1, &SCHNORR_C1, &SCHNORR_E1);
+    SCHNORR_challenge(&GAMMAPT1, &SCHNORR_C1, &A_ID, &A_AD, &SCHNORR_E1);
     SCHNORR_prove(&SCHNORR_R1, &SCHNORR_E1, &GAMMA1, &SCHNORR_P1);
 
     printf("\tC = ");
@@ -1420,7 +1476,7 @@
     printf("\n[Bob] Generate Schnorr Proof for DLOG GAMMA, GAMMA.G\n");
 
     SCHNORR_commit(RNG, &SCHNORR_R2, &SCHNORR_C2);
-    SCHNORR_challenge(&GAMMAPT2, &SCHNORR_C2, &SCHNORR_E2);
+    SCHNORR_challenge(&GAMMAPT2, &SCHNORR_C2, &B_ID, &B_AD, &SCHNORR_E2);
     SCHNORR_prove(&SCHNORR_R2, &SCHNORR_E2, &GAMMA2, &SCHNORR_P2);
 
     printf("\tC = ");
@@ -1448,7 +1504,7 @@
     printf("\n[Alice] Verify Schnorr Proof for GAMMA.G\n");
 
     OCT_clear(&SCHNORR_E2);
-    SCHNORR_challenge(&GAMMAPT2, &SCHNORR_C2, &SCHNORR_E2);
+    SCHNORR_challenge(&GAMMAPT2, &SCHNORR_C2, &B_ID, &B_AD, &SCHNORR_E2);
 
     printf("\tE = ");
     OCT_output(&SCHNORR_E2);
@@ -1478,7 +1534,7 @@
     printf("\n[Bob] Verify Schnorr Proof for GAMMA.G\n");
 
     OCT_clear(&SCHNORR_E1);
-    SCHNORR_challenge(&GAMMAPT1, &SCHNORR_C1, &SCHNORR_E1);
+    SCHNORR_challenge(&GAMMAPT1, &SCHNORR_C1, &A_ID, &A_AD, &SCHNORR_E1);
 
     printf("\tE = ");
     OCT_output(&SCHNORR_E1);
diff --git a/examples/example_schnorr.c b/examples/example_schnorr.c
index 6ecc719..3dad6e8 100644
--- a/examples/example_schnorr.c
+++ b/examples/example_schnorr.c
@@ -35,6 +35,12 @@
     char v[SFS_SECP256K1+1];
     octet V = {0, sizeof(v), v};
 
+    char id[32];
+    octet ID = {0, sizeof(id), id};
+
+    char ad[32];
+    octet AD = {0, sizeof(ad), ad};
+
     char r[SGS_SECP256K1];
     octet R = {0, sizeof(r), r};
 
@@ -52,6 +58,10 @@
     csprng RNG;
     RAND_seed(&RNG, 32, seed);
 
+    // Generate ID and AD
+    OCT_rand(&ID, &RNG, ID.len);
+    OCT_rand(&AD, &RNG, AD.len);
+
     // Generate DLOG
     BIG_256_56_rcopy(q, CURVE_Order_SECP256K1);
     BIG_256_56_randomnum(x, q, &RNG);
@@ -79,7 +89,7 @@
     OCT_output(&C);
 
     printf("\nGenerate a challenge from the public parameters\n");
-    SCHNORR_challenge(&V, &C, &E);
+    SCHNORR_challenge(&V, &C, &ID, &AD, &E);
 
     printf("\te = ");
     OCT_output(&E);